CHROMIUM: drm: rockchip/dw_hdmi-rockchip: Fixup the clock to be what we expect

We allow some amount of slop in dw_hdmi_rockchip_mode_valid().  That's
a good thing since allowing a little bit of slop lets us support a
bunch of extra resolutions.

Originally, we also made a change to the VOP code to add the concept
of slop in there.  That was reasonable, but there was a problem: it
would tend to request clock rates that weren't _exactly_ clock rates
that we thought about.  It's possible that the common clock framework
would map these to PLL rates that we haven't thought about and we
haven't tested for jitter.

Instead of changing VOP, we should probably adjust the clock ourselves
in the mode_fixup function.  That way we'll request the exact clock we
tested and we'll know how the common clock framework will map it.

Change-Id: I56c2b046f76d554aab5eaed7a6b171ea074d6a62
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Yakir Yang <ykk@rock-chips.com>
Reviewed-on: https://chromium-review.googlesource.com/284376
Reviewed-by: Alexandru Stan <amstan@chromium.org>
This commit is contained in:
Yakir Yang
2016-07-16 16:44:26 +08:00
committed by Tao Huang
parent b2b278207a
commit 52f76dc179

View File

@@ -300,7 +300,39 @@ dw_hdmi_rockchip_encoder_mode_fixup(struct drm_encoder *encoder,
const struct drm_display_mode *mode,
struct drm_display_mode *adj_mode)
{
return true;
struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
int pclk = adj_mode->clock * 1000;
int best_diff = INT_MAX;
int best_clock = 0;
int slop;
int i;
/* Pick the best clock */
for (i = 0; i < ARRAY_SIZE(dw_hdmi_rates); i++) {
int diff = dw_hdmi_rates[i] - pclk;
if (diff < 0)
diff = -diff;
if (diff < best_diff) {
best_diff = diff;
best_clock = dw_hdmi_rates[i];
/* Bail early if we're exact */
if (best_diff == 0)
return true;
}
}
/* Double check that it's OK */
slop = CLK_SLOP(pclk);
if ((pclk >= best_clock - slop) && (pclk <= best_clock + slop)) {
adj_mode->clock = DIV_ROUND_UP(best_clock, 1000);
return true;
}
/* Shoudn't be here; we should have said rate wasn't valid */
dev_warn(hdmi->dev, "tried to set invalid rate %d\n", adj_mode->clock);
return false;
}
static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder,