3 test -z "${DEBUG:-}" ||
set -x
6 FIRMWARE_PATH
="${EDID_PATH:-"/run/current-system/firmware"}"
7 mapfile
-t edid_paths
<<<"${FIRMWARE_PATH//":"/$'\n'}"
10 LOGGER
="ERROR" log
"$@"
15 # shellcheck disable=SC2059
16 printf "[${LOGGER:-"INFO"}] $1\n" "${@:2}" >&2
21 mapfile
-t candidates
< <(
23 find -L "${@:2}" -path "*/${filePath}"
25 if test "${#candidates[@]}" -eq 0; then
26 log
"'%s' path not found" "${filePath}"
29 log
"'%s' path found at %s" "${filePath}" "${candidates[0]}"
30 echo -n "${candidates[0]}"
35 until find_path
"${filePath}" "${@:2}"; do
41 local what
="$1" sleepFor
43 backoff_start
="${backoff_start:-"5"}"
44 backoff_current
="${backoff_current:-"${backoff_start}"}"
45 backoff_jitter_multiplier
="${backoff_jitter_multiplier:-"0.3"}"
46 backoff_multiplier
="${backoff_multiplier:-1.5}"
48 sleepFor
="$(bc <<<"${backoff_current} + ${RANDOM} % (${backoff_current} * ${backoff_jitter_multiplier})")"
50 log
"still waiting for '%s', retry in %s sec..." "${what}" "${sleepFor}"
52 backoff_current
="$(bc <<<"scale=2; ${backoff_current} * ${backoff_multiplier}")"
57 local connPath="$1" newMode="$2" currentMode
58 currentMode="$
(cat "$connPath/force")"
59 if test "${currentMode}" == "${newMode}"; then
60 log "video mode is already
'%s'" "${currentMode}"
63 log "changing video mode from
'%s' to
'%s'" "${currentMode}" "${newMode}"
64 echo "${newMode}" >"$connPath/force
"
69 local connPath="$1" edidPath="$2"
73 local connPath="$1" mode="$2"
74 test -n "$mode" || return
75 log "setting up fb mode...
"
77 # see https://github.com/torvalds/linux/blob/8cd26fd90c1ad7acdcfb9f69ca99d13aa7b24561/drivers/gpu/drm/drm_sysfs.c#L202-L207
78 # see https://docs.kernel.org/fb/modedb.html
80 *d) force_mode "$connPath" off ;;
81 *e) force_mode "$connPath" on ;;
82 *D) force_mode "$connPath" on-digital ;;
87 local connPath="$1" edidFilename="$2" edidPath
88 test -n "${edidFilename}" || return
89 log "loading EDID override...
"
90 edidPath="$
(find_path
"${edidFilename}" "${edid_paths[@]/%/"/"}" -maxdepth 2)"
92 force_edid "${connPath}" "$edidPath"
93 cat "$edidPath" >"${connPath}/edid_override
"
95 if cmp "${connPath}/edid_override
" "${edidPath}" &>/dev/null; then
96 log "EDID is already up to
date with
'%s'" "${edidPath}"
98 log "applying EDID override from
${edidPath}"
99 cat "$edidPath" >"${connPath}/edid_override
"
105 local conn="$1" edidFilename="$2" mode="$3"
106 export LOGGER="$conn:${edidFilename}:$mode"
107 CHANGED="${CHANGED:-0}"
109 log "starting configuration
"
111 connPath="$
(wait_for_file
"$conn" /sys
/kernel
/debug
/dri
/ -maxdepth 2 -type d
)"
112 apply_edid "${connPath}" "${edidFilename}"
113 apply_mode "${connPath}" "$mode"
115 if test "${CHANGED}" != 0; then
116 log "changes detected
, triggering hotplug
"
117 echo 1 >"${connPath}/trigger_hotplug
"
119 log "no changes detected
, skipping hotplug trigger
"
124 if [[ $EUID -ne 0 ]]; then
125 err "must be run as root
"
128 if test "$#" == 0; then
129 log "loading kernel parameters from
/proc
/cmdline
"
130 # replace script arguments with kernel parameters
131 mapfile -t args < <(xargs -n1 </proc/cmdline)
133 log "loading kernel parameters compatible arguments from commandline
"
137 local -A edids modes connectors
141 for arg in "${args[@]}"; do
144 test "${key}" == "${arg}" || value="${arg#*=}"
148 # one argument per connector:
149 # video=DP-4:e video=DP-1:e
150 connector="${value%:*}"
152 connectors["${connector}"]=""
153 modes["$connector"]="$mode"
156 # single argument for all connectors:
157 # drm.edid_firmware=DP-4:edid/one.bin,DP-1:edid/two.bin
158 mapfile -t entries <<<"${value//","/$'\n'}"
159 for entry in "${entries[@]}"; do
160 connector="${entry%:*}"
161 edidFilename="${entry#*:}"
162 connectors["${connector}"]=""
163 edids["${connector}"]="${edidFilename}"
169 for connector in "${!connectors[@]}"; do
170 # spawn in a subshell to easily adjust and runtime modify global variables
171 (load "${connector}" "${edids["${connector}"]:-""}" "${modes["${connector}"]:-""}") &