int irq;
struct drm_property *alpha;
+
+ struct completion disable_completion;
};
static void dcss_crtc_reset(struct drm_crtc *crtc)
pm_runtime_get_sync(dcss_crtc->dev->parent);
dcss_ss_enable(dcss, true);
- dcss_dtg_enable(dcss, true);
+ dcss_dtg_enable(dcss, true, NULL);
dcss_ctxld_enable(dcss);
crtc->enabled = true;
drm_crtc_vblank_off(crtc);
dcss_ss_enable(dcss, false);
- dcss_dtg_enable(dcss, false);
+ dcss_dtg_enable(dcss, false, &dcss_crtc->disable_completion);
dcss_ctxld_enable(dcss);
crtc->enabled = false;
+ wait_for_completion_timeout(&dcss_crtc->disable_completion,
+ msecs_to_jiffies(100));
+
pm_runtime_mark_last_busy(dcss_crtc->dev->parent);
pm_runtime_put_autosuspend(dcss_crtc->dev->parent);
}
return crtc->irq;
}
+ init_completion(&crtc->disable_completion);
+
ret = devm_request_irq(crtc->dev, crtc->irq, dcss_crtc_irq_handler,
IRQF_TRIGGER_RISING, "dcss_drm", crtc);
if (ret) {
u32 control_status;
u32 alpha;
+
+ /*
+ * This will be passed on by DRM CRTC so that we can signal when DTG has
+ * been successfully stopped. Otherwise, any modesetting while DTG is
+ * still on may result in unpredictable behavior.
+ */
+ struct completion *dis_completion;
};
static void dcss_dtg_write(struct dcss_dtg_priv *dtg, u32 val, u32 ofs)
dtg->base_reg + DCSS_DTG_TC_CONTROL_STATUS);
dtg->in_use = false;
+
+ complete(dtg->dis_completion);
}
-void dcss_dtg_enable(struct dcss_soc *dcss, bool en)
+void dcss_dtg_enable(struct dcss_soc *dcss, bool en,
+ struct completion *dis_completion)
{
struct dcss_dtg_priv *dtg = dcss->dtg_priv;
if (!en) {
dcss->dcss_disable_callback = dcss_dtg_disable_callback;
+ dtg->dis_completion = dis_completion;
return;
}
dcss->dcss_disable_callback = NULL;
+ dtg->dis_completion = NULL;
dtg->control_status |= DTG_START;
void dcss_dtg_sync_set(struct dcss_soc *dcss, struct videomode *vm);
void dcss_dtg_plane_pos_set(struct dcss_soc *dcss, int ch_num,
int px, int py, int pw, int ph);
-void dcss_dtg_enable(struct dcss_soc *dcss, bool en);
+void dcss_dtg_enable(struct dcss_soc *dcss, bool en,
+ struct completion *dis_completion);
bool dcss_dtg_is_enabled(struct dcss_soc *dcss);
void dcss_dtg_ch_enable(struct dcss_soc *dcss, int ch_num, bool en);
void dcss_dtg_plane_alpha_set(struct dcss_soc *dcss, int ch_num,