Loading drivers/gpu/drm/msm/sde/sde_encoder.c +12 −0 Original line number Diff line number Diff line Loading @@ -1512,6 +1512,7 @@ static int _sde_encoder_update_rsc_client( struct drm_crtc *primary_crtc; int pipe = -1; int rc = 0; int wait_refcount; if (!drm_enc || !drm_enc->dev) { SDE_ERROR("invalid encoder arguments\n"); Loading Loading @@ -1599,6 +1600,12 @@ static int _sde_encoder_update_rsc_client( return ret; } if (wait_vblank_crtc_id) wait_refcount = sde_rsc_client_get_vsync_refcount(sde_enc->rsc_client); SDE_EVT32_VERBOSE(DRMID(drm_enc), wait_vblank_crtc_id, wait_refcount, SDE_EVTLOG_FUNC_ENTRY); if (crtc->base.id != wait_vblank_crtc_id) { primary_crtc = drm_crtc_find(drm_enc->dev, wait_vblank_crtc_id); if (!primary_crtc) { Loading Loading @@ -1636,6 +1643,11 @@ static int _sde_encoder_update_rsc_client( SDE_EVT32(DRMID(drm_enc), wait_vblank_crtc_id, wait_count, SDE_EVTLOG_ERROR); if (wait_refcount) sde_rsc_client_reset_vsync_refcount(sde_enc->rsc_client); SDE_EVT32_VERBOSE(DRMID(drm_enc), wait_vblank_crtc_id, wait_refcount, SDE_EVTLOG_FUNC_EXIT); return ret; } Loading drivers/gpu/drm/msm/sde_rsc.c +94 −0 Original line number Diff line number Diff line Loading @@ -561,6 +561,23 @@ static int sde_rsc_switch_to_clk(struct sde_rsc_priv *rsc, msleep(PRIMARY_VBLANK_WORST_CASE_MS); } else { *wait_vblank_crtc_id = rsc->primary_client->crtc_id; /* increase refcount, so we wait for the next vsync */ atomic_inc(&rsc->rsc_vsync_wait); SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait)); } } else if (atomic_read(&rsc->rsc_vsync_wait)) { SDE_EVT32(rsc->primary_client, rsc->current_state, atomic_read(&rsc->rsc_vsync_wait)); /* Wait for the vsync, if the refcount is set */ rc = wait_event_timeout(rsc->rsc_vsync_waitq, atomic_read(&rsc->rsc_vsync_wait) == 0, msecs_to_jiffies(PRIMARY_VBLANK_WORST_CASE_MS*2)); if (!rc) { pr_err("Timeout waiting for vsync\n"); SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait), SDE_EVTLOG_ERROR); } } end: Loading Loading @@ -600,6 +617,23 @@ static int sde_rsc_switch_to_vid(struct sde_rsc_priv *rsc, msleep(PRIMARY_VBLANK_WORST_CASE_MS); } else { *wait_vblank_crtc_id = rsc->primary_client->crtc_id; /* increase refcount, so we wait for the next vsync */ atomic_inc(&rsc->rsc_vsync_wait); SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait)); } } else if (atomic_read(&rsc->rsc_vsync_wait)) { SDE_EVT32(rsc->primary_client, rsc->current_state, atomic_read(&rsc->rsc_vsync_wait)); /* Wait for the vsync, if the refcount is set */ rc = wait_event_timeout(rsc->rsc_vsync_waitq, atomic_read(&rsc->rsc_vsync_wait) == 0, msecs_to_jiffies(PRIMARY_VBLANK_WORST_CASE_MS*2)); if (!rc) { pr_err("Timeout waiting for vsync\n"); SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait), SDE_EVTLOG_ERROR); } } Loading @@ -607,6 +641,65 @@ static int sde_rsc_switch_to_vid(struct sde_rsc_priv *rsc, return rc; } /** * sde_rsc_client_get_vsync_refcount() - returns the status of the vsync * refcount, to signal if the client needs to reset the refcounting logic * @client: Client pointer provided by sde_rsc_client_create(). * * Return: value of the vsync refcount. */ int sde_rsc_client_get_vsync_refcount( struct sde_rsc_client *caller_client) { struct sde_rsc_priv *rsc; if (!caller_client) { pr_err("invalid client for rsc state update\n"); return -EINVAL; } else if (caller_client->rsc_index >= MAX_RSC_COUNT) { pr_err("invalid rsc index\n"); return -EINVAL; } rsc = rsc_prv_list[caller_client->rsc_index]; if (!rsc) return 0; return atomic_read(&rsc->rsc_vsync_wait); } /** * sde_rsc_client_reset_vsync_refcount() - reduces the refcounting * logic that waits for the vsync. * @client: Client pointer provided by sde_rsc_client_create(). * * Return: zero if refcount was already zero. */ int sde_rsc_client_reset_vsync_refcount( struct sde_rsc_client *caller_client) { struct sde_rsc_priv *rsc; int ret; if (!caller_client) { pr_err("invalid client for rsc state update\n"); return -EINVAL; } else if (caller_client->rsc_index >= MAX_RSC_COUNT) { pr_err("invalid rsc index\n"); return -EINVAL; } rsc = rsc_prv_list[caller_client->rsc_index]; if (!rsc) return 0; ret = atomic_add_unless(&rsc->rsc_vsync_wait, -1, 0); wake_up_all(&rsc->rsc_vsync_waitq); SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait)); return ret; } /** * sde_rsc_client_is_state_update_complete() - check if state update is complete * RSC state transition is not complete until HW receives VBLANK signal. This Loading Loading @@ -1307,6 +1400,7 @@ static int sde_rsc_probe(struct platform_device *pdev) INIT_LIST_HEAD(&rsc->client_list); INIT_LIST_HEAD(&rsc->event_list); mutex_init(&rsc->client_lock); init_waitqueue_head(&rsc->rsc_vsync_waitq); pr_info("sde rsc index:%d probed successfully\n", SDE_RSC_INDEX + counter); Loading drivers/gpu/drm/msm/sde_rsc_priv.h +4 −0 Original line number Diff line number Diff line Loading @@ -149,6 +149,8 @@ struct sde_rsc_timer_config { * and ab/ib vote on display rsc * master_drm: Primary client waits for vsync on this drm object based * on crtc id * rsc_vsync_wait: Refcount to indicate if we have to wait for the vsync. * rsc_vsync_waitq: Queue to wait for the vsync. */ struct sde_rsc_priv { u32 version; Loading Loading @@ -177,6 +179,8 @@ struct sde_rsc_priv { struct sde_rsc_client *primary_client; struct drm_device *master_drm; atomic_t rsc_vsync_wait; wait_queue_head_t rsc_vsync_waitq; }; /** Loading include/linux/sde_rsc.h +32 −0 Original line number Diff line number Diff line Loading @@ -185,6 +185,26 @@ int sde_rsc_client_state_update(struct sde_rsc_client *client, struct sde_rsc_cmd_config *config, int crtc_id, int *wait_vblank_crtc_id); /** * sde_rsc_client_get_vsync_refcount() - returns the status of the vsync * refcount, to signal if the client needs to reset the refcounting logic * @client: Client pointer provided by sde_rsc_client_create(). * * Return: true if the state update has completed. */ int sde_rsc_client_get_vsync_refcount( struct sde_rsc_client *caller_client); /** * sde_rsc_client_reset_vsync_refcount() - reduces the refcounting * logic that waits for the vsync. * @client: Client pointer provided by sde_rsc_client_create(). * * Return: true if the state update has completed. */ int sde_rsc_client_reset_vsync_refcount( struct sde_rsc_client *caller_client); /** * sde_rsc_client_is_state_update_complete() - check if state update is complete * RSC state transition is not complete until HW receives VBLANK signal. This Loading Loading @@ -265,6 +285,18 @@ static inline int sde_rsc_client_state_update(struct sde_rsc_client *client, return 0; } int sde_rsc_client_get_vsync_refcount( struct sde_rsc_client *caller_client) { return 0; } int sde_rsc_client_reset_vsync_refcount( struct sde_rsc_client *caller_client) { return 0; } static inline bool sde_rsc_client_is_state_update_complete( struct sde_rsc_client *caller_client) { Loading Loading
drivers/gpu/drm/msm/sde/sde_encoder.c +12 −0 Original line number Diff line number Diff line Loading @@ -1512,6 +1512,7 @@ static int _sde_encoder_update_rsc_client( struct drm_crtc *primary_crtc; int pipe = -1; int rc = 0; int wait_refcount; if (!drm_enc || !drm_enc->dev) { SDE_ERROR("invalid encoder arguments\n"); Loading Loading @@ -1599,6 +1600,12 @@ static int _sde_encoder_update_rsc_client( return ret; } if (wait_vblank_crtc_id) wait_refcount = sde_rsc_client_get_vsync_refcount(sde_enc->rsc_client); SDE_EVT32_VERBOSE(DRMID(drm_enc), wait_vblank_crtc_id, wait_refcount, SDE_EVTLOG_FUNC_ENTRY); if (crtc->base.id != wait_vblank_crtc_id) { primary_crtc = drm_crtc_find(drm_enc->dev, wait_vblank_crtc_id); if (!primary_crtc) { Loading Loading @@ -1636,6 +1643,11 @@ static int _sde_encoder_update_rsc_client( SDE_EVT32(DRMID(drm_enc), wait_vblank_crtc_id, wait_count, SDE_EVTLOG_ERROR); if (wait_refcount) sde_rsc_client_reset_vsync_refcount(sde_enc->rsc_client); SDE_EVT32_VERBOSE(DRMID(drm_enc), wait_vblank_crtc_id, wait_refcount, SDE_EVTLOG_FUNC_EXIT); return ret; } Loading
drivers/gpu/drm/msm/sde_rsc.c +94 −0 Original line number Diff line number Diff line Loading @@ -561,6 +561,23 @@ static int sde_rsc_switch_to_clk(struct sde_rsc_priv *rsc, msleep(PRIMARY_VBLANK_WORST_CASE_MS); } else { *wait_vblank_crtc_id = rsc->primary_client->crtc_id; /* increase refcount, so we wait for the next vsync */ atomic_inc(&rsc->rsc_vsync_wait); SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait)); } } else if (atomic_read(&rsc->rsc_vsync_wait)) { SDE_EVT32(rsc->primary_client, rsc->current_state, atomic_read(&rsc->rsc_vsync_wait)); /* Wait for the vsync, if the refcount is set */ rc = wait_event_timeout(rsc->rsc_vsync_waitq, atomic_read(&rsc->rsc_vsync_wait) == 0, msecs_to_jiffies(PRIMARY_VBLANK_WORST_CASE_MS*2)); if (!rc) { pr_err("Timeout waiting for vsync\n"); SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait), SDE_EVTLOG_ERROR); } } end: Loading Loading @@ -600,6 +617,23 @@ static int sde_rsc_switch_to_vid(struct sde_rsc_priv *rsc, msleep(PRIMARY_VBLANK_WORST_CASE_MS); } else { *wait_vblank_crtc_id = rsc->primary_client->crtc_id; /* increase refcount, so we wait for the next vsync */ atomic_inc(&rsc->rsc_vsync_wait); SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait)); } } else if (atomic_read(&rsc->rsc_vsync_wait)) { SDE_EVT32(rsc->primary_client, rsc->current_state, atomic_read(&rsc->rsc_vsync_wait)); /* Wait for the vsync, if the refcount is set */ rc = wait_event_timeout(rsc->rsc_vsync_waitq, atomic_read(&rsc->rsc_vsync_wait) == 0, msecs_to_jiffies(PRIMARY_VBLANK_WORST_CASE_MS*2)); if (!rc) { pr_err("Timeout waiting for vsync\n"); SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait), SDE_EVTLOG_ERROR); } } Loading @@ -607,6 +641,65 @@ static int sde_rsc_switch_to_vid(struct sde_rsc_priv *rsc, return rc; } /** * sde_rsc_client_get_vsync_refcount() - returns the status of the vsync * refcount, to signal if the client needs to reset the refcounting logic * @client: Client pointer provided by sde_rsc_client_create(). * * Return: value of the vsync refcount. */ int sde_rsc_client_get_vsync_refcount( struct sde_rsc_client *caller_client) { struct sde_rsc_priv *rsc; if (!caller_client) { pr_err("invalid client for rsc state update\n"); return -EINVAL; } else if (caller_client->rsc_index >= MAX_RSC_COUNT) { pr_err("invalid rsc index\n"); return -EINVAL; } rsc = rsc_prv_list[caller_client->rsc_index]; if (!rsc) return 0; return atomic_read(&rsc->rsc_vsync_wait); } /** * sde_rsc_client_reset_vsync_refcount() - reduces the refcounting * logic that waits for the vsync. * @client: Client pointer provided by sde_rsc_client_create(). * * Return: zero if refcount was already zero. */ int sde_rsc_client_reset_vsync_refcount( struct sde_rsc_client *caller_client) { struct sde_rsc_priv *rsc; int ret; if (!caller_client) { pr_err("invalid client for rsc state update\n"); return -EINVAL; } else if (caller_client->rsc_index >= MAX_RSC_COUNT) { pr_err("invalid rsc index\n"); return -EINVAL; } rsc = rsc_prv_list[caller_client->rsc_index]; if (!rsc) return 0; ret = atomic_add_unless(&rsc->rsc_vsync_wait, -1, 0); wake_up_all(&rsc->rsc_vsync_waitq); SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait)); return ret; } /** * sde_rsc_client_is_state_update_complete() - check if state update is complete * RSC state transition is not complete until HW receives VBLANK signal. This Loading Loading @@ -1307,6 +1400,7 @@ static int sde_rsc_probe(struct platform_device *pdev) INIT_LIST_HEAD(&rsc->client_list); INIT_LIST_HEAD(&rsc->event_list); mutex_init(&rsc->client_lock); init_waitqueue_head(&rsc->rsc_vsync_waitq); pr_info("sde rsc index:%d probed successfully\n", SDE_RSC_INDEX + counter); Loading
drivers/gpu/drm/msm/sde_rsc_priv.h +4 −0 Original line number Diff line number Diff line Loading @@ -149,6 +149,8 @@ struct sde_rsc_timer_config { * and ab/ib vote on display rsc * master_drm: Primary client waits for vsync on this drm object based * on crtc id * rsc_vsync_wait: Refcount to indicate if we have to wait for the vsync. * rsc_vsync_waitq: Queue to wait for the vsync. */ struct sde_rsc_priv { u32 version; Loading Loading @@ -177,6 +179,8 @@ struct sde_rsc_priv { struct sde_rsc_client *primary_client; struct drm_device *master_drm; atomic_t rsc_vsync_wait; wait_queue_head_t rsc_vsync_waitq; }; /** Loading
include/linux/sde_rsc.h +32 −0 Original line number Diff line number Diff line Loading @@ -185,6 +185,26 @@ int sde_rsc_client_state_update(struct sde_rsc_client *client, struct sde_rsc_cmd_config *config, int crtc_id, int *wait_vblank_crtc_id); /** * sde_rsc_client_get_vsync_refcount() - returns the status of the vsync * refcount, to signal if the client needs to reset the refcounting logic * @client: Client pointer provided by sde_rsc_client_create(). * * Return: true if the state update has completed. */ int sde_rsc_client_get_vsync_refcount( struct sde_rsc_client *caller_client); /** * sde_rsc_client_reset_vsync_refcount() - reduces the refcounting * logic that waits for the vsync. * @client: Client pointer provided by sde_rsc_client_create(). * * Return: true if the state update has completed. */ int sde_rsc_client_reset_vsync_refcount( struct sde_rsc_client *caller_client); /** * sde_rsc_client_is_state_update_complete() - check if state update is complete * RSC state transition is not complete until HW receives VBLANK signal. This Loading Loading @@ -265,6 +285,18 @@ static inline int sde_rsc_client_state_update(struct sde_rsc_client *client, return 0; } int sde_rsc_client_get_vsync_refcount( struct sde_rsc_client *caller_client) { return 0; } int sde_rsc_client_reset_vsync_refcount( struct sde_rsc_client *caller_client) { return 0; } static inline bool sde_rsc_client_is_state_update_complete( struct sde_rsc_client *caller_client) { Loading