diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index db632d493f4f..80ac9cb1096b 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -73,6 +73,55 @@ struct rockchip_hdmi { #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x) +#define CLK_SLOP(clk) ((clk) / 1000) +#define CLK_PLUS_SLOP(clk) ((clk) + CLK_SLOP(clk)) + +static const int dw_hdmi_rates[] = { + 25176471, /* for 25.175 MHz, 0.006% off */ + 25200000, + 27000000, + 28320000, + 30240000, + 31500000, + 32000000, + 33750000, + 36000000, + 40000000, + 49500000, + 50000000, + 54000000, + 57290323, /* for 57.284 MHz, .011 % off */ + 65000000, + 68250000, + 71000000, + 72000000, + 73250000, + 74250000, + 74437500, /* for 74.44 MHz, .003% off */ + 75000000, + 78750000, + 78800000, + 79500000, + 83500000, + 85500000, + 88750000, + 97750000, + 101000000, + 106500000, + 108000000, + 115500000, + 118666667, /* for 118.68 MHz, .011% off */ + 119000000, + 121714286, /* for 121.75 MHz, .029% off */ + 135000000, + 136800000, /* for 136.75 MHz, .037% off */ + 146250000, + 148500000, + 154000000, + 162000000, + 297000000, +}; + static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = { { 30666000, { @@ -215,19 +264,19 @@ static enum drm_mode_status dw_hdmi_rockchip_mode_valid(struct drm_connector *connector, const struct drm_display_mode *mode) { - const struct dw_hdmi_mpll_config *mpll_cfg = rockchip_mpll_cfg; int pclk = mode->clock * 1000; - bool valid = false; + int num_rates = ARRAY_SIZE(dw_hdmi_rates); int i; - for (i = 0; mpll_cfg[i].mpixelclock != (~0UL); i++) { - if (pclk == mpll_cfg[i].mpixelclock) { - valid = true; - break; - } + for (i = 0; i < num_rates; i++) { + int slop = CLK_SLOP(pclk); + + if ((pclk >= dw_hdmi_rates[i] - slop) && + (pclk <= dw_hdmi_rates[i] + slop)) + return MODE_OK; } - return (valid) ? MODE_OK : MODE_BAD; + return MODE_BAD; } static const struct drm_encoder_funcs dw_hdmi_rockchip_encoder_funcs = {