Просмотр исходного кода

Merge changes I63392417,I6ca0188d into display-kernel.lnx.5.4

* changes:
  disp: msm: add trace logs in display early wakeup function
  disp: msm: add support for display early wakeup
Linux Build Service Account 5 лет назад
Родитель
Сommit
87f5eca6e0
5 измененных файлов с 140 добавлено и 0 удалено
  1. 53 0
      msm/msm_drv.c
  2. 2 0
      msm/msm_kms.h
  3. 50 0
      msm/sde/sde_encoder.c
  4. 8 0
      msm/sde/sde_encoder.h
  5. 27 0
      msm/sde/sde_kms.c

+ 53 - 0
msm/msm_drv.c

@@ -1626,6 +1626,57 @@ int msm_ioctl_power_ctrl(struct drm_device *dev, void *data,
 	return rc;
 }
 
+/**
+ * msm_ioctl_display_early_wakeup - early wakeup display.
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ */
+int msm_ioctl_display_hint_ops(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_msm_display_hint *display_hint = data;
+	struct drm_msm_early_wakeup early_wakeup;
+	void __user *early_wakeup_usr;
+	struct msm_drm_private *priv;
+	struct msm_kms *kms;
+
+	priv = dev->dev_private;
+	kms = priv->kms;
+
+	if (unlikely(!display_hint)) {
+		DRM_ERROR("invalid ioctl data\n");
+		return -EINVAL;
+	}
+
+	SDE_EVT32(display_hint->hint_flags);
+
+	if (display_hint->hint_flags == DRM_MSM_DISPLAY_EARLY_WAKEUP_HINT) {
+		if (!display_hint->data) {
+			DRM_ERROR("early_wakeup: wrong parameter\n");
+			return -EINVAL;
+		}
+
+		early_wakeup_usr =
+			(void __user *)((uintptr_t)display_hint->data);
+
+		if (copy_from_user(&early_wakeup, early_wakeup_usr,
+				sizeof(early_wakeup))) {
+			DRM_ERROR("early_wakeup: copy from user failed\n");
+			return -EINVAL;
+		}
+
+		SDE_EVT32(early_wakeup.wakeup_hint);
+		if (kms && kms->funcs && kms->funcs->display_early_wakeup
+						&& early_wakeup.wakeup_hint)
+			kms->funcs->display_early_wakeup(dev,
+					early_wakeup.connector_id);
+	}
+
+	return 0;
+}
+
 static const struct drm_ioctl_desc msm_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(MSM_GEM_NEW,      msm_ioctl_gem_new,      DRM_AUTH|DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_PREP, msm_ioctl_gem_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW),
