Allow Dual Screen Configurations for intel IGPs

improve xrandr_facts.py to match drm and xrandr outputs

TODO: use drm.edid_firmware kernel boot parameter to load EDID files
  on startup
This commit is contained in:
Alexander Grothe 2019-02-22 00:12:02 +01:00
parent c0dc185952
commit 08ed05594e
5 changed files with 966 additions and 593 deletions

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,26 @@
#+LATEX: \defaultfontfeatures{Ligatures=TeX}
#+LATEX_HEADER: \usepackage{parskip}
# #+LATEX_HEADER_EXTRA:
#+BEGIN_SRC latex
\newcommand*\justify{%
\fontdimen2\font=0.4em% interword space
\fontdimen3\font=0.2em% interword stretch
\fontdimen4\font=0.1em% interword shrink
\fontdimen7\font=0.1em% extra space
\hyphenchar\font=`\-% allowing hyphenation
}
\renewcommand{\texttt}[1]{%
\begingroup
\ttfamily
\begingroup\lccode`~=`/\lowercase{\endgroup\def~}{/\discretionary{}{}{}}%
\begingroup\lccode`~=`[\lowercase{\endgroup\def~}{[\discretionary{}{}{}}%
\begingroup\lccode`~=`.\lowercase{\endgroup\def~}{.\discretionary{}{}{}}%
\catcode`/=\active\catcode`[=\active\catcode`.=\active
\justify\scantokens{#1\noexpand}%
\endgroup
}
#+END_SRC
#+EXCLUDE_TAGS: noexport
:END:
@ -1832,7 +1852,7 @@ ctl.!default {
The X-Server is started by using the two systemd units ~xlogin@.service~ and ~x@.service~ provided by the package *xlogin*. The former is enabled (and started) for the vdr user - which results (using the default settings for the user *vdr* with the uid *666*) in the activation of ~xlogin@vdr.service~ when reaching the graphical.target. To simplify starting and stopping the X-server and the desktop session a ~yavdr-xorg.service~ is provided by the package ~yavdr-xorg~, which depends on the two units mentioned before.
~x@vt7.service~ is started automatically as a dependency of ~xlogin@vdr.service~ and starts the X-server. ~xlogin@vdr.service~ also starts a systemd user session using ~user@666.service~.
In order to use the keyboard layout configured during installation for the X-Server the script ~write-x11-keyboard-config~ reads the keyboard configuration from ~/etc/default/keyboard~ when starting ~x@.service~ and writes the file ~/etc/X11/xorg.conf.d/00-keyboard.conf~ (because systemd for Ubuntu (and Debian) has been patched not to create ~/etc/X11/xorg.conf.d/00-keyboard.conf~ according to the ~localectl~ settings).
In order to use the keyboard layout configured during installation for the X-Server we are using a script ~write-x11-keyboard-config,~ which reads the keyboard configuration from ~/etc/default/keyboard~ when starting ~x@.service~ and writes the file ~/etc/X11/xorg.conf.d/00-keyboard.conf~ (because systemd for Ubuntu (and Debian) has been patched not to automatically create the configuration file ~/etc/X11/xorg.conf.d/00-keyboard.conf~ according to the ~localectl~ settings).
To prevent stopping the X-server when vdr is running, additional dependencies are set up - see the drop-in rules created in ~/etc/systemd/system/vdr.service.d/~.
@ -2336,6 +2356,12 @@ preferred_refreshrates:
- '-w alsa-driver-broken'
# - '-a pulse' # do we need this with our existing asound.conf?
- name: vdr-config | use vaapi for softhddevice if we got an intel IGP
lineinfile:
path: /etc/vdr/conf.avail/softhddevice.conf
line: '-v va-pi'
state: present if intel_detected else absent
- name: add a login shell for the user vdr
user:
name: '{{ vdr.user }}'
@ -2704,21 +2730,41 @@ EndSection
***** intel graphics xorg.conf snippet
#+BEGIN_SRC jinja2 :tangle roles/yavdr-xorg/templates/20-intel.conf.j2
{{ ansible_managed | comment }}
{% set output = xorg.primary.connector|replace("-", "") %}
{% set primary_output = xorg.primary.connector|replace("-", "") %}
{% if xorg.secondary is defined %}
{% set secondary_output = xorg.secondary.connector|replace("-", "") %}
{% endif %}
Section "Device"
Identifier "Device0"
Driver "intel"
Option "TearFree" "true"
Option "UseEDID" "true"
Option "CustomEDID" "{{ output }}:{{ xorg.primary.edid }}"
{% if xorg.secondary is defined %}
Option "ZaphodHeads" "{{ primary_output }}"
Screen 0
{% endif %}
EndSection
{% if xorg.secondary is defined %}
Section "Device"
Identifier "Device1"
Driver "intel"
Option "TearFree" "true"
Option "ZaphodHeads" "{{ secondary_output }}"
Screen 1
EndSection
Section "ServerLayout"
Identifier "Layout0"
Screen 0 "Screen0" 0 0
Screen 1 "Screen1" RightOf "Screen0"
EndSection
{% endif %}
Section "Screen"
Identifier "Screen0"
Device "Device0"
Monitor "{{ output }}"
Monitor "{{ primary_output }}"
DefaultDepth 24
SubSection "Display"
Depth 24
@ -2729,8 +2775,26 @@ Section "Screen"
{% endif %}
EndSubSection
EndSection
{% if xorg.secondary is defined %}
Section "Screen"
Identifier "Screen1"
Device "Device1"
Monitor "{{ secondary_output }}"
DefaultDepth 24
SubSection "Display"
Depth 24
{% if xorg.secondary.mode %}
Modes "{{ xorg.secondary.mode }}"
{% else %}
Modes "1920x1080_50" "1920x1080_60" "1920x1080_24"
{% endif %}
EndSubSection
EndSection
{% endif %}
Section "Monitor"
Identifier "{{ output }}"
Identifier "{{ primary_output }}"
{% if xorg.primary.modelines %}
{% for modeline in xorg.primary.modelines %}
{{ modeline }}
@ -2742,8 +2806,23 @@ Section "Monitor"
{% endif %}
EndSection
{% if xorg.secondary is defined %}
Section "Monitor"
Identifier "{{ secondary_output }}"
{% if xorg.secondary.modelines %}
{% for modeline in xorg.secondary.modelines %}
{{ modeline }}
{% endfor %}
{% else %}
Modeline "1920x1080_24" 74.230 1920 2560 2604 2752 1080 1084 1089 1125 +hsync +vsync
Modeline "1920x1080_50" 148.500 1920 2448 2492 2640 1080 1084 1089 1125 +hsync +vsync
Modeline "1920x1080_60" 148.500 1920 2008 2056 2200 1080 1084 1089 1125 +hsync +vsync
{% endif %}
EndSection
{% endif %}
{% for connector, data in xrandr["Screen 0:"].iteritems() %}
{% if not data.is_connected or connector != xorg.primary.connector %}
{% if not data.is_connected or connector != xorg.primary.connector or (xorg.secondary is defined and connector != xorg.secondary.connector) %}
Section "Monitor"
Identifier "{{ connector|replace("-","") }}"
Option "Ignore" "true"

View File

@ -255,33 +255,39 @@ def collect_nvidia_data():
raise ValueError
Connector = namedtuple('Connector', "name xrandr_edid")
def find_drm_connectors(primary):
def find_drm_connectors(connections):
"""
takes a namedtuple Connector as the only argument.
returns a dict with the following schema:
returns a dict with the following schema (secondary may be empty):
{
'primary': {
'edid': 'edid.HDMI-1.bin',
'drm_connector': 'HDMI-A-1',
'xrandr_connector': 'HDMI-1',
},
'secondary': {
'edid': 'edid.eDP-1.bin',
'drm_connector': 'eDP-1',
'xrandr_connector': 'eDP-1',
}
'ignored_outputs': ['HDMI-A-2', 'DP-1']
}
"""
STATUS_GLOB = '/sys/class/drm/card0*/status'
CONNECTOR_RE = re.compile('card0-(?P<connector>[^/]+)/status')
def read_edid_bytes(edid_file):
edid_bytes = b''
try:
with open(primary.xrandr_edid, 'rb') as f:
xrandr_edid_bytes = f.read()
with open(edid_file, 'rb') as f:
edid_bytes = f.read()
except IOError:
xrandr_edid_bytes = b''
pass
return edid_bytes
drm = {'primary': {}, 'ignored_outputs': []}
xrandr_edid_bytes = read_edid_bytes(connections.get('primary', {}).get('edid', ""))
secondary_xrandr_edid_bytes = read_edid_bytes(connections.get('secondary', {}).get('edid', ''))
drm = {'primary': {}, 'secondary': {}, 'ignored_outputs': []}
for status_p in glob(STATUS_GLOB):
match = re.search(CONNECTOR_RE, status_p)
if match:
@ -295,19 +301,22 @@ def find_drm_connectors(primary):
except IOError:
continue
if connected and xrandr_edid_bytes:
drm_edid = os.path.join(os.path.dirname(status_p), 'edid')
try:
with open(drm_edid, 'rb') as f:
is_primary = f.read() == xrandr_edid_bytes
except IOError:
continue
else:
if is_primary:
if connected:
edid = read_edid_bytes(os.path.join(
os.path.dirname(status_p), 'edid'))
if edid:
if edid == xrandr_edid_bytes:
drm['primary'] = {
'edid': os.path.basename(primary.xrandr_edid),
'edid': os.path.basename(connections['primary'].get('edid', "")),
'drm_connector': drm_connector,
'xrandr_connector': primary.name,
'xrandr_connector': connections['primary'].get('connector',''),
}
continue
if secondary_xrandr_edid_bytes:
drm['secondary'] = {
'edid': os.path.basename(connections.get('secondary').get('edid', '')),
'drm_connector': drm_connector,
'xrandr_connector': connections['secondary'].get('connector',''),
}
continue
drm['ignored_outputs'].append(drm_connector)
@ -350,22 +359,24 @@ def output_data(data, write_edids=True):
result[name]['bus_id'] = bus_id
connector_0, resolution_0, refreshrate_0 = max(modes, key=sort_mode)[:3]
vendor_0, model_0, modelines_0 = parse_edid_data('/etc/X11/edid.{}.bin'.format(connector_0))
connector_0_edid = '/etc/X11/edid.{}.bin'.format(connector_0)
vendor_0, model_0, modelines_0 = parse_edid_data(connector_0_edid)
create_entry(result, 'primary', connector_0, resolution_0,
refreshrate_0, vendor_0, model_0, modelines_0)
if write_edids:
drm = find_drm_connectors(Connector(connector_0,
'/etc/X11/edid.{}.bin'.format(connector_0)))
# check if additional monitors exist
other_modes = [mode for mode in modes if mode[0] != connector_0]
if other_modes:
connector_1, resolution_1, refreshrate_1 = max(other_modes, key=sort_mode)[:3]
vendor_1, model_1, modelines_1 = parse_edid_data('/etc/X11/edid.{}.bin'.format(connector_1))
connector_1_edid = '/etc/X11/edid.{}.bin'.format(connector_1)
vendor_1, model_1, modelines_1 = parse_edid_data(connector_1_edid)
create_entry(result, 'secondary', connector_1, resolution_1,
refreshrate_1, vendor_1, model_1, modelines_1)
if write_edids:
drm = find_drm_connectors(result)
module.exit_json(changed=True if write_edids else False,
ansible_facts={'xrandr': data, 'xorg': result, 'drm': drm})

View File

@ -44,6 +44,12 @@
- '-w alsa-driver-broken'
# - '-a pulse' # do we need this with our existing asound.conf?
- name: vdr-config | use vaapi for softhddevice if we got an intel IGP
lineinfile:
path: /etc/vdr/conf.avail/softhddevice.conf
line: '-v va-pi'
state: present if intel_detected else absent
- name: add a login shell for the user vdr
user:
name: '{{ vdr.user }}'

View File

@ -1,19 +1,39 @@
{{ ansible_managed | comment }}
{% set output = xorg.primary.connector|replace("-", "") %}
{% set primary_output = xorg.primary.connector|replace("-", "") %}
{% if xorg.secondary is defined %}
{% set secondary_output = xorg.secondary.connector|replace("-", "") %}
{% endif %}
Section "Device"
Identifier "Device0"
Driver "intel"
Option "TearFree" "true"
Option "UseEDID" "true"
Option "CustomEDID" "{{ output }}:{{ xorg.primary.edid }}"
{% if xorg.secondary is defined %}
Option "ZaphodHeads" "{{ primary_output }}"
Screen 0
{% endif %}
EndSection
{% if xorg.secondary is defined %}
Section "Device"
Identifier "Device1"
Driver "intel"
Option "TearFree" "true"
Option "ZaphodHeads" "{{ secondary_output }}"
Screen 1
EndSection
Section "ServerLayout"
Identifier "Layout0"
Screen 0 "Screen0" 0 0
Screen 1 "Screen1" RightOf "Screen0"
EndSection
{% endif %}
Section "Screen"
Identifier "Screen0"
Device "Device0"
Monitor "{{ output }}"
Monitor "{{ primary_output }}"
DefaultDepth 24
SubSection "Display"
Depth 24
@ -24,8 +44,26 @@ Section "Screen"
{% endif %}
EndSubSection
EndSection
{% if xorg.secondary is defined %}
Section "Screen"
Identifier "Screen1"
Device "Device1"
Monitor "{{ secondary_output }}"
DefaultDepth 24
SubSection "Display"
Depth 24
{% if xorg.secondary.mode %}
Modes "{{ xorg.secondary.mode }}"
{% else %}
Modes "1920x1080_50" "1920x1080_60" "1920x1080_24"
{% endif %}
EndSubSection
EndSection
{% endif %}
Section "Monitor"
Identifier "{{ output }}"
Identifier "{{ primary_output }}"
{% if xorg.primary.modelines %}
{% for modeline in xorg.primary.modelines %}
{{ modeline }}
@ -37,8 +75,23 @@ Section "Monitor"
{% endif %}
EndSection
{% if xorg.secondary is defined %}
Section "Monitor"
Identifier "{{ secondary_output }}"
{% if xorg.secondary.modelines %}
{% for modeline in xorg.secondary.modelines %}
{{ modeline }}
{% endfor %}
{% else %}
Modeline "1920x1080_24" 74.230 1920 2560 2604 2752 1080 1084 1089 1125 +hsync +vsync
Modeline "1920x1080_50" 148.500 1920 2448 2492 2640 1080 1084 1089 1125 +hsync +vsync
Modeline "1920x1080_60" 148.500 1920 2008 2056 2200 1080 1084 1089 1125 +hsync +vsync
{% endif %}
EndSection
{% endif %}
{% for connector, data in xrandr["Screen 0:"].iteritems() %}
{% if not data.is_connected or connector != xorg.primary.connector %}
{% if not data.is_connected or connector != xorg.primary.connector or (xorg.secondary is defined and connector != xorg.secondary.connector) %}
Section "Monitor"
Identifier "{{ connector|replace("-","") }}"
Option "Ignore" "true"