# KMS: autoriconoscimento via EDID ed abilitare uscite

## djinnZ

Più che altro è un appunto ma può sempre tornare utile.

Faccio presente che non garantisco nulla ed i cocci sono vostri (in particolare quelli del monitor, non si gioca con le frequenze)...

... e potrei sempre aver inserito intenzionalmente un errore, tanto per il gusto di far danno.  :Twisted Evil: 

Talvolta il monitor o la scheda grafica sono problematici o non gradiscono l'accoppiata e viene riportato un EDID sballato o non viene riportato del tutto.Alle volte torna comodo utilizzare un cavo ad 'Y' per connettere più monitor allo stesso pc; spesso, non sempre (si fa per dire), l'EDID non viene rilevato.Oppure si usa uno switch per connettere più pc allo stesso monitor.Od ancora non intendete asciare inutilmente acceso il monitor per una postazione server utilizzata al massimo due volte all'anno (per il resto si opera da remoto, come tutte le persone normali).Tra, per esempio: 1280x1024@60, 1024x768@70, 1024x768@60 e 800x600@70; volete che sia disponibile solo la 1024x768 a 60hz perchè è più luminosa, anche se meno nitida.Il bios o l'altro sistema operativo costringono ad utilizzare una centratura assurda per essere visualizzati e quindi è necessario che il sistema linux si adegui.Molto probabilmente, certamente anzi, siete degli avari (nel senso di pitocchi/spilorci, non di popolazione) nonché deprecabili sabotatori dell'ordine costituito nel rifiutare l'omologazione, ma le affermazioni scontate non risolvono nulla.

Invocare sui responsabili di codesti problemi una antica maledizione sumera che ne perseguiti i discendenti sino alla undicesima generazione neppure aiuta a risolvere ma, quantomeno, offre un temporaneo ed effimero sollievo alle nostre martoriate gonadi.

Il cervello, finchè ci sarà concesso di usarlo, invece serve; anche perchè alcuni ementi qui riportati, quali i percorsi in /sys, sono sempre soggetti a modifiche.

Un primo approccio, per consentire al computer di funzionare senza monitor connesso od attivo, è inserire un parametro  *kernel command line wrote:*   

> video=device:e

 per forzare il rilevamento del monitor e non dover riavviare solo per avere X correttamente funzionante.

Il problema con KMS è che pretende di far tutto da solo e, comunque. se non riceve un EDID o quest'ultimo non è corretto, non solo imposta la risoluzione a 1024x768 (che potrebbe persino andar bene) ma inizia a spammare i log con fetenzia di questo genere:

```
[drm:drm_edid_block_valid] *ERROR* EDID checksum is invalid (252)

[drm:drm_edid_block_valid] *ERROR* Raw EDID:

<3>00 ff ff ff ff ff ff 00 25 b2 6a 98 00 00 00 00  ........%.j.....

<3>18 09 01 01 0c 24 1b 64 e8 e0 52 a1 54 46 9b 24  .....$.d..R.TF.$

<3>10 48 4f a0 21 00 31 59 45 59 61 59 a9 4f 81 59  .HO.!.1YEYaY.O.Y

<3>71 4f 61 68 01 01 7c 15 80 e0 20 e0 38 10 20 60  qOah..|... .8. `

<3>86 00 68 0e 11 00 00 18 54 3d 00 c0 51 00 30 40  ..h.....T=..Q.0@

<3>40 a0 13 00 68 0e 11 00 80 80 80 80 00 80 80 80  @...h...........

<3>96 80 60 ff 00 0a 80 20 20 20 20 20 00 00 00 00  ..`....     ....

<3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 13  ................

radeon 0000:05:00.0: VGA-1: EDID block 0 invalid.

[drm:radeon_vga_detect] *ERROR* VGA-1: probed a monitor but no|invalid EDID
```

oppure

```
[drm:drm_edid_block_valid] *ERROR* Raw EDID:

<3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

<3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

<3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

<3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

<3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

<3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

<3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

<3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

```

Una prima soluzione, nel caso l'edid non sia corretto, la ho già postata qui con questa 