@@ -1639,6 +1690,8 @@ static const struct drm_ioctl_desc msm_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(MSM_RMFB2, msm_ioctl_rmfb2, DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(MSM_POWER_CTRL, msm_ioctl_power_ctrl,
 			DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(MSM_DISPLAY_HINT, msm_ioctl_display_hint_ops,
+			DRM_UNLOCKED),
 };
 
 static const struct vm_operations_struct vm_ops = {

+ 2 - 0
msm/msm_kms.h

@@ -100,6 +100,8 @@ struct msm_kms_funcs {
 	void (*set_encoder_mode)(struct msm_kms *kms,
 				 struct drm_encoder *encoder,
 				 bool cmd_mode);
+	void (*display_early_wakeup)(struct drm_device *dev,
+				const int32_t connector_id);
 	/* pm suspend/resume hooks */
 	int (*pm_suspend)(struct device *dev);
 	int (*pm_resume)(struct device *dev);

+ 50 - 0
msm/sde/sde_encoder.c

@@ -3690,6 +3690,53 @@ static void sde_encoder_input_event_work_handler(struct kthread_work *work)
 			SDE_ENC_RC_EVENT_EARLY_WAKEUP);
 }
 
+static void sde_encoder_early_wakeup_work_handler(struct kthread_work *work)
+{
+	struct sde_encoder_virt *sde_enc = container_of(work,
+			struct sde_encoder_virt, early_wakeup_work);
+
+	if (!sde_enc) {
+		SDE_ERROR("invalid sde encoder\n");
+		return;
+	}
+
+	SDE_ATRACE_BEGIN("encoder_early_wakeup");
+	sde_encoder_resource_control(&sde_enc->base,
+			SDE_ENC_RC_EVENT_EARLY_WAKEUP);
+	SDE_ATRACE_END("encoder_early_wakeup");
+}
+
+void sde_encoder_early_wakeup(struct drm_encoder *drm_enc)
+{
+	struct sde_encoder_virt *sde_enc = NULL;
+	struct msm_drm_thread *disp_thread = NULL;
+	struct msm_drm_private *priv = NULL;
+
+	priv = drm_enc->dev->dev_private;
+	sde_enc = to_sde_encoder_virt(drm_enc);
+
+	if (!sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE)) {
+		SDE_DEBUG_ENC(sde_enc,
+			"should only early wake up command mode display\n");
+		return;
+	}
+
+	if (!sde_enc->crtc || (sde_enc->crtc->index
+			>= ARRAY_SIZE(priv->event_thread))) {
+		SDE_ERROR("invalid CRTC: %d or crtc index: %d\n",
+			sde_enc->crtc == NULL,
+			sde_enc->crtc ? sde_enc->crtc->index : -EINVAL);
+		return;
+	}
+
+	disp_thread = &priv->disp_thread[sde_enc->crtc->index];
+
+	SDE_ATRACE_BEGIN("queue_early_wakeup_work");
+	kthread_queue_work(&disp_thread->worker,
+				&sde_enc->early_wakeup_work);
+	SDE_ATRACE_END("queue_early_wakeup_work");
+}
+
 int sde_encoder_poll_line_counts(struct drm_encoder *drm_enc)
 {
 	static const uint64_t timeout_us = 50000;
@@ -4812,6 +4859,9 @@ struct drm_encoder *sde_encoder_init_with_ops(
 	kthread_init_work(&sde_enc->input_event_work,
 			sde_encoder_input_event_work_handler);
 
+	kthread_init_work(&sde_enc->early_wakeup_work,
+			sde_encoder_early_wakeup_work_handler);
+
 	kthread_init_work(&sde_enc->esd_trigger_work,
 			sde_encoder_esd_trigger_work_handler);
 

+ 8 - 0
msm/sde/sde_encoder.h

@@ -168,6 +168,7 @@ struct sde_encoder_ops {
  * @rc_state:			resource controller state
  * @delayed_off_work:		delayed worker to schedule disabling of
  *				clks and resources after IDLE_TIMEOUT time.
+ * @early_wakeup_work:		worker to handle early wakeup event
  * @input_event_work:		worker to handle input device touch events
  * @esd_trigger_work:		worker to handle esd trigger events
  * @input_handler:			handler for input device events
@@ -234,6 +235,7 @@ struct sde_encoder_virt {
 	struct mutex rc_lock;
 	enum sde_enc_rc_states rc_state;
 	struct kthread_delayed_work delayed_off_work;
+	struct kthread_work early_wakeup_work;
 	struct kthread_work input_event_work;
 	struct kthread_work esd_trigger_work;
 	struct input_handler *input_handler;
@@ -267,6 +269,12 @@ void sde_encoder_get_hw_resources(struct drm_encoder *encoder,
 		struct sde_encoder_hw_resources *hw_res,
 		struct drm_connector_state *conn_state);
 
+/**
+ * sde_encoder_early_wakeup - early wake up display
+ * @encoder:	encoder pointer
+ */
+void sde_encoder_early_wakeup(struct drm_encoder *drm_enc);
+
 /**
  * sde_encoder_register_vblank_callback - provide callback to encoder that
  *	will be called on the next vblank.

+ 27 - 0
msm/sde/sde_kms.c

@@ -3134,6 +3134,32 @@ end:
 	drm_modeset_acquire_fini(&ctx);
 }
 
+
+void sde_kms_display_early_wakeup(struct drm_device *dev,
+				const int32_t connector_id)
+{
+	struct drm_connector_list_iter conn_iter;
+	struct drm_connector *conn;
+	struct drm_encoder *drm_enc;
+
+	drm_connector_list_iter_begin(dev, &conn_iter);
+
+	drm_for_each_connector_iter(conn, &conn_iter) {
+		if (connector_id != DRM_MSM_WAKE_UP_ALL_DISPLAYS &&
+			connector_id != conn->base.id)
+			continue;
+
+		if (conn->state && conn->state->best_encoder)
+			drm_enc = conn->state->best_encoder;
+		else
+			drm_enc = conn->encoder;
+
+		sde_encoder_early_wakeup(drm_enc);
+	}
+
+	drm_connector_list_iter_end(&conn_iter);
+}
+
 static void _sde_kms_pm_suspend_idle_helper(struct sde_kms *sde_kms,
 	struct device *dev)
 {
@@ -3408,6 +3434,7 @@ static const struct msm_kms_funcs kms_funcs = {
 	.atomic_check = sde_kms_atomic_check,
 	.get_format      = sde_get_msm_format,
 	.round_pixclk    = sde_kms_round_pixclk,
+	.display_early_wakeup = sde_kms_display_early_wakeup,
 	.pm_suspend      = sde_kms_pm_suspend,
 	.pm_resume       = sde_kms_pm_resume,
 	.destroy         = sde_kms_destroy,