qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

edid-generate.c (15241B)


      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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 */
    247 static void edid_desc_xtra3_std(uint8_t *desc)
    248 {
    249     edid_desc_type(desc, 0xf7);
    250     desc[5] = 10;
    251 }
    252 
    253 static void edid_desc_dummy(uint8_t *desc)
    254 {
    255     edid_desc_type(desc, 0x10);
    256 }
    257 
    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 
    292 static uint32_t edid_to_10bit(float value)
    293 {
    294     return (uint32_t)(value * 1024 + 0.5);
    295 }
    296 
    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 
    330 static uint32_t qemu_edid_dpi_from_mm(uint32_t mm, uint32_t res)
    331 {
    332     return res * 254 / 10 / mm;
    333 }
    334 
    335 uint32_t qemu_edid_dpi_to_mm(uint32_t dpi, uint32_t res)
    336 {
    337     return res * 254 / 10 / dpi;
    338 }
    339 
    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 
    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 
    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 
    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 }