summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLiu Ying <victor.liu@nxp.com>2019-12-02 20:02:39 +0800
committerLiu Ying <victor.liu@nxp.com>2019-12-17 14:23:45 +0800
commitf0ee89aa2a457b797e1109de027ca523a6f5895f (patch)
treea2abda746f6bf3c0543b7c228db75b6ea511a7dc /drivers
parent0b95f14a8eb2b62f024eb6992089bdd920b11c56 (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.c150
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);