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