```
So much broken hardware, so few bullets.

Signed-off-by: Adam Jackson <ajax at redhat.com>

---

 Documentation/kernel-parameters.txt |    3 +++

 drivers/gpu/drm/drm_edid.c          |   12 ++++++++++--

 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt

index 17d50d2..5814331 100644

--- a/Documentation/kernel-parameters.txt

+++ b/Documentation/kernel-parameters.txt

@@ -713,6 +713,9 @@ and is between 256 and 4096 characters. It is defined in the file

    edd=      [EDD]

          Format: {"off" | "on" | "skip[mbr]"}

 

+   edid_force_checksum=<bool> [DRM]

+         Forcibly correct EDID checksum errors. Default is off.

+

    edid_threshold=<int> [DRM]

          Set the minimum number of bytes of an EDID header

          that must be valid, out of 8.  The default is 6.

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c

index 6a1b5a3..55b498e 100644

--- a/drivers/gpu/drm/drm_edid.c

+++ b/drivers/gpu/drm/drm_edid.c

@@ -66,6 +66,10 @@ static unsigned int edid_threshold = 6;

 MODULE_PARM_DESC(edid_threshold, "EDID header fixup threshold (default: 6)");

 module_param_named(edid_threshold, edid_threshold, int, 0600);

 

+static bool edid_force_checksum = 0;

+MODULE_PARM_DESC(edid_force_checksum, "Forcibly correct EDID checksum");

+module_param_named(edid_force_checksum, edid_force_checksum, int, 0600);

+

 #define LEVEL_DMT   0

 #define LEVEL_GTF   1

 #define LEVEL_GTF2   2

@@ -149,8 +153,12 @@ drm_edid_block_valid(u8 *raw_edid)

    for (i = 0; i < EDID_LENGTH; i++)

       csum += raw_edid[i];

    if (csum) {

-      DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum);

-      goto bad;

+      if (edid_force_checksum) {

+         raw_edid[0x7f] -= csum;

+      } else {

+         DRM_ERROR("EDID checksum is invalid (%d)\n", csum);

+         goto bad;

+      }

    }

 

    /* per-block-type checks */

-- 

1.7.0.1
```

per diversi CRT ed alcuni vecchi LCD è funzionale.

Sorvolando sulla necessità di riadattare detta patch ai kernel correnti (non è difficile) non risolve il problema del monitor disconnesso o spento e, come vedremo, non è che serva a molto.

Per prima cosa ci serve sapere come sono individuati i device di uscita dal kernel. Esempio: *lspci wrote:*   

> 00:00.0 Host bridge: Advanced Micro Devices [AMD] nee ATI RX780/RX790 Chipset Host Bridge
> 
> 00:02.0 PCI bridge: Advanced Micro Devices [AMD] nee ATI RD790 PCI to PCI bridge (external gfx0 port A)
> 
> 00:09.0 PCI bridge: Advanced Micro Devices [AMD] nee ATI RD790 PCI to PCI bridge (PCI express gpp port E)
> ...

 quindi andiamo a spulciare in sysfs *ls /sys/bus/pci/devices/0000\:05\:00.0/drm/card0 wrote:*   

> card0-DVI-I-1/
> 
> card0-HDMI-A-1/
> 
> card0-VGA-1/
> ...

 Supponendo che il monitor sia correttamente rilevato, vogliamo solo non doverlo avere connesso ed acceso all'avvio, ed è collegato alla porta VGA, pertanto, ci basta copiare l'EDID con un banalissimo  *Quote:*   

> cat /sys/bus/pci/devices/0000\:05\:00.0/drm/card0/card0-VGA-1/edid > /lib/firmware/edid/MioMonitor.bin

 pertanto la configurazione del kernel per disabilitare le altre uscite e forzare la VGA a comportarsi come se il monitor fosse connesso ed attivo, supponendo di utilizzare una ATI e di non voler configurare la linea di comando nel bootloader, sarà *Quote:*   

> [omissis]
> 
> CONFIG_CMDLINE_BOOL=y
> 
> CONFIG_CMDLINE="video=HDMI-A-1:d video=DVI-I-1:d drm_kms_helper.edid_firmware=VGA-1:edid/MioMonitor.bin video=VGA-1:e"
> ...

 utile sottolineare che edid_firmware e video=device:e vanno inseriti in quest'ordine ed è possibile specificare per ogni uscita un differente default.

Se l'EDID è valido e l'unico problema è il checksum (il caso in cui la patch di cui sopra è utile) si può pensare di correggerlo. Per prima cosa serve l'utility edid-decode

```
git clone git://anongit.freedesktop.org/xorg/app/edid-decode

cd edid-decode

make
```

se prendiamo l'EDID *Quote:*   

> cat /sys/bus/pci/devices/0000\:05\:00.0/drm/card0/card0-VGA-1/edid > MioMonitor.bin

 e lo visualizziamo vedremo

```
00000000  00 ff ff ff ff ff ff 00  4c 2d a2 08 57 45 55 5a  |........L-..WEUZ|

00000010  0e 16 01 03 0e 29 17 78  2a 78 41 a2 59 55 9b 25  |.....).x*xA.YU.%|

00000020  0f 50 54 bf ee 00 81 c0  01 01 01 01 01 01 01 01  |.PT.............|

00000030  01 01 01 01 01 01 66 21  56 aa 51 00 1e 30 46 8f  |......f!V.Q..0F.|

00000040  33 00 9a e6 10 00 00 1e  00 00 00 fd 00 38 4b 1e  |3............8K.|

00000050  51 09 00 0a 20 20 20 20  20 20 00 00 00 fc 00 53  |Q...      .....S|

00000060  31 39 42 31 35 30 0a 20  20 20 20 20 00 00 00 ff  |19B150.     ....|

00000070  00 48 4d 42 43 34 30 36  35 34 36 0a 20 20 00 99  |.HMBC406546.  ..|

00000080
```

verificandolo vedremo invece

