diff options
-rw-r--r-- | drivers/gpu/drm/imx/dpu/dpu-crtc.c | 2 | ||||
-rw-r--r-- | drivers/gpu/imx/dpu/dpu-framegen.c | 45 | ||||
-rw-r--r-- | include/video/dpu.h | 4 |
3 files changed, 38 insertions, 13 deletions
diff --git a/drivers/gpu/drm/imx/dpu/dpu-crtc.c b/drivers/gpu/drm/imx/dpu/dpu-crtc.c index 4c05b8cd3834..01b0a04ca2b6 100644 --- a/drivers/gpu/drm/imx/dpu/dpu-crtc.c +++ b/drivers/gpu/drm/imx/dpu/dpu-crtc.c @@ -455,7 +455,7 @@ static void dpu_crtc_mode_set_nofb(struct drm_crtc *crtc) crtc->base.id, crtc->name, __func__, drm_mode_vrefresh(mode)); - framegen_cfg_videomode(dpu_crtc->fg, mode); + framegen_cfg_videomode(dpu_crtc->fg, mode, DRM_MODE_ENCODER_NONE); framegen_displaymode(dpu_crtc->fg, FGDM__SEC_ON_TOP); framegen_panic_displaymode(dpu_crtc->fg, FGDM__TEST); diff --git a/drivers/gpu/imx/dpu/dpu-framegen.c b/drivers/gpu/imx/dpu/dpu-framegen.c index 21041fe987a5..a64995a4a1ad 100644 --- a/drivers/gpu/imx/dpu/dpu-framegen.c +++ b/drivers/gpu/imx/dpu/dpu-framegen.c @@ -19,6 +19,7 @@ #include <linux/mutex.h> #include <linux/platform_device.h> #include <linux/types.h> +#include <drm/drm_mode.h> #include <video/dpu.h> #include "dpu-prv.h" @@ -92,10 +93,12 @@ struct dpu_framegen { void __iomem *base; struct clk *clk_pll; + struct clk *clk_bypass; struct clk *clk_disp; struct mutex mutex; int id; bool inuse; + bool use_bypass_clk; struct dpu_soc *dpu; }; @@ -151,8 +154,10 @@ void framegen_syncmode(struct dpu_framegen *fg, fgsyncmode_t mode) } EXPORT_SYMBOL_GPL(framegen_syncmode); -void framegen_cfg_videomode(struct dpu_framegen *fg, struct drm_display_mode *m) +void framegen_cfg_videomode(struct dpu_framegen *fg, struct drm_display_mode *m, + unsigned int encoder_type) { + struct dpu_soc *dpu = fg->dpu; u32 hact, htotal, hsync, hsbp; u32 vact, vtotal, vsync, vsbp; u32 kick_row, kick_col; @@ -204,14 +209,28 @@ void framegen_cfg_videomode(struct dpu_framegen *fg, struct drm_display_mode *m) disp_clock_rate = m->clock * 1000; - /* find an even divisor for PLL */ - do { - div += 2; - pll_clock_rate = disp_clock_rate * div; - } while (pll_clock_rate < PLL_MIN_FREQ_HZ); + if (encoder_type == DRM_MODE_ENCODER_TMDS) { + dpu_pxlink_set_mst_addr(dpu, fg->id, 1); + + clk_set_parent(fg->clk_disp, fg->clk_bypass); + + fg->use_bypass_clk = true; + } else { + dpu_pxlink_set_mst_addr(dpu, fg->id, 0); + + clk_set_parent(fg->clk_disp, fg->clk_pll); - clk_set_rate(fg->clk_pll, pll_clock_rate); - clk_set_rate(fg->clk_disp, disp_clock_rate); + /* find an even divisor for PLL */ + do { + div += 2; + pll_clock_rate = disp_clock_rate * div; + } while (pll_clock_rate < PLL_MIN_FREQ_HZ); + + clk_set_rate(fg->clk_pll, pll_clock_rate); + clk_set_rate(fg->clk_disp, disp_clock_rate); + + fg->use_bypass_clk = false; + } } EXPORT_SYMBOL_GPL(framegen_cfg_videomode); @@ -386,14 +405,16 @@ EXPORT_SYMBOL_GPL(framegen_wait_for_secondary_syncup); void framegen_enable_clock(struct dpu_framegen *fg) { - clk_prepare_enable(fg->clk_pll); + if (!fg->use_bypass_clk) + clk_prepare_enable(fg->clk_pll); clk_prepare_enable(fg->clk_disp); } EXPORT_SYMBOL_GPL(framegen_enable_clock); void framegen_disable_clock(struct dpu_framegen *fg) { - clk_disable_unprepare(fg->clk_pll); + if (!fg->use_bypass_clk) + clk_disable_unprepare(fg->clk_pll); clk_disable_unprepare(fg->clk_disp); } EXPORT_SYMBOL_GPL(framegen_disable_clock); @@ -473,6 +494,10 @@ int dpu_fg_init(struct dpu_soc *dpu, unsigned int id, if (IS_ERR(fg->clk_pll)) return PTR_ERR(fg->clk_pll); + fg->clk_bypass = devm_clk_get(dpu->dev, "bypass0"); + if (IS_ERR(fg->clk_bypass)) + return PTR_ERR(fg->clk_bypass); + fg->clk_disp = devm_clk_get(dpu->dev, id ? "disp1" : "disp0"); if (IS_ERR(fg->clk_disp)) return PTR_ERR(fg->clk_disp); diff --git a/include/video/dpu.h b/include/video/dpu.h index fdb74fa57944..ad9d30453a89 100644 --- a/include/video/dpu.h +++ b/include/video/dpu.h @@ -473,8 +473,8 @@ void framegen_enable(struct dpu_framegen *fg); void framegen_disable(struct dpu_framegen *fg); void framegen_shdtokgen(struct dpu_framegen *fg); void framegen_syncmode(struct dpu_framegen *fg, fgsyncmode_t mode); -void -framegen_cfg_videomode(struct dpu_framegen *fg, struct drm_display_mode *m); +void framegen_cfg_videomode(struct dpu_framegen *fg, struct drm_display_mode *m, + unsigned int encoder_type); void framegen_pkickconfig(struct dpu_framegen *fg, bool enable); void framegen_sacfg(struct dpu_framegen *fg, unsigned int x, unsigned int y); void framegen_displaymode(struct dpu_framegen *fg, fgdm_t mode); |