Merge "disp: msm: sde: move resource state change to display thread"

This commit is contained in:
qctecmdr 2020-02-07 15:10:33 -08:00 committed by Gerrit - the friendly Code Review server
commit 52161a09b6

View File

@ -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
@ -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,
@ -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)
{
@ -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 */
@ -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)
{
@ -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;
}
@ -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);
@ -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,
@ -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);
}