```
Extracted contents:

header:          00 ff ff ff ff ff ff 00

serial number:   4c 2d a2 08 57 45 55 5a 0e 16

version:         01 03

basic params:    0e 29 17 78 2a

chroma info:     78 41 a2 59 55 9b 25 0f 50 54

established:     bf ee 00

standard:        81 c0 01 01 01 01 01 01 01 01 01 01 01 01 01 01

descriptor 1:    66 21 56 aa 51 00 1e 30 46 8f 33 00 9a e6 10 00 00 1e

descriptor 2:    00 00 00 fd 00 38 4b 1e 51 09 00 0a 20 20 20 20 20 20

descriptor 3:    00 00 00 fc 00 53 31 39 42 31 35 30 0a 20 20 20 20 20

descriptor 4:    00 00 00 ff 00 48 4d 42 43 34 30 36 35 34 36 0a 20 20

extensions:      00

checksum:        99

Manufacturer: SAM Model 8a2 Serial Number 1515537751

Made week 14 of 2012

EDID version: 1.3

Analog display, Input voltage level: 0.7/0.3 V

Sync: Separate Composite SyncOnGreen 

Maximum image size: 41 cm x 23 cm

Gamma: 2.20

DPMS levels: Off

RGB color display

First detailed timing is preferred timing

Established timings supported:

  720x400@70Hz

  640x480@60Hz

  640x480@67Hz

  640x480@72Hz

  640x480@75Hz

  800x600@56Hz

  800x600@60Hz

  800x600@72Hz

  800x600@75Hz

  832x624@75Hz

  1024x768@60Hz

  1024x768@70Hz

  1024x768@75Hz

Standard timings supported:

  1280x720@60Hz

Detailed mode: Clock 85.500 MHz, 410 mm x 230 mm

               1366 1436 1579 1792 hborder 0

                768  771  774  798 vborder 0

               +hsync +vsync 

Monitor ranges (GTF): 56-75Hz V, 30-81kHz H, max dotclock 90MHz

Monitor name: S19B150

Serial number: HMBC406546

Checksum: 0x99 (should be 0x93)

EDID block does not conform at all!

        Block has broken checksum
```

il checksum altri non è che l'ultimo carattere, basta cambiare il valore in 0x93 e l'edid è pronto per essere utilizzato come nuovo default, con le istruzioni di cui sopra, ovviamente.

In alternativa si può pensare di utilizzare gli edid forniti con il kernel *Quote:*   

> emerge dos2unix
> 
> cd /usr/src/linux/Documentation/EDID
> 
> cp 1920x1080.S 0000x0000.S

 ed editare il file.

Per chi ha familiarità con la configurazione delle modeline di X i parametri sono abbastanza intuitivi e l'uso di codesta risorsa online o di programmi appositi, residuo del glorioso passato in cui ci si doveva impostare le modeline partendo da zero, può tornare veramente utile.

Con il comando make viene generato il file 0000x0000.bin che può essere controllato con edid-decode per correggere il checksum, come da istruzioni.

Per dettagli, soprattutto nel caso in cui si debba procedere alla centratura, cercate i vecchi howto su come migliorare le modeline aggiungendo anche la centratura del monitor.

Come ulteriore alternativa segnalo solo che per un certo sistema inoperativo proprietario sono disponibili un editor di EDID che consentono di costruirli da zero od una maggiore personalizzazione, soprattutto nel caso in cui si tenta di riciclare un EDID non valido.

Rimane da capire come i beneamati devel del progetto KMS non abbiano voluto includere la patch per ignorare il checksum degli EDID nel kernel (l'alibi ufficiale è che imporre frequenze sballate potrebbe danneggiare il monitor) ma anche come mai i devel gento non abbiano incluso dos2unix tra le dipendenze del kernel (è necessario al make degli EDID) e non abbiano incluso edid-decode nell'albero di portage (serve comunque) ma tant'è.

Sempre ringraziando i beneamati devel del kernel c'è da sottolineare basiti che comunque KMS continua a spammare i log con messaggi idioti del genere 

```
[drm] Got external EDID base block and 0 extensions from "edid/MioMonitor.bin" for connector "VGA-1"
```

 (e viene proprio da chiedersi che senso abbia informare con tanta veemente, demenziale, sollecitudine che sono stati utilizzati dei parametri manuali) ma certamente con frequenza minore e ridotto massacro di byte liberi innocenti rispetto all'errore.

Forse è segno dei tempi bui in cui versiamo, forse Kornbluth aveva davvero visto il futuro.

Questo per dire che se un'anima pia, in vena di discutere nell'odioso idioma d'albione, vorrà segnalare i problemi a chi di competenza e tentare di ricondurli a più miti consigli sarà agire ben più gradito di qualsiasi ringraziamento.

Inutile sottolineare che dette istruzioni sono concepite per un kernel con KMS builtin ma ritengo che sia ovvio configurare edid_firmware=VGA-1:edid/MioMonitor.bin come parametro per la soluzione modulare.

Qualche link a casacciohttp://cgit.freedesktop.org/xorg/app/edid-decodehttp://xtiming.sourceforge.net/cgi-bin/xtiming.plhttp://umc.sourceforge.nethttp://sourceforge.net/projects/edideditorhttp://www.tucows.com/preview/329441

----------

