aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/drm_edid.c62
-rw-r--r--drivers/gpu/drm/drm_modes.c19
2 files changed, 78 insertions, 3 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index d5d2c03fd136..c214f1246cb4 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2545,6 +2545,33 @@ cea_mode_alternate_clock(const struct drm_display_mode *cea_mode)
2545 return clock; 2545 return clock;
2546} 2546}
2547 2547
2548static u8 drm_match_cea_mode_clock_tolerance(const struct drm_display_mode *to_match,
2549 unsigned int clock_tolerance)
2550{
2551 u8 mode;
2552
2553 if (!to_match->clock)
2554 return 0;
2555
2556 for (mode = 0; mode < ARRAY_SIZE(edid_cea_modes); mode++) {
2557 const struct drm_display_mode *cea_mode = &edid_cea_modes[mode];
2558 unsigned int clock1, clock2;
2559
2560 /* Check both 60Hz and 59.94Hz */
2561 clock1 = cea_mode->clock;
2562 clock2 = cea_mode_alternate_clock(cea_mode);
2563
2564 if (abs(to_match->clock - clock1) > clock_tolerance &&
2565 abs(to_match->clock - clock2) > clock_tolerance)
2566 continue;
2567
2568 if (drm_mode_equal_no_clocks(to_match, cea_mode))
2569 return mode + 1;
2570 }
2571
2572 return 0;
2573}
2574
2548/** 2575/**
2549 * drm_match_cea_mode - look for a CEA mode matching given mode 2576 * drm_match_cea_mode - look for a CEA mode matching given mode
2550 * @to_match: display mode 2577 * @to_match: display mode
@@ -2609,6 +2636,33 @@ hdmi_mode_alternate_clock(const struct drm_display_mode *hdmi_mode)
2609 return cea_mode_alternate_clock(hdmi_mode); 2636 return cea_mode_alternate_clock(hdmi_mode);
2610} 2637}
2611 2638
2639static u8 drm_match_hdmi_mode_clock_tolerance(const struct drm_display_mode *to_match,
2640 unsigned int clock_tolerance)
2641{
2642 u8 mode;
2643
2644 if (!to_match->clock)
2645 return 0;
2646
2647 for (mode = 0; mode < ARRAY_SIZE(edid_4k_modes); mode++) {
2648 const struct drm_display_mode *hdmi_mode = &edid_4k_modes[mode];
2649 unsigned int clock1, clock2;
2650
2651 /* Make sure to also match alternate clocks */
2652 clock1 = hdmi_mode->clock;
2653 clock2 = hdmi_mode_alternate_clock(hdmi_mode);
2654
2655 if (abs(to_match->clock - clock1) > clock_tolerance &&
2656 abs(to_match->clock - clock2) > clock_tolerance)
2657 continue;
2658
2659 if (drm_mode_equal_no_clocks(to_match, hdmi_mode))
2660 return mode + 1;
2661 }
2662
2663 return 0;
2664}
2665
2612/* 2666/*
2613 * drm_match_hdmi_mode - look for a HDMI mode matching given mode 2667 * drm_match_hdmi_mode - look for a HDMI mode matching given mode
2614 * @to_match: display mode 2668 * @to_match: display mode
@@ -3119,14 +3173,18 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
3119 u8 mode_idx; 3173 u8 mode_idx;
3120 const char *type; 3174 const char *type;
3121 3175
3122 mode_idx = drm_match_cea_mode(mode) - 1; 3176 /*
3177 * allow 5kHz clock difference either way to account for
3178 * the 10kHz clock resolution limit of detailed timings.
3179 */
3180 mode_idx = drm_match_cea_mode_clock_tolerance(mode, 5) - 1;
3123 if (mode_idx < ARRAY_SIZE(edid_cea_modes)) { 3181 if (mode_idx < ARRAY_SIZE(edid_cea_modes)) {
3124 type = "CEA"; 3182 type = "CEA";
3125 cea_mode = &edid_cea_modes[mode_idx]; 3183 cea_mode = &edid_cea_modes[mode_idx];
3126 clock1 = cea_mode->clock; 3184 clock1 = cea_mode->clock;
3127 clock2 = cea_mode_alternate_clock(cea_mode); 3185 clock2 = cea_mode_alternate_clock(cea_mode);
3128 } else { 3186 } else {
3129 mode_idx = drm_match_hdmi_mode(mode) - 1; 3187 mode_idx = drm_match_hdmi_mode_clock_tolerance(mode, 5) - 1;
3130 if (mode_idx < ARRAY_SIZE(edid_4k_modes)) { 3188 if (mode_idx < ARRAY_SIZE(edid_4k_modes)) {
3131 type = "HDMI"; 3189 type = "HDMI";
3132 cea_mode = &edid_4k_modes[mode_idx]; 3190 cea_mode = &edid_4k_modes[mode_idx];
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index bde9b2911dc2..ef6bd3656548 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -917,13 +917,30 @@ bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_displ
917 } else if (mode1->clock != mode2->clock) 917 } else if (mode1->clock != mode2->clock)
918 return false; 918 return false;
919 919
920 return drm_mode_equal_no_clocks(mode1, mode2);
921}
922EXPORT_SYMBOL(drm_mode_equal);
923
924/**
925 * drm_mode_equal_no_clocks - test modes for equality
926 * @mode1: first mode
927 * @mode2: second mode
928 *
929 * Check to see if @mode1 and @mode2 are equivalent, but
930 * don't check the pixel clocks.
931 *
932 * Returns:
933 * True if the modes are equal, false otherwise.
934 */
935bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2)
936{
920 if ((mode1->flags & DRM_MODE_FLAG_3D_MASK) != 937 if ((mode1->flags & DRM_MODE_FLAG_3D_MASK) !=
921 (mode2->flags & DRM_MODE_FLAG_3D_MASK)) 938 (mode2->flags & DRM_MODE_FLAG_3D_MASK))
922 return false; 939 return false;
923 940
924 return drm_mode_equal_no_clocks_no_stereo(mode1, mode2); 941 return drm_mode_equal_no_clocks_no_stereo(mode1, mode2);
925} 942}
926EXPORT_SYMBOL(drm_mode_equal); 943EXPORT_SYMBOL(drm_mode_equal_no_clocks);
927 944
928/** 945/**
929 * drm_mode_equal_no_clocks_no_stereo - test modes for equality 946 * drm_mode_equal_no_clocks_no_stereo - test modes for equality