aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_edid.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_edid.c')
-rw-r--r--drivers/gpu/drm/drm_edid.c103
1 files changed, 67 insertions, 36 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 3e927ce7557d..ece03fc2d386 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -508,25 +508,10 @@ static void
508cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) 508cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure)
509{ 509{
510 int i, n = 0; 510 int i, n = 0;
511 u8 rev = ext[0x01], d = ext[0x02]; 511 u8 d = ext[0x02];
512 u8 *det_base = ext + d; 512 u8 *det_base = ext + d;
513 513
514 switch (rev) { 514 n = (127 - d) / 18;
515 case 0:
516 /* can't happen */
517 return;
518 case 1:
519 /* have to infer how many blocks we have, check pixel clock */
520 for (i = 0; i < 6; i++)
521 if (det_base[18*i] || det_base[18*i+1])
522 n++;
523 break;
524 default:
525 /* explicit count */
526 n = min(ext[0x03] & 0x0f, 6);
527 break;
528 }
529
530 for (i = 0; i < n; i++) 515 for (i = 0; i < n; i++)
531 cb((struct detailed_timing *)(det_base + 18 * i), closure); 516 cb((struct detailed_timing *)(det_base + 18 * i), closure);
532} 517}
@@ -1319,6 +1304,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
1319 1304
1320#define HDMI_IDENTIFIER 0x000C03 1305#define HDMI_IDENTIFIER 0x000C03
1321#define AUDIO_BLOCK 0x01 1306#define AUDIO_BLOCK 0x01
1307#define VIDEO_BLOCK 0x02
1322#define VENDOR_BLOCK 0x03 1308#define VENDOR_BLOCK 0x03
1323#define SPEAKER_BLOCK 0x04 1309#define SPEAKER_BLOCK 0x04
1324#define EDID_BASIC_AUDIO (1 << 6) 1310#define EDID_BASIC_AUDIO (1 << 6)
@@ -1349,6 +1335,47 @@ u8 *drm_find_cea_extension(struct edid *edid)
1349} 1335}
1350EXPORT_SYMBOL(drm_find_cea_extension); 1336EXPORT_SYMBOL(drm_find_cea_extension);
1351 1337
1338static int
1339do_cea_modes (struct drm_connector *connector, u8 *db, u8 len)
1340{
1341 struct drm_device *dev = connector->dev;
1342 u8 * mode, cea_mode;
1343 int modes = 0;
1344
1345 for (mode = db; mode < db + len; mode++) {
1346 cea_mode = (*mode & 127) - 1; /* CEA modes are numbered 1..127 */
1347 if (cea_mode < drm_num_cea_modes) {
1348 struct drm_display_mode *newmode;
1349 newmode = drm_mode_duplicate(dev,
1350 &edid_cea_modes[cea_mode]);
1351 if (newmode) {
1352 drm_mode_probed_add(connector, newmode);
1353 modes++;
1354 }
1355 }
1356 }
1357
1358 return modes;
1359}
1360
1361static int
1362add_cea_modes(struct drm_connector *connector, struct edid *edid)
1363{
1364 u8 * cea = drm_find_cea_extension(edid);
1365 u8 * db, dbl;
1366 int modes = 0;
1367
1368 if (cea && cea[1] >= 3) {
1369 for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) {
1370 dbl = db[0] & 0x1f;
1371 if (((db[0] & 0xe0) >> 5) == VIDEO_BLOCK)
1372 modes += do_cea_modes (connector, db+1, dbl);
1373 }
1374 }
1375
1376 return modes;
1377}
1378
1352static void 1379static void
1353parse_hdmi_vsdb(struct drm_connector *connector, uint8_t *db) 1380parse_hdmi_vsdb(struct drm_connector *connector, uint8_t *db)
1354{ 1381{
@@ -1432,26 +1459,29 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
1432 eld[18] = edid->prod_code[0]; 1459 eld[18] = edid->prod_code[0];
1433 eld[19] = edid->prod_code[1]; 1460 eld[19] = edid->prod_code[1];
1434 1461
1435 for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) { 1462 if (cea[1] >= 3)
1436 dbl = db[0] & 0x1f; 1463 for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) {
1437 1464 dbl = db[0] & 0x1f;
1438 switch ((db[0] & 0xe0) >> 5) { 1465
1439 case AUDIO_BLOCK: /* Audio Data Block, contains SADs */ 1466 switch ((db[0] & 0xe0) >> 5) {
1440 sad_count = dbl / 3; 1467 case AUDIO_BLOCK:
1441 memcpy(eld + 20 + mnl, &db[1], dbl); 1468 /* Audio Data Block, contains SADs */
1442 break; 1469 sad_count = dbl / 3;
1443 case SPEAKER_BLOCK: /* Speaker Allocation Data Block */ 1470 memcpy(eld + 20 + mnl, &db[1], dbl);
1444 eld[7] = db[1]; 1471 break;
1445 break; 1472 case SPEAKER_BLOCK:
1446 case VENDOR_BLOCK: 1473 /* Speaker Allocation Data Block */
1447 /* HDMI Vendor-Specific Data Block */ 1474 eld[7] = db[1];
1448 if (db[1] == 0x03 && db[2] == 0x0c && db[3] == 0) 1475 break;
1449 parse_hdmi_vsdb(connector, db); 1476 case VENDOR_BLOCK:
1450 break; 1477 /* HDMI Vendor-Specific Data Block */
1451 default: 1478 if (db[1] == 0x03 && db[2] == 0x0c && db[3] == 0)
1452 break; 1479 parse_hdmi_vsdb(connector, db);
1480 break;
1481 default:
1482 break;
1483 }
1453 } 1484 }
1454 }
1455 eld[5] |= sad_count << 4; 1485 eld[5] |= sad_count << 4;
1456 eld[2] = (20 + mnl + sad_count * 3 + 3) / 4; 1486 eld[2] = (20 + mnl + sad_count * 3 + 3) / 4;
1457 1487
@@ -1722,6 +1752,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
1722 num_modes += add_standard_modes(connector, edid); 1752 num_modes += add_standard_modes(connector, edid);
1723 num_modes += add_established_modes(connector, edid); 1753 num_modes += add_established_modes(connector, edid);
1724 num_modes += add_inferred_modes(connector, edid); 1754 num_modes += add_inferred_modes(connector, edid);
1755 num_modes += add_cea_modes(connector, edid);
1725 1756
1726 if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) 1757 if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
1727 edid_fixup_preferred(connector, quirks); 1758 edid_fixup_preferred(connector, quirks);