Loading msm/sde/sde_encoder.c +46 −98 Original line number Diff line number Diff line Loading @@ -84,12 +84,9 @@ * Event that signals the start of the transfer. When this event is * received, enable MDP/DSI core clocks and request RSC with CMD state. * Regardless of the previous state, the resource should be in ON state * at the end of this event. * @SDE_ENC_RC_EVENT_FRAME_DONE: * This event happens at INTERRUPT level. * Event signals the end of the data transfer after the PP FRAME_DONE * event. At the end of this event, a delayed work is scheduled to go to * IDLE_PC state after IDLE_POWERCOLLAPSE_DURATION time. * at the end of this event. At the end of this event, a delayed work is * scheduled to go to IDLE_PC state after IDLE_POWERCOLLAPSE_DURATION * ktime. * @SDE_ENC_RC_EVENT_PRE_STOP: * This event happens at NORMAL priority. * This event, when received during the ON state, set RSC to IDLE, and Loading Loading @@ -128,7 +125,6 @@ */ enum sde_enc_rc_events { SDE_ENC_RC_EVENT_KICKOFF = 1, SDE_ENC_RC_EVENT_FRAME_DONE, SDE_ENC_RC_EVENT_PRE_STOP, SDE_ENC_RC_EVENT_STOP, SDE_ENC_RC_EVENT_PRE_MODESET, Loading Loading @@ -1491,6 +1487,45 @@ void sde_encoder_control_idle_pc(struct drm_encoder *drm_enc, bool enable) SDE_EVT32(sde_enc->idle_pc_enabled); } static void _sde_encoder_rc_restart_delayed(struct sde_encoder_virt *sde_enc, u32 sw_event) { struct drm_encoder *drm_enc = &sde_enc->base; struct msm_drm_private *priv; unsigned int lp, idle_pc_duration; struct msm_drm_thread *disp_thread; bool autorefresh_enabled = false; autorefresh_enabled = _sde_encoder_is_autorefresh_enabled(sde_enc); if (autorefresh_enabled) return; /* set idle timeout based on master connector's lp value */ if (sde_enc->cur_master) lp = sde_connector_get_lp( sde_enc->cur_master->connector); else lp = SDE_MODE_DPMS_ON; if (lp == SDE_MODE_DPMS_LP2) idle_pc_duration = IDLE_SHORT_TIMEOUT; else idle_pc_duration = IDLE_POWERCOLLAPSE_DURATION; priv = drm_enc->dev->dev_private; disp_thread = &priv->disp_thread[sde_enc->crtc->index]; kthread_mod_delayed_work( &disp_thread->worker, &sde_enc->delayed_off_work, msecs_to_jiffies(idle_pc_duration)); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, autorefresh_enabled, idle_pc_duration, SDE_EVTLOG_FUNC_CASE2); SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work scheduled\n", sw_event); } static void _sde_encoder_rc_cancel_delayed(struct sde_encoder_virt *sde_enc, u32 sw_event) { Loading @@ -1505,9 +1540,6 @@ static int _sde_encoder_rc_kickoff(struct drm_encoder *drm_enc, { int ret = 0; /* cancel delayed off work, if any */ _sde_encoder_rc_cancel_delayed(sde_enc, sw_event); mutex_lock(&sde_enc->rc_lock); /* return if the resource control is already in ON state */ Loading Loading @@ -1547,88 +1579,13 @@ static int _sde_encoder_rc_kickoff(struct drm_encoder *drm_enc, SDE_ENC_RC_STATE_ON, SDE_EVTLOG_FUNC_CASE1); sde_enc->rc_state = SDE_ENC_RC_STATE_ON; /* restart delayed off work, if required */ _sde_encoder_rc_restart_delayed(sde_enc, sw_event); end: mutex_unlock(&sde_enc->rc_lock); return ret; } static int _sde_encoder_rc_frame_done(struct drm_encoder *drm_enc, u32 sw_event, struct sde_encoder_virt *sde_enc, struct msm_drm_private *priv) { unsigned int lp, idle_pc_duration; struct msm_drm_thread *disp_thread; bool autorefresh_enabled = false; if (!sde_enc->crtc) { SDE_ERROR("invalid crtc, sw_event:%u\n", sw_event); return -EINVAL; } if (sde_enc->crtc->index >= ARRAY_SIZE(priv->disp_thread)) { SDE_ERROR("invalid crtc index :%u\n", sde_enc->crtc->index); return -EINVAL; } disp_thread = &priv->disp_thread[sde_enc->crtc->index]; /* * mutex lock is not used as this event happens at interrupt * context. And locking is not required as, the other events * like KICKOFF and STOP does a wait-for-idle before executing * the resource_control */ if (sde_enc->rc_state != SDE_ENC_RC_STATE_ON) { SDE_ERROR_ENC(sde_enc, "sw_event:%d,rc:%d-unexpected\n", sw_event, sde_enc->rc_state); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, SDE_EVTLOG_ERROR); return -EINVAL; } /* * schedule off work item only when there are no * frames pending */ if (sde_crtc_frame_pending(sde_enc->crtc) > 1) { SDE_DEBUG_ENC(sde_enc, "skip schedule work"); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, SDE_EVTLOG_FUNC_CASE2); return 0; } /* schedule delayed off work if autorefresh is disabled */ if (sde_enc->cur_master && sde_enc->cur_master->ops.is_autorefresh_enabled) autorefresh_enabled = sde_enc->cur_master->ops.is_autorefresh_enabled( sde_enc->cur_master); /* set idle timeout based on master connector's lp value */ if (sde_enc->cur_master) lp = sde_connector_get_lp( sde_enc->cur_master->connector); else lp = SDE_MODE_DPMS_ON; if (lp == SDE_MODE_DPMS_LP2) idle_pc_duration = IDLE_SHORT_TIMEOUT; else idle_pc_duration = IDLE_POWERCOLLAPSE_DURATION; if (!autorefresh_enabled) kthread_mod_delayed_work( &disp_thread->worker, &sde_enc->delayed_off_work, msecs_to_jiffies(idle_pc_duration)); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, autorefresh_enabled, idle_pc_duration, SDE_EVTLOG_FUNC_CASE2); SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work scheduled\n", sw_event); return 0; } static int _sde_encoder_rc_pre_stop(struct drm_encoder *drm_enc, u32 sw_event, struct sde_encoder_virt *sde_enc, bool is_vid_mode) { Loading Loading @@ -1828,6 +1785,8 @@ static int _sde_encoder_rc_idle(struct drm_encoder *drm_enc, SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, sde_crtc_frame_pending(sde_enc->crtc), SDE_EVTLOG_ERROR); _sde_encoder_rc_restart_delayed(sde_enc, SDE_ENC_RC_EVENT_ENTER_IDLE); goto end; } Loading Loading @@ -1965,10 +1924,6 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc, ret = _sde_encoder_rc_kickoff(drm_enc, sw_event, sde_enc, is_vid_mode); break; case SDE_ENC_RC_EVENT_FRAME_DONE: ret = _sde_encoder_rc_frame_done(drm_enc, sw_event, sde_enc, priv); break; case SDE_ENC_RC_EVENT_PRE_STOP: ret = _sde_encoder_rc_pre_stop(drm_enc, sw_event, sde_enc, is_vid_mode); Loading Loading @@ -2965,9 +2920,6 @@ static void sde_encoder_frame_done_callback( } if (trigger) { sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_FRAME_DONE); if (sde_enc->crtc_frame_event_cb) sde_enc->crtc_frame_event_cb( &sde_enc->crtc_frame_event_cb_data, Loading @@ -2976,10 +2928,6 @@ static void sde_encoder_frame_done_callback( atomic_set(&sde_enc->frame_done_cnt[i], 0); } } else if (sde_enc->crtc_frame_event_cb) { if (!is_cmd_mode) sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_FRAME_DONE); sde_enc->crtc_frame_event_cb( &sde_enc->crtc_frame_event_cb_data, event); } Loading Loading
msm/sde/sde_encoder.c +46 −98 Original line number Diff line number Diff line Loading @@ -84,12 +84,9 @@ * Event that signals the start of the transfer. When this event is * received, enable MDP/DSI core clocks and request RSC with CMD state. * Regardless of the previous state, the resource should be in ON state * at the end of this event. * @SDE_ENC_RC_EVENT_FRAME_DONE: * This event happens at INTERRUPT level. * Event signals the end of the data transfer after the PP FRAME_DONE * event. At the end of this event, a delayed work is scheduled to go to * IDLE_PC state after IDLE_POWERCOLLAPSE_DURATION time. * at the end of this event. At the end of this event, a delayed work is * scheduled to go to IDLE_PC state after IDLE_POWERCOLLAPSE_DURATION * ktime. * @SDE_ENC_RC_EVENT_PRE_STOP: * This event happens at NORMAL priority. * This event, when received during the ON state, set RSC to IDLE, and Loading Loading @@ -128,7 +125,6 @@ */ enum sde_enc_rc_events { SDE_ENC_RC_EVENT_KICKOFF = 1, SDE_ENC_RC_EVENT_FRAME_DONE, SDE_ENC_RC_EVENT_PRE_STOP, SDE_ENC_RC_EVENT_STOP, SDE_ENC_RC_EVENT_PRE_MODESET, Loading Loading @@ -1491,6 +1487,45 @@ void sde_encoder_control_idle_pc(struct drm_encoder *drm_enc, bool enable) SDE_EVT32(sde_enc->idle_pc_enabled); } static void _sde_encoder_rc_restart_delayed(struct sde_encoder_virt *sde_enc, u32 sw_event) { struct drm_encoder *drm_enc = &sde_enc->base; struct msm_drm_private *priv; unsigned int lp, idle_pc_duration; struct msm_drm_thread *disp_thread; bool autorefresh_enabled = false; autorefresh_enabled = _sde_encoder_is_autorefresh_enabled(sde_enc); if (autorefresh_enabled) return; /* set idle timeout based on master connector's lp value */ if (sde_enc->cur_master) lp = sde_connector_get_lp( sde_enc->cur_master->connector); else lp = SDE_MODE_DPMS_ON; if (lp == SDE_MODE_DPMS_LP2) idle_pc_duration = IDLE_SHORT_TIMEOUT; else idle_pc_duration = IDLE_POWERCOLLAPSE_DURATION; priv = drm_enc->dev->dev_private; disp_thread = &priv->disp_thread[sde_enc->crtc->index]; kthread_mod_delayed_work( &disp_thread->worker, &sde_enc->delayed_off_work, msecs_to_jiffies(idle_pc_duration)); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, autorefresh_enabled, idle_pc_duration, SDE_EVTLOG_FUNC_CASE2); SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work scheduled\n", sw_event); } static void _sde_encoder_rc_cancel_delayed(struct sde_encoder_virt *sde_enc, u32 sw_event) { Loading @@ -1505,9 +1540,6 @@ static int _sde_encoder_rc_kickoff(struct drm_encoder *drm_enc, { int ret = 0; /* cancel delayed off work, if any */ _sde_encoder_rc_cancel_delayed(sde_enc, sw_event); mutex_lock(&sde_enc->rc_lock); /* return if the resource control is already in ON state */ Loading Loading @@ -1547,88 +1579,13 @@ static int _sde_encoder_rc_kickoff(struct drm_encoder *drm_enc, SDE_ENC_RC_STATE_ON, SDE_EVTLOG_FUNC_CASE1); sde_enc->rc_state = SDE_ENC_RC_STATE_ON; /* restart delayed off work, if required */ _sde_encoder_rc_restart_delayed(sde_enc, sw_event); end: mutex_unlock(&sde_enc->rc_lock); return ret; } static int _sde_encoder_rc_frame_done(struct drm_encoder *drm_enc, u32 sw_event, struct sde_encoder_virt *sde_enc, struct msm_drm_private *priv) { unsigned int lp, idle_pc_duration; struct msm_drm_thread *disp_thread; bool autorefresh_enabled = false; if (!sde_enc->crtc) { SDE_ERROR("invalid crtc, sw_event:%u\n", sw_event); return -EINVAL; } if (sde_enc->crtc->index >= ARRAY_SIZE(priv->disp_thread)) { SDE_ERROR("invalid crtc index :%u\n", sde_enc->crtc->index); return -EINVAL; } disp_thread = &priv->disp_thread[sde_enc->crtc->index]; /* * mutex lock is not used as this event happens at interrupt * context. And locking is not required as, the other events * like KICKOFF and STOP does a wait-for-idle before executing * the resource_control */ if (sde_enc->rc_state != SDE_ENC_RC_STATE_ON) { SDE_ERROR_ENC(sde_enc, "sw_event:%d,rc:%d-unexpected\n", sw_event, sde_enc->rc_state); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, SDE_EVTLOG_ERROR); return -EINVAL; } /* * schedule off work item only when there are no * frames pending */ if (sde_crtc_frame_pending(sde_enc->crtc) > 1) { SDE_DEBUG_ENC(sde_enc, "skip schedule work"); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, SDE_EVTLOG_FUNC_CASE2); return 0; } /* schedule delayed off work if autorefresh is disabled */ if (sde_enc->cur_master && sde_enc->cur_master->ops.is_autorefresh_enabled) autorefresh_enabled = sde_enc->cur_master->ops.is_autorefresh_enabled( sde_enc->cur_master); /* set idle timeout based on master connector's lp value */ if (sde_enc->cur_master) lp = sde_connector_get_lp( sde_enc->cur_master->connector); else lp = SDE_MODE_DPMS_ON; if (lp == SDE_MODE_DPMS_LP2) idle_pc_duration = IDLE_SHORT_TIMEOUT; else idle_pc_duration = IDLE_POWERCOLLAPSE_DURATION; if (!autorefresh_enabled) kthread_mod_delayed_work( &disp_thread->worker, &sde_enc->delayed_off_work, msecs_to_jiffies(idle_pc_duration)); SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, autorefresh_enabled, idle_pc_duration, SDE_EVTLOG_FUNC_CASE2); SDE_DEBUG_ENC(sde_enc, "sw_event:%d, work scheduled\n", sw_event); return 0; } static int _sde_encoder_rc_pre_stop(struct drm_encoder *drm_enc, u32 sw_event, struct sde_encoder_virt *sde_enc, bool is_vid_mode) { Loading Loading @@ -1828,6 +1785,8 @@ static int _sde_encoder_rc_idle(struct drm_encoder *drm_enc, SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state, sde_crtc_frame_pending(sde_enc->crtc), SDE_EVTLOG_ERROR); _sde_encoder_rc_restart_delayed(sde_enc, SDE_ENC_RC_EVENT_ENTER_IDLE); goto end; } Loading Loading @@ -1965,10 +1924,6 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc, ret = _sde_encoder_rc_kickoff(drm_enc, sw_event, sde_enc, is_vid_mode); break; case SDE_ENC_RC_EVENT_FRAME_DONE: ret = _sde_encoder_rc_frame_done(drm_enc, sw_event, sde_enc, priv); break; case SDE_ENC_RC_EVENT_PRE_STOP: ret = _sde_encoder_rc_pre_stop(drm_enc, sw_event, sde_enc, is_vid_mode); Loading Loading @@ -2965,9 +2920,6 @@ static void sde_encoder_frame_done_callback( } if (trigger) { sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_FRAME_DONE); if (sde_enc->crtc_frame_event_cb) sde_enc->crtc_frame_event_cb( &sde_enc->crtc_frame_event_cb_data, Loading @@ -2976,10 +2928,6 @@ static void sde_encoder_frame_done_callback( atomic_set(&sde_enc->frame_done_cnt[i], 0); } } else if (sde_enc->crtc_frame_event_cb) { if (!is_cmd_mode) sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_FRAME_DONE); sde_enc->crtc_frame_event_cb( &sde_enc->crtc_frame_event_cb_data, event); } Loading