For LVDS displays with pre-configured PLL clock, bypass the clock divider calculation by setting ATMEL_XLCDC_CLKBYP flag. For non-LVDS displays, retain existing clock divider calculation logic to determine appropriate clock scaling based on display requirements.
Signed-off-by: Manikandan Muralidharan <[email protected]> --- changes in v3: - Introduce ATMEL_XLCDC_CLKBYP to this series --- .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 65 ++++++++++--------- include/linux/mfd/atmel-hlcdc.h | 1 + 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index 26c9fbdfd871..73ac5ebbe121 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -127,39 +127,44 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c) (adj->crtc_hdisplay - 1) | ((adj->crtc_vdisplay - 1) << 16)); - prate = clk_get_rate(crtc->dc->hlcdc->sys_clk); - mode_rate = adj->crtc_clock * 1000; - if (!crtc->dc->desc->fixed_clksrc) { - prate *= 2; - cfg |= ATMEL_HLCDC_CLKSEL; - mask |= ATMEL_HLCDC_CLKSEL; - } + if (crtc->dc->hlcdc->lvds_pll_clk) { + cfg |= ATMEL_XLCDC_CLKBYP; + mask |= ATMEL_XLCDC_CLKBYP; + } else { + prate = clk_get_rate(crtc->dc->hlcdc->sys_clk); + mode_rate = adj->crtc_clock * 1000; + if (!crtc->dc->desc->fixed_clksrc) { + prate *= 2; + cfg |= ATMEL_HLCDC_CLKSEL; + mask |= ATMEL_HLCDC_CLKSEL; + } - div = DIV_ROUND_UP(prate, mode_rate); - if (div < 2) { - div = 2; - } else if (ATMEL_HLCDC_CLKDIV(div) & ~ATMEL_HLCDC_CLKDIV_MASK) { - /* The divider ended up too big, try a lower base rate. */ - cfg &= ~ATMEL_HLCDC_CLKSEL; - prate /= 2; div = DIV_ROUND_UP(prate, mode_rate); - if (ATMEL_HLCDC_CLKDIV(div) & ~ATMEL_HLCDC_CLKDIV_MASK) - div = ATMEL_HLCDC_CLKDIV_MASK; - } else { - int div_low = prate / mode_rate; - - if (div_low >= 2 && - (10 * (prate / div_low - mode_rate) < - (mode_rate - prate / div))) - /* - * At least 10 times better when using a higher - * frequency than requested, instead of a lower. - * So, go with that. - */ - div = div_low; - } + if (div < 2) { + div = 2; + } else if (ATMEL_HLCDC_CLKDIV(div) & ~ATMEL_HLCDC_CLKDIV_MASK) { + /* The divider ended up too big, try a lower base rate. */ + cfg &= ~ATMEL_HLCDC_CLKSEL; + prate /= 2; + div = DIV_ROUND_UP(prate, mode_rate); + if (ATMEL_HLCDC_CLKDIV(div) & ~ATMEL_HLCDC_CLKDIV_MASK) + div = ATMEL_HLCDC_CLKDIV_MASK; + } else { + int div_low = prate / mode_rate; + + if (div_low >= 2 && + (10 * (prate / div_low - mode_rate) < + (mode_rate - prate / div))) + /* + * At least 10 times better when using a higher + * frequency than requested, instead of a lower. + * So, go with that. + */ + div = div_low; + } - cfg |= ATMEL_HLCDC_CLKDIV(div); + cfg |= ATMEL_HLCDC_CLKDIV(div); + } if (connector && connector->display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) diff --git a/include/linux/mfd/atmel-hlcdc.h b/include/linux/mfd/atmel-hlcdc.h index 07c2081867fd..19504d3ea12c 100644 --- a/include/linux/mfd/atmel-hlcdc.h +++ b/include/linux/mfd/atmel-hlcdc.h @@ -44,6 +44,7 @@ #define ATMEL_XLCDC_HEO_UPDATE BIT(3) #define ATMEL_HLCDC_CLKPOL BIT(0) +#define ATMEL_XLCDC_CLKBYP BIT(1) #define ATMEL_HLCDC_CLKSEL BIT(2) #define ATMEL_HLCDC_CLKPWMSEL BIT(3) #define ATMEL_HLCDC_CGDIS(i) BIT(8 + (i)) -- 2.25.1
