diff options
author | Liu Ying <victor.liu@nxp.com> | 2019-12-02 20:02:39 +0800 |
---|---|---|
committer | Liu Ying <victor.liu@nxp.com> | 2019-12-17 14:23:45 +0800 |
commit | f0ee89aa2a457b797e1109de027ca523a6f5895f (patch) | |
tree | a2abda746f6bf3c0543b7c228db75b6ea511a7dc /drivers | |
parent | 0b95f14a8eb2b62f024eb6992089bdd920b11c56 (diff) |
MLK-23107-2 drm/imx: dpu: kms: Disable DPRC repeat_en in ->atomic_flush() where necessary
The SoC designer suggests us to disable DPRC repeat_en right after
FrameGen frame counter moving so that a plane with prefetch engine
can be disabled correctly on-the-fly. This helps the plane be
enabled again later without flashing at the initial several lines
fetched by the plane. The DPRC repeat_en disablement should be done
as soon as the FrameGen frame counter moving, which requires us to
disable preemption and irq. However, based on tests, there is no
malfunction observed without the strict sequence implemented.
So, tag this as FIXME to achieve some simplicity for now.
Reviewed-by: Sandor Yu <Sandor.yu@nxp.com>
Signed-off-by: Liu Ying <victor.liu@nxp.com>
(cherry picked from commit 75a21048bf9eda17d1068a10b3073051a7b7b742)
(cherry picked from commit 33a15d7e666a39743c7b9ca36d329b4e915b47f5)
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/imx/dpu/dpu-crtc.c | 150 |
1 files changed, 103 insertions, 47 deletions
diff --git a/drivers/gpu/drm/imx/dpu/dpu-crtc.c b/drivers/gpu/drm/imx/dpu/dpu-crtc.c index 62be0f48b759..4ace85979756 100644 --- a/drivers/gpu/drm/imx/dpu/dpu-crtc.c +++ b/drivers/gpu/drm/imx/dpu/dpu-crtc.c @@ -685,14 +685,19 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, struct dpu_crtc_state *old_dcstate = to_dpu_crtc_state(old_imx_crtc_state); struct dpu_plane *dplane = to_dpu_plane(crtc->primary); + struct dpu_plane_state *old_dpstate; struct dpu_plane_res *res = &dplane->grp->res; struct dpu_extdst *ed = res->ed[dplane->stream_id], *aux_ed; + struct dpu_fetchunit *fu; + dpu_block_id_t source; struct completion *shdld_done; struct completion *m_content_shdld_done = NULL; struct completion *s_content_shdld_done = NULL; unsigned long ret; int i; bool need_modeset = drm_atomic_crtc_needs_modeset(crtc->state); + bool need_wait4fgfcm = false, need_aux_wait4fgfcm = false; + bool use_prefetch; if (!crtc->state->active && !old_crtc_state->active) return; @@ -700,6 +705,104 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, if (!need_modeset && to_disable_dpu_crc(dcstate, old_dcstate)) dpu_crtc_disable_crc_source(crtc, old_dcstate->use_pc); + /* + * Scan over old plane fetchunits to determine if we + * need to wait for FrameGen frame counter moving in + * the next loop prior to DPRC repeat_en disablement + * or not. + */ + for (i = 0; i < dpu_crtc->hw_plane_num; i++) { + bool aux_source_flag; + + old_dpstate = old_dcstate->dpu_plane_states[i]; + if (!old_dpstate) + continue; + + aux_source_flag = false; +again1: + source = aux_source_flag ? + old_dpstate->aux_source : old_dpstate->source; + use_prefetch = aux_source_flag ? + old_dpstate->use_aux_prefetch : + old_dpstate->use_prefetch; + fu = source_to_fu(res, source); + if (!fu) + return; + + if (!fu->ops->is_enabled(fu) && use_prefetch && !need_modeset) { + if (aux_source_flag) + need_aux_wait4fgfcm = true; + else + need_wait4fgfcm = true; + } + + if (old_dpstate->need_aux_source && !aux_source_flag) { + aux_source_flag = true; + goto again1; + } + } + + for (i = 0; i < dpu_crtc->hw_plane_num; i++) { + struct dpu_fetchunit *fe; + struct dpu_hscaler *hs; + struct dpu_vscaler *vs; + bool aux_source_disable; + + old_dpstate = old_dcstate->dpu_plane_states[i]; + if (!old_dpstate) + continue; + + /* + * Sync with FrameGen frame counter moving so that + * we may disable DPRC repeat_en correctly. + * FIXME: to disable preemption and irq to make sure + * DPRC repeat_en will be disabled ASAP. + */ + if (need_wait4fgfcm || need_aux_wait4fgfcm) + framegen_wait_for_frame_counter_moving( + dcstate->use_pc ? + dpu_crtc->m_fg : dpu_crtc->fg); + + aux_source_disable = false; +again2: + source = aux_source_disable ? + old_dpstate->aux_source : old_dpstate->source; + use_prefetch = aux_source_disable ? + old_dpstate->use_aux_prefetch : + old_dpstate->use_prefetch; + fu = source_to_fu(res, source); + if (!fu) + return; + + if (!fu->ops->is_enabled(fu)) { + fu->ops->set_stream_id(fu, DPU_PLANE_SRC_DISABLED); + if (fu->dprc && use_prefetch) + dprc_disable_repeat_en(fu->dprc); + } + + if (fetchunit_is_fetchdecode(fu)) { + fe = fetchdecode_get_fetcheco(fu); + if (!fe->ops->is_enabled(fe)) + fe->ops->set_stream_id(fe, + DPU_PLANE_SRC_DISABLED); + + hs = fetchdecode_get_hscaler(fu); + if (!hscaler_is_enabled(hs)) + hscaler_set_stream_id(hs, + DPU_PLANE_SRC_DISABLED); + + vs = fetchdecode_get_vscaler(fu); + if (!vscaler_is_enabled(vs)) + vscaler_set_stream_id(vs, + DPU_PLANE_SRC_DISABLED); + } + + if (old_dpstate->need_aux_source && !aux_source_disable) { + aux_source_disable = true; + goto again2; + } + } + if (dcstate->use_pc) { aux_dpu_crtc = dpu_crtc_get_aux_dpu_crtc(dpu_crtc); @@ -785,53 +888,6 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc, } } - for (i = 0; i < dpu_crtc->hw_plane_num; i++) { - struct dpu_plane_state *old_dpstate; - struct dpu_fetchunit *fu; - struct dpu_fetchunit *fe; - struct dpu_hscaler *hs; - struct dpu_vscaler *vs; - dpu_block_id_t source; - bool aux_source_disable; - - old_dpstate = old_dcstate->dpu_plane_states[i]; - if (!old_dpstate) - continue; - - aux_source_disable = false; -again: - source = aux_source_disable ? - old_dpstate->aux_source : old_dpstate->source; - fu = source_to_fu(res, source); - if (!fu) - return; - - if (!fu->ops->is_enabled(fu)) - fu->ops->set_stream_id(fu, DPU_PLANE_SRC_DISABLED); - - if (fetchunit_is_fetchdecode(fu)) { - fe = fetchdecode_get_fetcheco(fu); - if (!fe->ops->is_enabled(fe)) - fe->ops->set_stream_id(fe, - DPU_PLANE_SRC_DISABLED); - - hs = fetchdecode_get_hscaler(fu); - if (!hscaler_is_enabled(hs)) - hscaler_set_stream_id(hs, - DPU_PLANE_SRC_DISABLED); - - vs = fetchdecode_get_vscaler(fu); - if (!vscaler_is_enabled(vs)) - vscaler_set_stream_id(vs, - DPU_PLANE_SRC_DISABLED); - } - - if (old_dpstate->need_aux_source && !aux_source_disable) { - aux_source_disable = true; - goto again; - } - } - if (!need_modeset && to_enable_dpu_crc(dcstate, old_dcstate)) dpu_crtc_enable_crc_source(crtc, dcstate->crc.source, &dcstate->crc.roi); |