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 } 565