Loading msm/sde/sde_encoder.c +2 −2 Original line number Diff line number Diff line Loading @@ -3362,6 +3362,7 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) sde_enc->phys_encs[i]->cont_splash_enabled = false; sde_enc->phys_encs[i]->connector = NULL; } atomic_set(&sde_enc->frame_done_cnt[i], 0); } sde_enc->cur_master = NULL; Loading Loading @@ -3647,8 +3648,7 @@ static void sde_encoder_frame_done_callback( /* One of the physical encoders has become idle */ for (i = 0; i < sde_enc->num_phys_encs; i++) { if ((sde_enc->phys_encs[i] == ready_phys) || (event & SDE_ENCODER_FRAME_EVENT_ERROR)) { if (sde_enc->phys_encs[i] == ready_phys) { SDE_EVT32_VERBOSE(DRMID(drm_enc), i, atomic_read(&sde_enc->frame_done_cnt[i])); if (!atomic_add_unless( Loading msm/sde/sde_encoder_phys.h +2 −1 Original line number Diff line number Diff line Loading @@ -365,12 +365,12 @@ struct sde_encoder_phys_cmd_autorefresh { * struct sde_encoder_phys_cmd - sub-class of sde_encoder_phys to handle command * mode specific operations * @base: Baseclass physical encoder structure * @intf_idx: Intf Block index used by this phys encoder * @stream_sel: Stream selection for multi-stream interfaces * @pp_timeout_report_cnt: number of pingpong done irq timeout errors * @autorefresh: autorefresh feature state * @pending_vblank_cnt: Atomic counter tracking pending wait for VBLANK * @pending_vblank_wq: Wait queue for blocking until VBLANK received * @wr_ptr_wait_success: log wr_ptr_wait success for release fence trigger */ struct sde_encoder_phys_cmd { struct sde_encoder_phys base; Loading @@ -379,6 +379,7 @@ struct sde_encoder_phys_cmd { struct sde_encoder_phys_cmd_autorefresh autorefresh; atomic_t pending_vblank_cnt; wait_queue_head_t pending_vblank_wq; bool wr_ptr_wait_success; }; /** Loading msm/sde/sde_encoder_phys_cmd.c +31 −27 Original line number Diff line number Diff line Loading @@ -461,20 +461,18 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( conn = phys_enc->connector; if (atomic_read(&phys_enc->pending_kickoff_cnt) == 0) /* decrement the kickoff_cnt before checking for ESD status */ if (!atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0)) return 0; cmd_enc->pp_timeout_report_cnt++; pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt) + 1; SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, cmd_enc->pp_timeout_report_cnt, pending_kickoff_cnt, frame_event); /* decrement the kickoff_cnt before checking for ESD status */ atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); /* check if panel is still sending TE signal or not */ if (sde_connector_esd_status(phys_enc->connector)) goto exit; Loading Loading @@ -651,13 +649,29 @@ static int _sde_encoder_phys_cmd_wait_for_idle( to_sde_encoder_phys_cmd(phys_enc); struct sde_encoder_wait_info wait_info; bool recovery_events; int ret, i, pending_cnt; int ret; struct sde_hw_ctl *ctl; if (!phys_enc) { SDE_ERROR("invalid encoder\n"); return -EINVAL; } ctl = phys_enc->hw_ctl; if (cmd_enc->wr_ptr_wait_success && (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && ctl->ops.get_scheduler_status && (ctl->ops.get_scheduler_status(ctl) & BIT(0)) && atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0) && phys_enc->parent_ops.handle_frame_done) { phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, SDE_ENCODER_FRAME_EVENT_DONE | SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE); return 0; } wait_info.wq = &phys_enc->pending_kickoff_wq; wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt; wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; Loading @@ -671,8 +685,6 @@ static int _sde_encoder_phys_cmd_wait_for_idle( ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_PINGPONG, &wait_info); if (ret == -ETIMEDOUT) { pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); for (i = 0; i < pending_cnt; i++) _sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc, recovery_events); } else if (!ret) { Loading Loading @@ -1368,19 +1380,9 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); } else if ((ret == 0) && (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && ctl->ops.get_scheduler_status && (ctl->ops.get_scheduler_status(ctl) & BIT(0)) && atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0) && phys_enc->parent_ops.handle_frame_done) { phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, SDE_ENCODER_FRAME_EVENT_DONE | SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE); } cmd_enc->wr_ptr_wait_success = (ret == 0) ? true : false; return ret; } Loading Loading @@ -1408,7 +1410,7 @@ static int sde_encoder_phys_cmd_wait_for_tx_complete( static int sde_encoder_phys_cmd_wait_for_commit_done( struct sde_encoder_phys *phys_enc) { int rc = 0; int rc = 0, i, pending_cnt; struct sde_encoder_phys_cmd *cmd_enc; if (!phys_enc) Loading @@ -1421,11 +1423,11 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( rc = _sde_encoder_phys_cmd_wait_for_wr_ptr(phys_enc); if (rc == -ETIMEDOUT) goto wait_for_idle; } if (!rc && sde_encoder_phys_cmd_is_master(phys_enc) && cmd_enc->autorefresh.cfg.enable) rc = _sde_encoder_phys_cmd_wait_for_autorefresh_done(phys_enc); if (cmd_enc->autorefresh.cfg.enable) rc = _sde_encoder_phys_cmd_wait_for_autorefresh_done( phys_enc); } /* wait for posted start or serialize trigger */ if ((atomic_read(&phys_enc->pending_kickoff_cnt) > 1) || Loading @@ -1435,14 +1437,16 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( return rc; wait_for_idle: rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); for (i = 0; i < pending_cnt; i++) rc |= sde_encoder_wait_for_event(phys_enc->parent, MSM_ENC_TX_COMPLETE); if (rc) { SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->frame_trigger_mode, atomic_read(&phys_enc->pending_kickoff_cnt), phys_enc->enable_state, rc); atomic_set(&phys_enc->pending_kickoff_cnt, 0); SDE_ERROR("pp:%d failed wait_for_idle: %d\n", phys_enc->hw_pp->idx - PINGPONG_0, rc); if (phys_enc->enable_state == SDE_ENC_ERR_NEEDS_HW_RESET) Loading Loading
msm/sde/sde_encoder.c +2 −2 Original line number Diff line number Diff line Loading @@ -3362,6 +3362,7 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) sde_enc->phys_encs[i]->cont_splash_enabled = false; sde_enc->phys_encs[i]->connector = NULL; } atomic_set(&sde_enc->frame_done_cnt[i], 0); } sde_enc->cur_master = NULL; Loading Loading @@ -3647,8 +3648,7 @@ static void sde_encoder_frame_done_callback( /* One of the physical encoders has become idle */ for (i = 0; i < sde_enc->num_phys_encs; i++) { if ((sde_enc->phys_encs[i] == ready_phys) || (event & SDE_ENCODER_FRAME_EVENT_ERROR)) { if (sde_enc->phys_encs[i] == ready_phys) { SDE_EVT32_VERBOSE(DRMID(drm_enc), i, atomic_read(&sde_enc->frame_done_cnt[i])); if (!atomic_add_unless( Loading
msm/sde/sde_encoder_phys.h +2 −1 Original line number Diff line number Diff line Loading @@ -365,12 +365,12 @@ struct sde_encoder_phys_cmd_autorefresh { * struct sde_encoder_phys_cmd - sub-class of sde_encoder_phys to handle command * mode specific operations * @base: Baseclass physical encoder structure * @intf_idx: Intf Block index used by this phys encoder * @stream_sel: Stream selection for multi-stream interfaces * @pp_timeout_report_cnt: number of pingpong done irq timeout errors * @autorefresh: autorefresh feature state * @pending_vblank_cnt: Atomic counter tracking pending wait for VBLANK * @pending_vblank_wq: Wait queue for blocking until VBLANK received * @wr_ptr_wait_success: log wr_ptr_wait success for release fence trigger */ struct sde_encoder_phys_cmd { struct sde_encoder_phys base; Loading @@ -379,6 +379,7 @@ struct sde_encoder_phys_cmd { struct sde_encoder_phys_cmd_autorefresh autorefresh; atomic_t pending_vblank_cnt; wait_queue_head_t pending_vblank_wq; bool wr_ptr_wait_success; }; /** Loading
msm/sde/sde_encoder_phys_cmd.c +31 −27 Original line number Diff line number Diff line Loading @@ -461,20 +461,18 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout( conn = phys_enc->connector; if (atomic_read(&phys_enc->pending_kickoff_cnt) == 0) /* decrement the kickoff_cnt before checking for ESD status */ if (!atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0)) return 0; cmd_enc->pp_timeout_report_cnt++; pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt) + 1; SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, cmd_enc->pp_timeout_report_cnt, pending_kickoff_cnt, frame_event); /* decrement the kickoff_cnt before checking for ESD status */ atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0); /* check if panel is still sending TE signal or not */ if (sde_connector_esd_status(phys_enc->connector)) goto exit; Loading Loading @@ -651,13 +649,29 @@ static int _sde_encoder_phys_cmd_wait_for_idle( to_sde_encoder_phys_cmd(phys_enc); struct sde_encoder_wait_info wait_info; bool recovery_events; int ret, i, pending_cnt; int ret; struct sde_hw_ctl *ctl; if (!phys_enc) { SDE_ERROR("invalid encoder\n"); return -EINVAL; } ctl = phys_enc->hw_ctl; if (cmd_enc->wr_ptr_wait_success && (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && ctl->ops.get_scheduler_status && (ctl->ops.get_scheduler_status(ctl) & BIT(0)) && atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0) && phys_enc->parent_ops.handle_frame_done) { phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, SDE_ENCODER_FRAME_EVENT_DONE | SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE); return 0; } wait_info.wq = &phys_enc->pending_kickoff_wq; wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt; wait_info.timeout_ms = KICKOFF_TIMEOUT_MS; Loading @@ -671,8 +685,6 @@ static int _sde_encoder_phys_cmd_wait_for_idle( ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_PINGPONG, &wait_info); if (ret == -ETIMEDOUT) { pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); for (i = 0; i < pending_cnt; i++) _sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc, recovery_events); } else if (!ret) { Loading Loading @@ -1368,19 +1380,9 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr( phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE); } else if ((ret == 0) && (phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) && ctl->ops.get_scheduler_status && (ctl->ops.get_scheduler_status(ctl) & BIT(0)) && atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0) && phys_enc->parent_ops.handle_frame_done) { phys_enc->parent_ops.handle_frame_done( phys_enc->parent, phys_enc, SDE_ENCODER_FRAME_EVENT_DONE | SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE); } cmd_enc->wr_ptr_wait_success = (ret == 0) ? true : false; return ret; } Loading Loading @@ -1408,7 +1410,7 @@ static int sde_encoder_phys_cmd_wait_for_tx_complete( static int sde_encoder_phys_cmd_wait_for_commit_done( struct sde_encoder_phys *phys_enc) { int rc = 0; int rc = 0, i, pending_cnt; struct sde_encoder_phys_cmd *cmd_enc; if (!phys_enc) Loading @@ -1421,11 +1423,11 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( rc = _sde_encoder_phys_cmd_wait_for_wr_ptr(phys_enc); if (rc == -ETIMEDOUT) goto wait_for_idle; } if (!rc && sde_encoder_phys_cmd_is_master(phys_enc) && cmd_enc->autorefresh.cfg.enable) rc = _sde_encoder_phys_cmd_wait_for_autorefresh_done(phys_enc); if (cmd_enc->autorefresh.cfg.enable) rc = _sde_encoder_phys_cmd_wait_for_autorefresh_done( phys_enc); } /* wait for posted start or serialize trigger */ if ((atomic_read(&phys_enc->pending_kickoff_cnt) > 1) || Loading @@ -1435,14 +1437,16 @@ static int sde_encoder_phys_cmd_wait_for_commit_done( return rc; wait_for_idle: rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc); pending_cnt = atomic_read(&phys_enc->pending_kickoff_cnt); for (i = 0; i < pending_cnt; i++) rc |= sde_encoder_wait_for_event(phys_enc->parent, MSM_ENC_TX_COMPLETE); if (rc) { SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0, phys_enc->frame_trigger_mode, atomic_read(&phys_enc->pending_kickoff_cnt), phys_enc->enable_state, rc); atomic_set(&phys_enc->pending_kickoff_cnt, 0); SDE_ERROR("pp:%d failed wait_for_idle: %d\n", phys_enc->hw_pp->idx - PINGPONG_0, rc); if (phys_enc->enable_state == SDE_ENC_ERR_NEEDS_HW_RESET) Loading