disp: msm: sde: switch to WD vsync on unexpected panel jitter
Switch to watchdog vsync whenever panel jitter is identified during frame-transfer on command mode display. This would allow the HW to finish processing the frame with watchdog vsync source. Switch back to default vsync source after the frame-transfer is complete. This would help in the MDP hang issues in panels that generate TEs with thresholds greater than the projected jitter. Change-Id: Ic3fa78d90e7f44cb0186857716ac27e72505fd32 Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org>
This commit is contained in:
@@ -1769,6 +1769,9 @@ static void _sde_encoder_update_vsync_source(struct sde_encoder_virt *sde_enc,
|
||||
else
|
||||
vsync_source = sde_enc->te_source;
|
||||
|
||||
SDE_EVT32(DRMID(&sde_enc->base), vsync_source, is_dummy,
|
||||
disp_info->is_te_using_watchdog_timer);
|
||||
|
||||
for (i = 0; i < sde_enc->num_phys_encs; i++) {
|
||||
phys = sde_enc->phys_encs[i];
|
||||
|
||||
@@ -1825,7 +1828,8 @@ static void _sde_encoder_dsc_disable(struct sde_encoder_virt *sde_enc)
|
||||
*/
|
||||
}
|
||||
|
||||
static int _sde_encoder_switch_to_watchdog_vsync(struct drm_encoder *drm_enc)
|
||||
int sde_encoder_helper_switch_vsync(struct drm_encoder *drm_enc,
|
||||
bool watchdog_te)
|
||||
{
|
||||
struct sde_encoder_virt *sde_enc;
|
||||
struct msm_display_info disp_info;
|
||||
@@ -1840,7 +1844,7 @@ static int _sde_encoder_switch_to_watchdog_vsync(struct drm_encoder *drm_enc)
|
||||
sde_encoder_control_te(drm_enc, false);
|
||||
|
||||
memcpy(&disp_info, &sde_enc->disp_info, sizeof(disp_info));
|
||||
disp_info.is_te_using_watchdog_timer = true;
|
||||
disp_info.is_te_using_watchdog_timer = watchdog_te;
|
||||
_sde_encoder_update_vsync_source(sde_enc, &disp_info, false);
|
||||
|
||||
sde_encoder_control_te(drm_enc, true);
|
||||
@@ -1901,7 +1905,7 @@ static int _sde_encoder_rsc_client_update_vsync_wait(
|
||||
* by generating the vsync from watchdog timer.
|
||||
*/
|
||||
if (crtc->base.id == wait_vblank_crtc_id)
|
||||
_sde_encoder_switch_to_watchdog_vsync(drm_enc);
|
||||
sde_encoder_helper_switch_vsync(drm_enc, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5696,6 +5700,28 @@ int sde_encoder_wait_for_event(struct drm_encoder *drm_enc,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sde_encoder_helper_get_jitter_bounds_ns(struct drm_encoder *drm_enc,
|
||||
u64 *l_bound, u64 *u_bound)
|
||||
{
|
||||
struct sde_encoder_virt *sde_enc;
|
||||
u64 jitter_ns, frametime_ns;
|
||||
struct msm_mode_info *info;
|
||||
|
||||
if (!drm_enc) {
|
||||
SDE_ERROR("invalid encoder\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sde_enc = to_sde_encoder_virt(drm_enc);
|
||||
info = &sde_enc->mode_info;
|
||||
|
||||
frametime_ns = (1 * 1000000000) / info->frame_rate;
|
||||
jitter_ns = (info->jitter_numer * frametime_ns) /
|
||||
(info->jitter_denom * 100);
|
||||
*l_bound = frametime_ns - jitter_ns;
|
||||
*u_bound = frametime_ns + jitter_ns;
|
||||
}
|
||||
|
||||
u32 sde_encoder_get_fps(struct drm_encoder *drm_enc)
|
||||
{
|
||||
struct sde_encoder_virt *sde_enc;
|
||||
@@ -5993,12 +6019,12 @@ int sde_encoder_display_failure_notification(struct drm_encoder *enc,
|
||||
kthread_flush_work(&sde_enc->esd_trigger_work);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* panel may stop generating te signal (vsync) during esd failure. rsc
|
||||
* hardware may hang without vsync. Avoid rsc hang by generating the
|
||||
* vsync from watchdog timer instead of panel.
|
||||
*/
|
||||
_sde_encoder_switch_to_watchdog_vsync(enc);
|
||||
sde_encoder_helper_switch_vsync(enc, true);
|
||||
|
||||
if (!skip_pre_kickoff)
|
||||
sde_encoder_wait_for_event(enc, MSM_ENC_TX_COMPLETE);
|
||||
|
Reference in New Issue
Block a user