diff options
author | Lespiau, Damien <damien.lespiau@intel.com> | 2013-08-19 11:58:55 -0400 |
---|---|---|
committer | Dave Airlie <airlied@gmail.com> | 2013-08-29 18:40:14 -0400 |
commit | 3f2f653378112c1453c0d83c81746a9225e4bc75 (patch) | |
tree | 27d2a06b1ee7a62078197ec17a8e464a03ec8050 | |
parent | 7ebe1963a063daf30f95752c35244c5d49550aa9 (diff) |
drm: Add support for alternate clocks of 4k modes
v2: Fix hmdi typo (Simon Farnsworth, Ville Syrjälä)
Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Simon Farnsworth <simon.farnsworth@onelan.co.uk>
Reviewed-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Dave Airlie <airlied@gmail.com>
-rw-r--r-- | drivers/gpu/drm/drm_edid.c | 68 |
1 files changed, 62 insertions, 6 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 9de573cd3683..2381abd452f1 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -2409,6 +2409,54 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match) | |||
2409 | } | 2409 | } |
2410 | EXPORT_SYMBOL(drm_match_cea_mode); | 2410 | EXPORT_SYMBOL(drm_match_cea_mode); |
2411 | 2411 | ||
2412 | /* | ||
2413 | * Calculate the alternate clock for HDMI modes (those from the HDMI vendor | ||
2414 | * specific block). | ||
2415 | * | ||
2416 | * It's almost like cea_mode_alternate_clock(), we just need to add an | ||
2417 | * exception for the VIC 4 mode (4096x2160@24Hz): no alternate clock for this | ||
2418 | * one. | ||
2419 | */ | ||
2420 | static unsigned int | ||
2421 | hdmi_mode_alternate_clock(const struct drm_display_mode *hdmi_mode) | ||
2422 | { | ||
2423 | if (hdmi_mode->vdisplay == 4096 && hdmi_mode->hdisplay == 2160) | ||
2424 | return hdmi_mode->clock; | ||
2425 | |||
2426 | return cea_mode_alternate_clock(hdmi_mode); | ||
2427 | } | ||
2428 | |||
2429 | /* | ||
2430 | * drm_match_hdmi_mode - look for a HDMI mode matching given mode | ||
2431 | * @to_match: display mode | ||
2432 | * | ||
2433 | * An HDMI mode is one defined in the HDMI vendor specific block. | ||
2434 | * | ||
2435 | * Returns the HDMI Video ID (VIC) of the mode or 0 if it isn't one. | ||
2436 | */ | ||
2437 | static u8 drm_match_hdmi_mode(const struct drm_display_mode *to_match) | ||
2438 | { | ||
2439 | u8 mode; | ||
2440 | |||
2441 | if (!to_match->clock) | ||
2442 | return 0; | ||
2443 | |||
2444 | for (mode = 0; mode < ARRAY_SIZE(edid_4k_modes); mode++) { | ||
2445 | const struct drm_display_mode *hdmi_mode = &edid_4k_modes[mode]; | ||
2446 | unsigned int clock1, clock2; | ||
2447 | |||
2448 | /* Make sure to also match alternate clocks */ | ||
2449 | clock1 = hdmi_mode->clock; | ||
2450 | clock2 = hdmi_mode_alternate_clock(hdmi_mode); | ||
2451 | |||
2452 | if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) || | ||
2453 | KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) && | ||
2454 | drm_mode_equal_no_clocks(to_match, hdmi_mode)) | ||
2455 | return mode + 1; | ||
2456 | } | ||
2457 | return 0; | ||
2458 | } | ||
2459 | |||
2412 | static int | 2460 | static int |
2413 | add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid) | 2461 | add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid) |
2414 | { | 2462 | { |
@@ -2426,18 +2474,26 @@ add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid) | |||
2426 | * with the alternate clock for certain CEA modes. | 2474 | * with the alternate clock for certain CEA modes. |
2427 | */ | 2475 | */ |
2428 | list_for_each_entry(mode, &connector->probed_modes, head) { | 2476 | list_for_each_entry(mode, &connector->probed_modes, head) { |
2429 | const struct drm_display_mode *cea_mode; | 2477 | const struct drm_display_mode *cea_mode = NULL; |
2430 | struct drm_display_mode *newmode; | 2478 | struct drm_display_mode *newmode; |
2431 | u8 cea_mode_idx = drm_match_cea_mode(mode) - 1; | 2479 | u8 mode_idx = drm_match_cea_mode(mode) - 1; |
2432 | unsigned int clock1, clock2; | 2480 | unsigned int clock1, clock2; |
2433 | 2481 | ||
2434 | if (cea_mode_idx >= ARRAY_SIZE(edid_cea_modes)) | 2482 | if (mode_idx < ARRAY_SIZE(edid_cea_modes)) { |
2435 | continue; | 2483 | cea_mode = &edid_cea_modes[mode_idx]; |
2484 | clock2 = cea_mode_alternate_clock(cea_mode); | ||
2485 | } else { | ||
2486 | mode_idx = drm_match_hdmi_mode(mode) - 1; | ||
2487 | if (mode_idx < ARRAY_SIZE(edid_4k_modes)) { | ||
2488 | cea_mode = &edid_4k_modes[mode_idx]; | ||
2489 | clock2 = hdmi_mode_alternate_clock(cea_mode); | ||
2490 | } | ||
2491 | } | ||
2436 | 2492 | ||
2437 | cea_mode = &edid_cea_modes[cea_mode_idx]; | 2493 | if (!cea_mode) |
2494 | continue; | ||
2438 | 2495 | ||
2439 | clock1 = cea_mode->clock; | 2496 | clock1 = cea_mode->clock; |
2440 | clock2 = cea_mode_alternate_clock(cea_mode); | ||
2441 | 2497 | ||
2442 | if (clock1 == clock2) | 2498 | if (clock1 == clock2) |
2443 | continue; | 2499 | continue; |