@@ -215,6 +215,47 @@ static int _sde_debugfs_fps_status(struct inode *inode, struct file *file)
215215}
216216#endif
217217
218+ static ssize_t early_wakeup_store (struct device * device ,
219+ struct device_attribute * attr , const char * buf , size_t count )
220+ {
221+ struct drm_crtc * crtc ;
222+ struct sde_crtc * sde_crtc ;
223+ struct msm_drm_private * priv ;
224+ u32 crtc_id ;
225+ bool trigger ;
226+
227+ if (!device || !buf || !count ) {
228+ SDE_ERROR ("invalid input param(s)\n" );
229+ return - EINVAL ;
230+ }
231+
232+ if (kstrtobool (buf , & trigger ) < 0 )
233+ return - EINVAL ;
234+
235+ if (!trigger )
236+ return count ;
237+
238+ crtc = dev_get_drvdata (device );
239+ if (!crtc || !crtc -> dev || !crtc -> dev -> dev_private ) {
240+ SDE_ERROR ("invalid crtc\n" );
241+ return - EINVAL ;
242+ }
243+
244+ sde_crtc = to_sde_crtc (crtc );
245+ priv = crtc -> dev -> dev_private ;
246+
247+ crtc_id = drm_crtc_index (crtc );
248+ if (crtc_id >= ARRAY_SIZE (priv -> disp_thread )) {
249+ SDE_ERROR ("invalid crtc index[%d]\n" , crtc_id );
250+ return - EINVAL ;
251+ }
252+
253+ kthread_queue_work (& priv -> disp_thread [crtc_id ].worker ,
254+ & sde_crtc -> early_wakeup_work );
255+
256+ return count ;
257+ }
258+
218259static ssize_t fps_periodicity_ms_store (struct device * device ,
219260 struct device_attribute * attr , const char * buf , size_t count )
220261{
@@ -402,12 +443,14 @@ static DEVICE_ATTR_RO(vsync_event);
402443static DEVICE_ATTR_RO (measured_fps );
403444static DEVICE_ATTR_RW (fps_periodicity_ms );
404445static DEVICE_ATTR_RO (retire_frame_event );
446+ static DEVICE_ATTR_WO (early_wakeup );
405447
406448static struct attribute * sde_crtc_dev_attrs [] = {
407449 & dev_attr_vsync_event .attr ,
408450 & dev_attr_measured_fps .attr ,
409451 & dev_attr_fps_periodicity_ms .attr ,
410452 & dev_attr_retire_frame_event .attr ,
453+ & dev_attr_early_wakeup .attr ,
411454 NULL
412455};
413456
@@ -6262,6 +6305,40 @@ static void __sde_crtc_idle_notify_work(struct kthread_work *work)
62626305 }
62636306}
62646307
6308+ /*
6309+ * __sde_crtc_early_wakeup_work - trigger early wakeup from user space
6310+ */
6311+ static void __sde_crtc_early_wakeup_work (struct kthread_work * work )
6312+ {
6313+ struct sde_crtc * sde_crtc = container_of (work , struct sde_crtc ,
6314+ early_wakeup_work );
6315+ struct drm_crtc * crtc ;
6316+ struct drm_device * dev ;
6317+ struct msm_drm_private * priv ;
6318+ struct sde_kms * sde_kms ;
6319+
6320+ if (!sde_crtc ) {
6321+ SDE_ERROR ("invalid sde crtc\n" );
6322+ return ;
6323+ }
6324+
6325+ if (!sde_crtc -> enabled ) {
6326+ SDE_INFO ("sde crtc is not enabled\n" );
6327+ return ;
6328+ }
6329+
6330+ crtc = & sde_crtc -> base ;
6331+ dev = crtc -> dev ;
6332+ if (!dev ) {
6333+ SDE_ERROR ("invalid drm device\n" );
6334+ return ;
6335+ }
6336+
6337+ priv = dev -> dev_private ;
6338+ sde_kms = to_sde_kms (priv -> kms );
6339+ sde_kms_trigger_early_wakeup (sde_kms , crtc );
6340+ }
6341+
62656342/* initialize crtc */
62666343struct drm_crtc * sde_crtc_init (struct drm_device * dev , struct drm_plane * plane )
62676344{
@@ -6353,6 +6430,8 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane)
63536430
63546431 kthread_init_delayed_work (& sde_crtc -> idle_notify_work ,
63556432 __sde_crtc_idle_notify_work );
6433+ kthread_init_work (& sde_crtc -> early_wakeup_work ,
6434+ __sde_crtc_early_wakeup_work );
63566435
63576436 SDE_DEBUG ("crtc=%d new_llcc=%d, old_llcc=%d\n" ,
63586437 crtc -> base .id ,
0 commit comments