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.c115
1 files changed, 96 insertions, 19 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 9e62bbedb5ad..95d6f4b6967c 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -968,6 +968,9 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid)
968 u8 csum = 0; 968 u8 csum = 0;
969 struct edid *edid = (struct edid *)raw_edid; 969 struct edid *edid = (struct edid *)raw_edid;
970 970
971 if (WARN_ON(!raw_edid))
972 return false;
973
971 if (edid_fixup > 8 || edid_fixup < 0) 974 if (edid_fixup > 8 || edid_fixup < 0)
972 edid_fixup = 6; 975 edid_fixup = 6;
973 976
@@ -1010,15 +1013,15 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid)
1010 break; 1013 break;
1011 } 1014 }
1012 1015
1013 return 1; 1016 return true;
1014 1017
1015bad: 1018bad:
1016 if (raw_edid && print_bad_edid) { 1019 if (print_bad_edid) {
1017 printk(KERN_ERR "Raw EDID:\n"); 1020 printk(KERN_ERR "Raw EDID:\n");
1018 print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1, 1021 print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1,
1019 raw_edid, EDID_LENGTH, false); 1022 raw_edid, EDID_LENGTH, false);
1020 } 1023 }
1021 return 0; 1024 return false;
1022} 1025}
1023EXPORT_SYMBOL(drm_edid_block_valid); 1026EXPORT_SYMBOL(drm_edid_block_valid);
1024 1027
@@ -1706,11 +1709,11 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
1706 return NULL; 1709 return NULL;
1707 1710
1708 if (pt->misc & DRM_EDID_PT_STEREO) { 1711 if (pt->misc & DRM_EDID_PT_STEREO) {
1709 printk(KERN_WARNING "stereo mode not supported\n"); 1712 DRM_DEBUG_KMS("stereo mode not supported\n");
1710 return NULL; 1713 return NULL;
1711 } 1714 }
1712 if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) { 1715 if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
1713 printk(KERN_WARNING "composite sync not supported\n"); 1716 DRM_DEBUG_KMS("composite sync not supported\n");
1714 } 1717 }
1715 1718
1716 /* it is incorrect if hsync/vsync width is zero */ 1719 /* it is incorrect if hsync/vsync width is zero */
@@ -2321,6 +2324,31 @@ u8 *drm_find_cea_extension(struct edid *edid)
2321} 2324}
2322EXPORT_SYMBOL(drm_find_cea_extension); 2325EXPORT_SYMBOL(drm_find_cea_extension);
2323 2326
2327/*
2328 * Calculate the alternate clock for the CEA mode
2329 * (60Hz vs. 59.94Hz etc.)
2330 */
2331static unsigned int
2332cea_mode_alternate_clock(const struct drm_display_mode *cea_mode)
2333{
2334 unsigned int clock = cea_mode->clock;
2335
2336 if (cea_mode->vrefresh % 6 != 0)
2337 return clock;
2338
2339 /*
2340 * edid_cea_modes contains the 59.94Hz
2341 * variant for 240 and 480 line modes,
2342 * and the 60Hz variant otherwise.
2343 */
2344 if (cea_mode->vdisplay == 240 || cea_mode->vdisplay == 480)
2345 clock = clock * 1001 / 1000;
2346 else
2347 clock = DIV_ROUND_UP(clock * 1000, 1001);
2348
2349 return clock;
2350}
2351
2324/** 2352/**
2325 * drm_match_cea_mode - look for a CEA mode matching given mode 2353 * drm_match_cea_mode - look for a CEA mode matching given mode
2326 * @to_match: display mode 2354 * @to_match: display mode
@@ -2339,21 +2367,9 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
2339 const struct drm_display_mode *cea_mode = &edid_cea_modes[mode]; 2367 const struct drm_display_mode *cea_mode = &edid_cea_modes[mode];
2340 unsigned int clock1, clock2; 2368 unsigned int clock1, clock2;
2341 2369
2342 clock1 = clock2 = cea_mode->clock;
2343
2344 /* Check both 60Hz and 59.94Hz */ 2370 /* Check both 60Hz and 59.94Hz */
2345 if (cea_mode->vrefresh % 6 == 0) { 2371 clock1 = cea_mode->clock;
2346 /* 2372 clock2 = cea_mode_alternate_clock(cea_mode);
2347 * edid_cea_modes contains the 59.94Hz
2348 * variant for 240 and 480 line modes,
2349 * and the 60Hz variant otherwise.
2350 */
2351 if (cea_mode->vdisplay == 240 ||
2352 cea_mode->vdisplay == 480)
2353 clock1 = clock1 * 1001 / 1000;
2354 else
2355 clock2 = DIV_ROUND_UP(clock2 * 1000, 1001);
2356 }
2357 2373
2358 if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) || 2374 if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) ||
2359 KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) && 2375 KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) &&
@@ -2364,6 +2380,66 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
2364} 2380}
2365EXPORT_SYMBOL(drm_match_cea_mode); 2381EXPORT_SYMBOL(drm_match_cea_mode);
2366 2382
2383static int
2384add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
2385{
2386 struct drm_device *dev = connector->dev;
2387 struct drm_display_mode *mode, *tmp;
2388 LIST_HEAD(list);
2389 int modes = 0;
2390
2391 /* Don't add CEA modes if the CEA extension block is missing */
2392 if (!drm_find_cea_extension(edid))
2393 return 0;
2394
2395 /*
2396 * Go through all probed modes and create a new mode
2397 * with the alternate clock for certain CEA modes.
2398 */
2399 list_for_each_entry(mode, &connector->probed_modes, head) {
2400 const struct drm_display_mode *cea_mode;
2401 struct drm_display_mode *newmode;
2402 u8 cea_mode_idx = drm_match_cea_mode(mode) - 1;
2403 unsigned int clock1, clock2;
2404
2405 if (cea_mode_idx >= ARRAY_SIZE(edid_cea_modes))
2406 continue;
2407
2408 cea_mode = &edid_cea_modes[cea_mode_idx];
2409
2410 clock1 = cea_mode->clock;
2411 clock2 = cea_mode_alternate_clock(cea_mode);
2412
2413 if (clock1 == clock2)
2414 continue;
2415
2416 if (mode->clock != clock1 && mode->clock != clock2)
2417 continue;
2418
2419 newmode = drm_mode_duplicate(dev, cea_mode);
2420 if (!newmode)
2421 continue;
2422
2423 /*
2424 * The current mode could be either variant. Make
2425 * sure to pick the "other" clock for the new mode.
2426 */
2427 if (mode->clock != clock1)
2428 newmode->clock = clock1;
2429 else
2430 newmode->clock = clock2;
2431
2432 list_add_tail(&newmode->head, &list);
2433 }
2434
2435 list_for_each_entry_safe(mode, tmp, &list, head) {
2436 list_del(&mode->head);
2437 drm_mode_probed_add(connector, mode);
2438 modes++;
2439 }
2440
2441 return modes;
2442}
2367 2443
2368static int 2444static int
2369do_cea_modes (struct drm_connector *connector, u8 *db, u8 len) 2445do_cea_modes (struct drm_connector *connector, u8 *db, u8 len)
@@ -2946,6 +3022,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
2946 if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) 3022 if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
2947 num_modes += add_inferred_modes(connector, edid); 3023 num_modes += add_inferred_modes(connector, edid);
2948 num_modes += add_cea_modes(connector, edid); 3024 num_modes += add_cea_modes(connector, edid);
3025 num_modes += add_alternate_cea_modes(connector, edid);
2949 3026
2950 if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) 3027 if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
2951 edid_fixup_preferred(connector, quirks); 3028 edid_fixup_preferred(connector, quirks);