techpack: drm/msm/sde: add sysfs node for trigger wake up early

Add sysfs node on crtc to trigger sde wake up early.
The command to trigger wake up early give in shell:

echo 1 > /sys/class/drm/sde-crtc-*/early_wakeup

Bug: 150196517
Test: trigger wake up and switch display power state
Test: testInflatingEmojiListViewFling
Test: testBrowseContentScroll
Change-Id: I96e6ad73e83e8a9e3e5e65e064c92f8e6a6d63f8
Signed-off-by: Midas Chien <midaschieh@google.com>
Signed-off-by: DennySPb <dennyspb@gmail.com>
Signed-off-by: Karan Parashar <karan@pixelos.net>
This commit is contained in:
Midas Chien 2020-04-22 16:29:32 +08:00 committed by zaidkhan0997
parent 29df08815f
commit a0e90ad8ce
Signed by: zaidkhan0997
GPG Key ID: 6C50557AD547C980
6 changed files with 144 additions and 0 deletions

View File

@ -217,6 +217,47 @@ static int _sde_debugfs_fps_status(struct inode *inode, struct file *file)
}
#endif
static ssize_t early_wakeup_store(struct device *device,
struct device_attribute *attr, const char *buf, size_t count)
{
struct drm_crtc *crtc;
struct sde_crtc *sde_crtc;
struct msm_drm_private *priv;
u32 crtc_id;
bool trigger;
if (!device || !buf || !count) {
SDE_ERROR("invalid input param(s)\n");
return -EINVAL;
}
if (kstrtobool(buf, &trigger) < 0)
return -EINVAL;
if (!trigger)
return count;
crtc = dev_get_drvdata(device);
if (!crtc || !crtc->dev || !crtc->dev->dev_private) {
SDE_ERROR("invalid crtc\n");
return -EINVAL;
}
sde_crtc = to_sde_crtc(crtc);
priv = crtc->dev->dev_private;
crtc_id = drm_crtc_index(crtc);
if (crtc_id >= ARRAY_SIZE(priv->disp_thread)) {
SDE_ERROR("invalid crtc index[%d]\n", crtc_id);
return -EINVAL;
}
kthread_queue_work(&priv->disp_thread[crtc_id].worker,
&sde_crtc->early_wakeup_work);
return count;
}
static ssize_t fps_periodicity_ms_store(struct device *device,
struct device_attribute *attr, const char *buf, size_t count)
{
@ -403,12 +444,14 @@ static DEVICE_ATTR_RO(vsync_event);
static DEVICE_ATTR_RO(measured_fps);
static DEVICE_ATTR_RW(fps_periodicity_ms);
static DEVICE_ATTR_RO(retire_frame_event);
static DEVICE_ATTR_WO(early_wakeup);
static struct attribute *sde_crtc_dev_attrs[] = {
&dev_attr_vsync_event.attr,
&dev_attr_measured_fps.attr,
&dev_attr_fps_periodicity_ms.attr,
&dev_attr_retire_frame_event.attr,
&dev_attr_early_wakeup.attr,
NULL
};
@ -6644,6 +6687,40 @@ void sde_crtc_cancel_delayed_work(struct drm_crtc *crtc)
SDE_EVT32(DRMID(crtc), idle_status, cache_status);
}
/*
* __sde_crtc_early_wakeup_work - trigger early wakeup from user space
*/
static void __sde_crtc_early_wakeup_work(struct kthread_work *work)
{
struct sde_crtc *sde_crtc = container_of(work, struct sde_crtc,
early_wakeup_work);
struct drm_crtc *crtc;
struct drm_device *dev;
struct msm_drm_private *priv;
struct sde_kms *sde_kms;
if (!sde_crtc) {
SDE_ERROR("invalid sde crtc\n");
return;
}
if (!sde_crtc->enabled) {
SDE_INFO("sde crtc is not enabled\n");
return;
}
crtc = &sde_crtc->base;
dev = crtc->dev;
if (!dev) {
SDE_ERROR("invalid drm device\n");
return;
}
priv = dev->dev_private;
sde_kms = to_sde_kms(priv->kms);
sde_kms_trigger_early_wakeup(sde_kms, crtc);
}
/* initialize crtc */
struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane)
{
@ -6740,6 +6817,8 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane)
__sde_crtc_idle_notify_work);
kthread_init_delayed_work(&sde_crtc->static_cache_read_work,
__sde_crtc_static_cache_read_work);
kthread_init_work(&sde_crtc->early_wakeup_work,
__sde_crtc_early_wakeup_work);
SDE_DEBUG("crtc=%d new_llcc=%d, old_llcc=%d\n",
crtc->base.id,

View File

@ -278,6 +278,7 @@ struct sde_crtc_misr_info {
* @misr_frame_count : misr frame count provided by client
* @misr_data : store misr data before turning off the clocks.
* @idle_notify_work: delayed worker to notify idle timeout to user space
* @early_wakeup_work: work to trigger early wakeup
* @power_event : registered power event handle
* @cur_perf : current performance committed to clock/bandwidth driver
* @plane_mask_old: keeps track of the planes used in the previous commit
@ -361,6 +362,7 @@ struct sde_crtc {
bool misr_reconfigure;
u32 misr_frame_count;
struct kthread_delayed_work idle_notify_work;
struct kthread_work early_wakeup_work;
struct sde_power_event *power_event;

View File

@ -5544,3 +5544,27 @@ void sde_encoder_enable_recovery_event(struct drm_encoder *encoder)
sde_enc = to_sde_encoder_virt(encoder);
sde_enc->recovery_events_enabled = true;
}
void sde_encoder_trigger_early_wakeup(struct drm_encoder *drm_enc)
{
struct sde_encoder_virt *sde_enc = NULL;
struct msm_drm_private *priv = NULL;
priv = drm_enc->dev->dev_private;
sde_enc = to_sde_encoder_virt(drm_enc);
if (!sde_enc->crtc || (sde_enc->crtc->index
>= ARRAY_SIZE(priv->disp_thread))) {
SDE_DEBUG_ENC(sde_enc,
"invalid cached CRTC: %d or crtc index: %d\n",
sde_enc->crtc == NULL,
sde_enc->crtc ? sde_enc->crtc->index : -EINVAL);
return;
}
if (sde_enc->rc_state == SDE_ENC_RC_STATE_IDLE) {
SDE_ATRACE_BEGIN("sde_encoder_resource_control");
sde_encoder_resource_control(drm_enc,
SDE_ENC_RC_EVENT_EARLY_WAKEUP);
SDE_ATRACE_END("sde_encoder_resource_control");
}
}

View File

@ -640,4 +640,11 @@ static inline bool sde_encoder_is_widebus_enabled(struct drm_encoder *drm_enc)
sde_enc = to_sde_encoder_virt(drm_enc);
return sde_enc->mode_info.wide_bus_en;
}
/**
* sde_encoder_trigger_early_wakeup - trigger early wake up
* @drm_enc: Pointer to drm encoder structure
*/
void sde_encoder_trigger_early_wakeup(struct drm_encoder *drm_enc);
#endif /* __SDE_ENCODER_H__ */

View File

@ -5129,3 +5129,26 @@ int sde_kms_handle_recovery(struct drm_encoder *encoder)
SDE_EVT32(DRMID(encoder), MSM_ENC_ACTIVE_REGION);
return sde_encoder_wait_for_event(encoder, MSM_ENC_ACTIVE_REGION);
}
void sde_kms_trigger_early_wakeup(struct sde_kms *sde_kms,
struct drm_crtc *crtc)
{
struct msm_drm_private *priv;
struct drm_encoder *drm_enc;
if (!sde_kms || !crtc) {
SDE_ERROR("invalid argument sde_kms %pK crtc %pK\n",
sde_kms, crtc);
return;
}
priv = sde_kms->dev->dev_private;
SDE_ATRACE_BEGIN("sde_kms_trigger_early_wakeup");
drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc->state->encoder_mask)
sde_encoder_trigger_early_wakeup(drm_enc);
if (sde_kms->first_kickoff)
sde_power_scale_reg_bus(&priv->phandle, VOTE_INDEX_HIGH, false);
SDE_ATRACE_END("sde_kms_trigger_early_wakeup");
}

View File

@ -754,4 +754,13 @@ int sde_kms_vm_trusted_prepare_commit(struct sde_kms *sde_kms,
*/
int sde_kms_vm_primary_prepare_commit(struct sde_kms *sde_kms,
struct drm_atomic_state *state);
/**
* sde_kms_trigger_early_wakeup - trigger early wake up
* @sde_kms: pointer to sde_kms structure
* @crtc: pointer to drm_crtc structure
*/
void sde_kms_trigger_early_wakeup(struct sde_kms *sde_kms,
struct drm_crtc *crtc);
#endif /* __sde_kms_H__ */