|
@@ -2545,6 +2545,33 @@ cea_mode_alternate_clock(const struct drm_display_mode *cea_mode)
|
|
|
return clock;
|
|
|
}
|
|
|
|
|
|
+static u8 drm_match_cea_mode_clock_tolerance(const struct drm_display_mode *to_match,
|
|
|
+ unsigned int clock_tolerance)
|
|
|
+{
|
|
|
+ u8 mode;
|
|
|
+
|
|
|
+ if (!to_match->clock)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ for (mode = 0; mode < ARRAY_SIZE(edid_cea_modes); mode++) {
|
|
|
+ const struct drm_display_mode *cea_mode = &edid_cea_modes[mode];
|
|
|
+ unsigned int clock1, clock2;
|
|
|
+
|
|
|
+ /* Check both 60Hz and 59.94Hz */
|
|
|
+ clock1 = cea_mode->clock;
|
|
|
+ clock2 = cea_mode_alternate_clock(cea_mode);
|
|
|
+
|
|
|
+ if (abs(to_match->clock - clock1) > clock_tolerance &&
|
|
|
+ abs(to_match->clock - clock2) > clock_tolerance)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (drm_mode_equal_no_clocks(to_match, cea_mode))
|
|
|
+ return mode + 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* drm_match_cea_mode - look for a CEA mode matching given mode
|
|
|
* @to_match: display mode
|
|
@@ -2609,6 +2636,33 @@ hdmi_mode_alternate_clock(const struct drm_display_mode *hdmi_mode)
|
|
|
return cea_mode_alternate_clock(hdmi_mode);
|
|
|
}
|
|
|
|
|
|
+static u8 drm_match_hdmi_mode_clock_tolerance(const struct drm_display_mode *to_match,
|
|
|
+ unsigned int clock_tolerance)
|
|
|
+{
|
|
|
+ u8 mode;
|
|
|
+
|
|
|
+ if (!to_match->clock)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ for (mode = 0; mode < ARRAY_SIZE(edid_4k_modes); mode++) {
|
|
|
+ const struct drm_display_mode *hdmi_mode = &edid_4k_modes[mode];
|
|
|
+ unsigned int clock1, clock2;
|
|
|
+
|
|
|
+ /* Make sure to also match alternate clocks */
|
|
|
+ clock1 = hdmi_mode->clock;
|
|
|
+ clock2 = hdmi_mode_alternate_clock(hdmi_mode);
|
|
|
+
|
|
|
+ if (abs(to_match->clock - clock1) > clock_tolerance &&
|
|
|
+ abs(to_match->clock - clock2) > clock_tolerance)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (drm_mode_equal_no_clocks(to_match, hdmi_mode))
|
|
|
+ return mode + 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* drm_match_hdmi_mode - look for a HDMI mode matching given mode
|
|
|
* @to_match: display mode
|
|
@@ -3119,14 +3173,18 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
|
|
|
u8 mode_idx;
|
|
|
const char *type;
|
|
|
|
|
|
- mode_idx = drm_match_cea_mode(mode) - 1;
|
|
|
+ /*
|
|
|
+ * allow 5kHz clock difference either way to account for
|
|
|
+ * the 10kHz clock resolution limit of detailed timings.
|
|
|
+ */
|
|
|
+ mode_idx = drm_match_cea_mode_clock_tolerance(mode, 5) - 1;
|
|
|
if (mode_idx < ARRAY_SIZE(edid_cea_modes)) {
|
|
|
type = "CEA";
|
|
|
cea_mode = &edid_cea_modes[mode_idx];
|
|
|
clock1 = cea_mode->clock;
|
|
|
clock2 = cea_mode_alternate_clock(cea_mode);
|
|
|
} else {
|
|
|
- mode_idx = drm_match_hdmi_mode(mode) - 1;
|
|
|
+ mode_idx = drm_match_hdmi_mode_clock_tolerance(mode, 5) - 1;
|
|
|
if (mode_idx < ARRAY_SIZE(edid_4k_modes)) {
|
|
|
type = "HDMI";
|
|
|
cea_mode = &edid_4k_modes[mode_idx];
|