xref: /openbmc/qemu/hw/display/edid-generate.c (revision 5c8463886d50eeb0337bd121ab877cf692731e36)
1  /*
2   * QEMU EDID generator.
3   *
4   * This work is licensed under the terms of the GNU GPL, version 2 or later.
5   * See the COPYING file in the top-level directory.
6   */
7  #include "qemu/osdep.h"
8  #include "qemu/bswap.h"
9  #include "hw/display/edid.h"
10  
11  static const struct edid_mode {
12      uint32_t xres;
13      uint32_t yres;
14      uint32_t byte;
15      uint32_t xtra3;
16      uint32_t bit;
17      uint32_t dta;
18  } modes[] = {
19      /* dea/dta extension timings (all @ 50 Hz) */
20      { .xres = 5120,   .yres = 2160,   .dta = 125 },
21      { .xres = 4096,   .yres = 2160,   .dta = 101 },
22      { .xres = 3840,   .yres = 2160,   .dta =  96 },
23      { .xres = 2560,   .yres = 1080,   .dta =  89 },
24      { .xres = 2048,   .yres = 1152 },
25      { .xres = 1920,   .yres = 1080,   .dta =  31 },
26  
27      /* dea/dta extension timings (all @ 60 Hz) */
28      { .xres = 3840,   .yres = 2160,   .dta =  97 },
29  
30      /* additional standard timings 3 (all @ 60Hz) */
31      { .xres = 1920,   .yres = 1200,   .xtra3 = 10,   .bit = 0 },
32      { .xres = 1600,   .yres = 1200,   .xtra3 =  9,   .bit = 2 },
33      { .xres = 1680,   .yres = 1050,   .xtra3 =  9,   .bit = 5 },
34      { .xres = 1440,   .yres =  900,   .xtra3 =  8,   .bit = 5 },
35      { .xres = 1280,   .yres = 1024,   .xtra3 =  7,   .bit = 1 },
36      { .xres = 1280,   .yres =  960,   .xtra3 =  7,   .bit = 3 },
37      { .xres = 1280,   .yres =  768,   .xtra3 =  7,   .bit = 6 },
38  
39      { .xres = 1920,   .yres = 1440,   .xtra3 = 11,   .bit = 5 },
40      { .xres = 1856,   .yres = 1392,   .xtra3 = 10,   .bit = 3 },
41      { .xres = 1792,   .yres = 1344,   .xtra3 = 10,   .bit = 5 },
42      { .xres = 1440,   .yres = 1050,   .xtra3 =  8,   .bit = 1 },
43      { .xres = 1360,   .yres =  768,   .xtra3 =  8,   .bit = 7 },
44  
45      /* established timings (all @ 60Hz) */
46      { .xres = 1024,   .yres =  768,   .byte  = 36,   .bit = 3 },
47      { .xres =  800,   .yres =  600,   .byte  = 35,   .bit = 0 },
48      { .xres =  640,   .yres =  480,   .byte  = 35,   .bit = 5 },
49  };
50  
51  typedef struct Timings {
52      uint32_t xfront;
53      uint32_t xsync;
54      uint32_t xblank;
55  
56      uint32_t yfront;
57      uint32_t ysync;
58      uint32_t yblank;
59  
60      uint64_t clock;
61  } Timings;
62  
generate_timings(Timings * timings,uint32_t refresh_rate,uint32_t xres,uint32_t yres)63  static void generate_timings(Timings *timings, uint32_t refresh_rate,
64                               uint32_t xres, uint32_t yres)
65  {
66      /* pull some realistic looking timings out of thin air */
67      timings->xfront = xres * 25 / 100;
68      timings->xsync  = xres *  3 / 100;
69      timings->xblank = xres * 35 / 100;
70  
71      timings->yfront = yres *  5 / 1000;
72      timings->ysync  = yres *  5 / 1000;
73      timings->yblank = yres * 35 / 1000;
74  
75      timings->clock  = ((uint64_t)refresh_rate *
76                         (xres + timings->xblank) *
77                         (yres + timings->yblank)) / 10000000;
78  }
79  
edid_ext_dta(uint8_t * dta)80  static void edid_ext_dta(uint8_t *dta)
81  {
82      dta[0] = 0x02;
83      dta[1] = 0x03;
84      dta[2] = 0x05;
85      dta[3] = 0x00;
86  
87      /* video data block */
88      dta[4] = 0x40;
89  }
90  
edid_ext_dta_mode(uint8_t * dta,uint8_t nr)91  static void edid_ext_dta_mode(uint8_t *dta, uint8_t nr)
92  {
93      dta[dta[2]] = nr;
94      dta[2]++;
95      dta[4]++;
96  }
97  
edid_std_mode(uint8_t * mode,uint32_t xres,uint32_t yres)98  static int edid_std_mode(uint8_t *mode, uint32_t xres, uint32_t yres)
99  {
100      uint32_t aspect;
101  
102      if (xres == 0 || yres == 0) {
103          mode[0] = 0x01;
104          mode[1] = 0x01;
105          return 0;
106  
107      } else if (xres * 10 == yres * 16) {
108          aspect = 0;
109      } else if (xres * 3 == yres * 4) {
110          aspect = 1;
111      } else if (xres * 4 == yres * 5) {
112          aspect = 2;
113      } else if (xres * 9 == yres * 16) {
114          aspect = 3;
115      } else {
116          return -1;
117      }
118  
119      if ((xres / 8) - 31 > 255) {
120          return -1;
121      }
122  
123      mode[0] = (xres / 8) - 31;
124      mode[1] = ((aspect << 6) | (60 - 60));
125      return 0;
126  }
127  
edid_fill_modes(uint8_t * edid,uint8_t * xtra3,uint8_t * dta,uint32_t maxx,uint32_t maxy)128  static void edid_fill_modes(uint8_t *edid, uint8_t *xtra3, uint8_t *dta,
129                              uint32_t maxx, uint32_t maxy)
130  {
131      const struct edid_mode *mode;
132      int std = 38;
133      int rc, i;
134  
135      for (i = 0; i < ARRAY_SIZE(modes); i++) {
136          mode = modes + i;
137  
138          if ((maxx && mode->xres > maxx) ||
139              (maxy && mode->yres > maxy)) {
140              continue;
141          }
142  
143          if (mode->byte) {
144              edid[mode->byte] |= (1 << mode->bit);
145          } else if (std < 54) {
146              rc = edid_std_mode(edid + std, mode->xres, mode->yres);
147              if (rc == 0) {
148                  std += 2;
149              }
150          } else if (mode->xtra3 && xtra3) {
151              xtra3[mode->xtra3] |= (1 << mode->bit);
152          }
153  
154          if (dta && mode->dta) {
155              edid_ext_dta_mode(dta, mode->dta);
156          }
157      }
158  
159      while (std < 54) {
160          edid_std_mode(edid + std, 0, 0);
161          std += 2;
162      }
163  }
164  
edid_checksum(uint8_t * edid,size_t len)165  static void edid_checksum(uint8_t *edid, size_t len)
166  {
167      uint32_t sum = 0;
168      int i;
169  
170      for (i = 0; i < len; i++) {
171          sum += edid[i];
172      }
173      sum &= 0xff;
174      if (sum) {
175          edid[len] = 0x100 - sum;
176      }
177  }
178  
edid_desc_next(uint8_t * edid,uint8_t * dta,uint8_t * desc)179  static uint8_t *edid_desc_next(uint8_t *edid, uint8_t *dta, uint8_t *desc)
180  {
181      if (desc == NULL) {
182          return NULL;
183      }
184      if (desc + 18 + 18 < edid + 127) {
185          return desc + 18;
186      }
187      if (dta) {
188          if (desc < edid + 127) {
189              return dta + dta[2];
190          }
191          if (desc + 18 + 18 < dta + 127) {
192              return desc + 18;
193          }
194      }
195      return NULL;
196  }
197  
edid_desc_type(uint8_t * desc,uint8_t type)198  static void edid_desc_type(uint8_t *desc, uint8_t type)
199  {
200      desc[0] = 0;
201      desc[1] = 0;
202      desc[2] = 0;
203      desc[3] = type;
204      desc[4] = 0;
205  }
206  
edid_desc_text(uint8_t * desc,uint8_t type,const char * text)207  static void edid_desc_text(uint8_t *desc, uint8_t type,
208                             const char *text)
209  {
210      size_t len;
211  
212      edid_desc_type(desc, type);
213      memset(desc + 5, ' ', 13);
214  
215      len = strlen(text);
216      if (len > 12) {
217          len = 12;
218      }
219      memcpy(desc + 5, text, len);
220      desc[5 + len] = '\n';
221  }
222  
edid_desc_ranges(uint8_t * desc)223  static void edid_desc_ranges(uint8_t *desc)
224  {
225      edid_desc_type(desc, 0xfd);
226  
227      /* vertical (50 -> 125 Hz) */
228      desc[5] =  50;
229      desc[6] = 125;
230  
231      /* horizontal (30 -> 160 kHz) */
232      desc[7] =  30;
233      desc[8] = 160;
234  
235      /* max dot clock (2550 MHz) */
236      desc[9] = 2550 / 10;
237  
238      /* no extended timing information */
239      desc[10] = 0x01;
240  
241      /* padding */
242      desc[11] = '\n';
243      memset(desc + 12, ' ', 6);
244  }
245  
246  /* additional standard timings 3 */
edid_desc_xtra3_std(uint8_t * desc)247  static void edid_desc_xtra3_std(uint8_t *desc)
248  {
249      edid_desc_type(desc, 0xf7);
250      desc[5] = 10;
251  }
252  
edid_desc_dummy(uint8_t * desc)253  static void edid_desc_dummy(uint8_t *desc)
254  {
255      edid_desc_type(desc, 0x10);
256  }
257  
edid_desc_timing(uint8_t * desc,const Timings * timings,uint32_t xres,uint32_t yres,uint32_t xmm,uint32_t ymm)258  static void edid_desc_timing(uint8_t *desc, const Timings *timings,
259                               uint32_t xres, uint32_t yres,
260                               uint32_t xmm, uint32_t ymm)
261  {
262      stw_le_p(desc, timings->clock);
263  
264      desc[2] = xres   & 0xff;
265      desc[3] = timings->xblank & 0xff;
266      desc[4] = (((xres   & 0xf00) >> 4) |
267                 ((timings->xblank & 0xf00) >> 8));
268  
269      desc[5] = yres   & 0xff;
270      desc[6] = timings->yblank & 0xff;
271      desc[7] = (((yres   & 0xf00) >> 4) |
272                 ((timings->yblank & 0xf00) >> 8));
273  
274      desc[8] = timings->xfront & 0xff;
275      desc[9] = timings->xsync  & 0xff;
276  
277      desc[10] = (((timings->yfront & 0x00f) << 4) |
278                  ((timings->ysync  & 0x00f) << 0));
279      desc[11] = (((timings->xfront & 0x300) >> 2) |
280                  ((timings->xsync  & 0x300) >> 4) |
281                  ((timings->yfront & 0x030) >> 2) |
282                  ((timings->ysync  & 0x030) >> 4));
283  
284      desc[12] = xmm & 0xff;
285      desc[13] = ymm & 0xff;
286      desc[14] = (((xmm & 0xf00) >> 4) |
287                  ((ymm & 0xf00) >> 8));
288  
289      desc[17] = 0x18;
290  }
291  
edid_to_10bit(float value)292  static uint32_t edid_to_10bit(float value)
293  {
294      return (uint32_t)(value * 1024 + 0.5);
295  }
296  
edid_colorspace(uint8_t * edid,float rx,float ry,float gx,float gy,float bx,float by,float wx,float wy)297  static void edid_colorspace(uint8_t *edid,
298                              float rx, float ry,
299                              float gx, float gy,
300                              float bx, float by,
301                              float wx, float wy)
302  {
303      uint32_t red_x   = edid_to_10bit(rx);
304      uint32_t red_y   = edid_to_10bit(ry);
305      uint32_t green_x = edid_to_10bit(gx);
306      uint32_t green_y = edid_to_10bit(gy);
307      uint32_t blue_x  = edid_to_10bit(bx);
308      uint32_t blue_y  = edid_to_10bit(by);
309      uint32_t white_x = edid_to_10bit(wx);
310      uint32_t white_y = edid_to_10bit(wy);
311  
312      edid[25] = (((red_x   & 0x03) << 6) |
313                  ((red_y   & 0x03) << 4) |
314                  ((green_x & 0x03) << 2) |
315                  ((green_y & 0x03) << 0));
316      edid[26] = (((blue_x  & 0x03) << 6) |
317                  ((blue_y  & 0x03) << 4) |
318                  ((white_x & 0x03) << 2) |
319                  ((white_y & 0x03) << 0));
320      edid[27] = red_x   >> 2;
321      edid[28] = red_y   >> 2;
322      edid[29] = green_x >> 2;
323      edid[30] = green_y >> 2;
324      edid[31] = blue_x  >> 2;
325      edid[32] = blue_y  >> 2;
326      edid[33] = white_x >> 2;
327      edid[34] = white_y >> 2;
328  }
329  
qemu_edid_dpi_from_mm(uint32_t mm,uint32_t res)330  static uint32_t qemu_edid_dpi_from_mm(uint32_t mm, uint32_t res)
331  {
332      return res * 254 / 10 / mm;
333  }
334  
qemu_edid_dpi_to_mm(uint32_t dpi,uint32_t res)335  uint32_t qemu_edid_dpi_to_mm(uint32_t dpi, uint32_t res)
336  {
337      return res * 254 / 10 / dpi;
338  }
339  
init_displayid(uint8_t * did)340  static void init_displayid(uint8_t *did)
341  {
342      did[0] = 0x70; /* display id extension */
343      did[1] = 0x13; /* version 1.3 */
344      did[2] = 4;    /* length */
345      did[3] = 0x03; /* product type (0x03 == standalone display device) */
346      edid_checksum(did + 1, did[2] + 4);
347  }
348  
qemu_displayid_generate(uint8_t * did,const Timings * timings,uint32_t xres,uint32_t yres,uint32_t xmm,uint32_t ymm)349  static void qemu_displayid_generate(uint8_t *did, const Timings *timings,
350                                      uint32_t xres, uint32_t yres,
351                                      uint32_t xmm, uint32_t ymm)
352  {
353      did[0] = 0x70; /* display id extension */
354      did[1] = 0x13; /* version 1.3 */
355      did[2] = 23;   /* length */
356      did[3] = 0x03; /* product type (0x03 == standalone display device) */
357  
358      did[5] = 0x03; /* Detailed Timings Data Block */
359      did[6] = 0x00; /* revision */
360      did[7] = 0x14; /* block length */
361  
362      did[8]  = timings->clock  & 0xff;
363      did[9]  = (timings->clock & 0xff00) >> 8;
364      did[10] = (timings->clock & 0xff0000) >> 16;
365  
366      did[11] = 0x88; /* leave aspect ratio undefined */
367  
368      stw_le_p(did + 12, 0xffff & (xres - 1));
369      stw_le_p(did + 14, 0xffff & (timings->xblank - 1));
370      stw_le_p(did + 16, 0xffff & (timings->xfront - 1));
371      stw_le_p(did + 18, 0xffff & (timings->xsync - 1));
372  
373      stw_le_p(did + 20, 0xffff & (yres - 1));
374      stw_le_p(did + 22, 0xffff & (timings->yblank - 1));
375      stw_le_p(did + 24, 0xffff & (timings->yfront - 1));
376      stw_le_p(did + 26, 0xffff & (timings->ysync - 1));
377  
378      edid_checksum(did + 1, did[2] + 4);
379  }
380  
qemu_edid_generate(uint8_t * edid,size_t size,qemu_edid_info * info)381  void qemu_edid_generate(uint8_t *edid, size_t size,
382                          qemu_edid_info *info)
383  {
384      Timings timings;
385      uint8_t *desc = edid + 54;
386      uint8_t *xtra3 = NULL;
387      uint8_t *dta = NULL;
388      uint8_t *did = NULL;
389      uint32_t width_mm, height_mm;
390      uint32_t refresh_rate = info->refresh_rate ? info->refresh_rate : 75000;
391      uint32_t dpi = 100; /* if no width_mm/height_mm */
392      uint32_t large_screen = 0;
393  
394      /* =============== set defaults  =============== */
395  
396      if (!info->vendor || strlen(info->vendor) != 3) {
397          info->vendor = "RHT";
398      }
399      if (!info->name) {
400          info->name = "QEMU Monitor";
401      }
402      if (!info->prefx) {
403          info->prefx = 1280;
404      }
405      if (!info->prefy) {
406          info->prefy = 800;
407      }
408      if (info->width_mm && info->height_mm) {
409          width_mm = info->width_mm;
410          height_mm = info->height_mm;
411          dpi = qemu_edid_dpi_from_mm(width_mm, info->prefx);
412      } else {
413          width_mm = qemu_edid_dpi_to_mm(dpi, info->prefx);
414          height_mm = qemu_edid_dpi_to_mm(dpi, info->prefy);
415      }
416  
417      generate_timings(&timings, refresh_rate, info->prefx, info->prefy);
418      if (info->prefx >= 4096 || info->prefy >= 4096 || timings.clock >= 65536) {
419          large_screen = 1;
420      }
421  
422      /* =============== extensions  =============== */
423  
424      if (size >= 256) {
425          dta = edid + 128;
426          edid[126]++;
427          edid_ext_dta(dta);
428      }
429  
430      if (size >= 384 && large_screen) {
431          did = edid + 256;
432          edid[126]++;
433          init_displayid(did);
434      }
435  
436      /* =============== header information =============== */
437  
438      /* fixed */
439      edid[0] = 0x00;
440      edid[1] = 0xff;
441      edid[2] = 0xff;
442      edid[3] = 0xff;
443      edid[4] = 0xff;
444      edid[5] = 0xff;
445      edid[6] = 0xff;
446      edid[7] = 0x00;
447  
448      /* manufacturer id, product code, serial number */
449      uint16_t vendor_id = ((((info->vendor[0] - '@') & 0x1f) << 10) |
450                            (((info->vendor[1] - '@') & 0x1f) <<  5) |
451                            (((info->vendor[2] - '@') & 0x1f) <<  0));
452      uint16_t model_nr = 0x1234;
453      uint32_t serial_nr = info->serial ? atoi(info->serial) : 0;
454      stw_be_p(edid +  8, vendor_id);
455      stw_le_p(edid + 10, model_nr);
456      stl_le_p(edid + 12, serial_nr);
457  
458      /* manufacture week and year */
459      edid[16] = 42;
460      edid[17] = 2014 - 1990;
461  
462      /* edid version */
463      edid[18] = 1;
464      edid[19] = 4;
465  
466  
467      /* =============== basic display parameters =============== */
468  
469      /* video input: digital, 8bpc, displayport */
470      edid[20] = 0xa5;
471  
472      /* screen size: undefined */
473      edid[21] = width_mm / 10;
474      edid[22] = height_mm / 10;
475  
476      /* display gamma: 2.2 */
477      edid[23] = 220 - 100;
478  
479      /* supported features bitmap: std sRGB, preferred timing */
480      edid[24] = 0x06;
481  
482  
483      /* =============== chromaticity coordinates =============== */
484  
485      /* standard sRGB colorspace */
486      edid_colorspace(edid,
487                      0.6400, 0.3300,   /* red   */
488                      0.3000, 0.6000,   /* green */
489                      0.1500, 0.0600,   /* blue  */
490                      0.3127, 0.3290);  /* white point  */
491  
492      /* =============== established timing bitmap =============== */
493      /* =============== standard timing information =============== */
494  
495      /* both filled by edid_fill_modes() */
496  
497  
498      /* =============== descriptor blocks =============== */
499  
500      if (!large_screen) {
501          /* The DTD section has only 12 bits to store the resolution */
502          edid_desc_timing(desc, &timings, info->prefx, info->prefy,
503                           width_mm, height_mm);
504          desc = edid_desc_next(edid, dta, desc);
505      }
506  
507      xtra3 = desc;
508      edid_desc_xtra3_std(xtra3);
509      desc = edid_desc_next(edid, dta, desc);
510      edid_fill_modes(edid, xtra3, dta, info->maxx, info->maxy);
511      /*
512       * dta video data block is finished at thus point,
513       * so dta descriptor offsets don't move any more.
514       */
515  
516      edid_desc_ranges(desc);
517      desc = edid_desc_next(edid, dta, desc);
518  
519      if (desc && info->name) {
520          edid_desc_text(desc, 0xfc, info->name);
521          desc = edid_desc_next(edid, dta, desc);
522      }
523  
524      if (desc && info->serial) {
525          edid_desc_text(desc, 0xff, info->serial);
526          desc = edid_desc_next(edid, dta, desc);
527      }
528  
529      while (desc) {
530          edid_desc_dummy(desc);
531          desc = edid_desc_next(edid, dta, desc);
532      }
533  
534      /* =============== display id extensions =============== */
535  
536      if (did && large_screen) {
537          qemu_displayid_generate(did, &timings, info->prefx, info->prefy,
538                                  width_mm, height_mm);
539      }
540  
541      /* =============== finish up =============== */
542  
543      edid_checksum(edid, 127);
544      if (dta) {
545          edid_checksum(dta, 127);
546      }
547      if (did) {
548          edid_checksum(did, 127);
549      }
550  }
551  
qemu_edid_size(uint8_t * edid)552  size_t qemu_edid_size(uint8_t *edid)
553  {
554      uint32_t exts;
555  
556      if (edid[0] != 0x00 ||
557          edid[1] != 0xff) {
558          /* doesn't look like a valid edid block */
559          return 0;
560      }
561  
562      exts = edid[126];
563      return 128 * (exts + 1);
564  }
565