struct completion *m_safety_shdld_done, *s_safety_shdld_done;
struct completion *m_content_shdld_done, *s_content_shdld_done;
struct completion *m_dec_shdld_done, *s_dec_shdld_done;
- unsigned long ret;
+ unsigned long ret, flags;
drm_crtc_vblank_on(crtc);
extdst_pixengcfg_sync_trigger(m_plane_ed);
framegen_shdtokgen(dpu_crtc->m_fg);
+ /* don't relinquish CPU until TCONs are set to operation mode */
+ local_irq_save(flags);
+ preempt_disable();
/* First turn on the slave stream, second the master stream. */
framegen_enable(dpu_crtc->s_fg);
framegen_enable(dpu_crtc->m_fg);
+ /*
+ * TKT320590:
+ * Turn TCONs into operation mode as soon as the first dumb
+ * frame is generated by DPU from the master stream(we don't
+ * relinquish CPU to ensure this). This makes DPRs/PRGs of
+ * the dual stream be able to evade the dumb frames of the
+ * dual stream respectively.
+ */
+ framegen_wait_for_frame_counter_moving(dpu_crtc->m_fg);
+ /* again, slave first, then master */
+ tcon_set_operation_mode(dpu_crtc->s_tcon);
+ tcon_set_operation_mode(dpu_crtc->m_tcon);
+ local_irq_restore(flags);
+ preempt_enable();
+
+ framegen_enable_pixel_link(dpu_crtc->s_fg);
+ framegen_enable_pixel_link(dpu_crtc->m_fg);
if (dpu_crtc->aux_is_master) {
m_safety_shdld_done = &aux_dpu_crtc->safety_shdld_done;
extdst_pixengcfg_sync_trigger(plane_ed);
extdst_pixengcfg_sync_trigger(dpu_crtc->ed);
framegen_shdtokgen(dpu_crtc->fg);
+
+ /* don't relinquish CPU until TCON is set to operation mode */
+ local_irq_save(flags);
+ preempt_disable();
framegen_enable(dpu_crtc->fg);
+ /*
+ * TKT320590:
+ * Turn TCON into operation mode as soon as the first dumb
+ * frame is generated by DPU(we don't relinquish CPU to ensure
+ * this). This makes DPR/PRG be able to evade the frame.
+ */
+ framegen_wait_for_frame_counter_moving(dpu_crtc->fg);
+ tcon_set_operation_mode(dpu_crtc->tcon);
+ local_irq_restore(flags);
+ preempt_enable();
+
+ framegen_enable_pixel_link(dpu_crtc->fg);
shdld_done = &dpu_crtc->safety_shdld_done;
ret = wait_for_completion_timeout(shdld_done, HZ);
crtc->state->event = NULL;
}
- /*
- * TKT320590:
- * Turn TCON into operation mode later after the first dumb frame is
- * generated by DPU. This makes DPR/PRG be able to evade the frame.
- * However, it turns out we have to set the TCON into operation mode
- * first and then wait for Framegen frame counter moving, otherwise,
- * the display pipeline is likely to broken(If pixel combiner is used,
- * one of the two display streams cannot be setup correctly sometimes.
- * If pixel combiner is unused and prefetch engine is used, the first
- * atomic flush after the enablement is likely to fail - content shadow
- * load irq doesn't come.). This is a mysterious issue.
- */
if (dcstate->use_pc) {
- tcon_set_operation_mode(dpu_crtc->m_tcon);
- tcon_set_operation_mode(dpu_crtc->s_tcon);
- framegen_wait_for_frame_counter_moving(dpu_crtc->m_fg);
- framegen_wait_for_frame_counter_moving(dpu_crtc->s_fg);
-
framegen_wait_for_secondary_syncup(dpu_crtc->m_fg);
framegen_wait_for_secondary_syncup(dpu_crtc->s_fg);
"enable - slave FrameGen requests to read empty FIFO\n");
}
} else {
- tcon_set_operation_mode(dpu_crtc->tcon);
- framegen_wait_for_frame_counter_moving(dpu_crtc->fg);
-
framegen_wait_for_secondary_syncup(dpu_crtc->fg);
if (framegen_secondary_requests_to_read_empty_fifo(dpu_crtc->fg)) {
if (dcstate->use_pc) {
tcon_disable_pc(dpu_crtc->tcon);
+ framegen_disable_pixel_link(dpu_crtc->m_fg);
+ framegen_disable_pixel_link(dpu_crtc->s_fg);
+
/* First turn off the master stream, second the slave stream. */
framegen_disable(dpu_crtc->m_fg);
framegen_disable(dpu_crtc->s_fg);
framegen_disable_clock(dpu_crtc->stream_id ?
dpu_crtc->aux_fg : dpu_crtc->fg);
} else {
+ framegen_disable_pixel_link(dpu_crtc->fg);
framegen_disable(dpu_crtc->fg);
framegen_wait_done(dpu_crtc->fg, adjusted_mode);
framegen_disable_clock(dpu_crtc->fg);
}
void framegen_enable(struct dpu_framegen *fg)
+{
+ dpu_fg_write(fg, FGEN, FGENABLE);
+}
+EXPORT_SYMBOL_GPL(framegen_enable);
+
+void framegen_disable(struct dpu_framegen *fg)
+{
+ dpu_fg_write(fg, 0, FGENABLE);
+}
+EXPORT_SYMBOL_GPL(framegen_disable);
+
+void framegen_enable_pixel_link(struct dpu_framegen *fg)
{
struct dpu_soc *dpu = fg->dpu;
const struct dpu_devtype *devtype = dpu->devtype;
- dpu_fg_write(fg, FGEN, FGENABLE);
-
if (!(devtype->has_dual_ldb && fg->encoder_type_has_lvds))
dpu_pixel_link_enable(dpu->id, fg->id);
}
-EXPORT_SYMBOL_GPL(framegen_enable);
+EXPORT_SYMBOL_GPL(framegen_enable_pixel_link);
-void framegen_disable(struct dpu_framegen *fg)
+void framegen_disable_pixel_link(struct dpu_framegen *fg)
{
struct dpu_soc *dpu = fg->dpu;
const struct dpu_devtype *devtype = dpu->devtype;
if (!(devtype->has_dual_ldb && fg->encoder_type_has_lvds))
dpu_pixel_link_disable(dpu->id, fg->id);
-
- dpu_fg_write(fg, 0, FGENABLE);
}
-EXPORT_SYMBOL_GPL(framegen_disable);
+EXPORT_SYMBOL_GPL(framegen_disable_pixel_link);
void framegen_shdtokgen(struct dpu_framegen *fg)
{