diff options
author | james qian wang (Arm Technology China) <james.qian.wang@arm.com> | 2019-01-22 11:10:57 +0000 |
---|---|---|
committer | Liviu Dudau <Liviu.Dudau@arm.com> | 2019-04-29 12:35:57 +0100 |
commit | a2491b900d63e3d9774cb1f8baae2ee1fbb75651 (patch) | |
tree | 8a5360473bcfa883853ed48c9e15c2d3cad8a8e1 | |
parent | 59dd6d58a5332daa7af9a4c14defe0a80a9e195d (diff) | |
download | linux-stable-a2491b900d63e3d9774cb1f8baae2ee1fbb75651.tar.gz linux-stable-a2491b900d63e3d9774cb1f8baae2ee1fbb75651.tar.bz2 linux-stable-a2491b900d63e3d9774cb1f8baae2ee1fbb75651.zip |
drm/komeda: Add komeda_crtc_mode_valid/fixup
komeda_crtc_mode_valid compares the input mode->clk with main engine clk
and AXI clk, and reject the mode if the required pixel clk can not be
satisfied by main engine clk and AXI-clk.
Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
-rw-r--r-- | drivers/gpu/drm/arm/display/komeda/komeda_crtc.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c index 40ee45d36ad6..902f3992083e 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c @@ -94,9 +94,61 @@ komeda_crtc_atomic_flush(struct drm_crtc *crtc, komeda_crtc_do_flush(crtc, old); } +static enum drm_mode_status +komeda_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *m) +{ + struct komeda_dev *mdev = crtc->dev->dev_private; + struct komeda_crtc *kcrtc = to_kcrtc(crtc); + struct komeda_pipeline *master = kcrtc->master; + long mode_clk, pxlclk; + + if (m->flags & DRM_MODE_FLAG_INTERLACE) + return MODE_NO_INTERLACE; + + /* main clock/AXI clk must be faster than pxlclk*/ + mode_clk = m->clock * 1000; + pxlclk = clk_round_rate(master->pxlclk, mode_clk); + if (pxlclk != mode_clk) { + DRM_DEBUG_ATOMIC("pxlclk doesn't support %ld Hz\n", mode_clk); + + return MODE_NOCLOCK; + } + + if (clk_round_rate(mdev->mclk, mode_clk) < pxlclk) { + DRM_DEBUG_ATOMIC("mclk can't satisfy the requirement of %s-clk: %ld.\n", + m->name, pxlclk); + + return MODE_CLOCK_HIGH; + } + + if (clk_round_rate(master->aclk, mode_clk) < pxlclk) { + DRM_DEBUG_ATOMIC("aclk can't satisfy the requirement of %s-clk: %ld.\n", + m->name, pxlclk); + + return MODE_CLOCK_HIGH; + } + + return MODE_OK; +} + +static bool komeda_crtc_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *m, + struct drm_display_mode *adjusted_mode) +{ + struct komeda_crtc *kcrtc = to_kcrtc(crtc); + struct komeda_pipeline *master = kcrtc->master; + long mode_clk = m->clock * 1000; + + adjusted_mode->clock = clk_round_rate(master->pxlclk, mode_clk) / 1000; + + return true; +} + struct drm_crtc_helper_funcs komeda_crtc_helper_funcs = { .atomic_check = komeda_crtc_atomic_check, .atomic_flush = komeda_crtc_atomic_flush, + .mode_valid = komeda_crtc_mode_valid, + .mode_fixup = komeda_crtc_mode_fixup, }; static const struct drm_crtc_funcs komeda_crtc_funcs = { |