Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d86f6e46 authored by Clarence Ip's avatar Clarence Ip
Browse files

drm/msm/sde: switch to lp2 for pm suspend call during lp1



If a pm suspend event is received while the display is in
LP1 power saving mode, switch to LP2 and leave the display
enabled rather than powering off normally. This is to satisfy
"always on" use cases that require the display panel to
be enabled while the rest of the system is suspended.

Change-Id: I2091f9baa159891a612029e01b829c32b0c13c9e
Signed-off-by: default avatarClarence Ip <cip@codeaurora.org>
parent c72985b2
Loading
Loading
Loading
Loading
+8 −91
Original line number Diff line number Diff line
@@ -142,11 +142,6 @@ int msm_atomic_check(struct drm_device *dev,
{
	struct msm_drm_private *priv;

	if (msm_is_suspend_blocked(dev)) {
		DRM_DEBUG("rejecting commit during suspend\n");
		return -EBUSY;
	}

	priv = dev->dev_private;
	if (priv && priv->kms && priv->kms->funcs &&
			priv->kms->funcs->atomic_check)
@@ -1668,12 +1663,8 @@ static struct drm_driver msm_driver = {
static int msm_pm_suspend(struct device *dev)
{
	struct drm_device *ddev;
	struct drm_modeset_acquire_ctx ctx;
	struct drm_connector *conn;
	struct drm_atomic_state *state;
	struct drm_crtc_state *crtc_state;
	struct msm_drm_private *priv;
	int ret = 0;
	struct msm_kms *kms;

	if (!dev)
		return -EINVAL;
@@ -1683,68 +1674,10 @@ static int msm_pm_suspend(struct device *dev)
		return -EINVAL;

	priv = ddev->dev_private;
	SDE_EVT32(0);

	/* acquire modeset lock(s) */
	drm_modeset_acquire_init(&ctx, 0);

retry:
	ret = drm_modeset_lock_all_ctx(ddev, &ctx);
	if (ret)
		goto unlock;

	/* save current state for resume */
	if (priv->suspend_state)
		drm_atomic_state_free(priv->suspend_state);
	priv->suspend_state = drm_atomic_helper_duplicate_state(ddev, &ctx);
	if (IS_ERR_OR_NULL(priv->suspend_state)) {
		DRM_ERROR("failed to back up suspend state\n");
		priv->suspend_state = NULL;
		goto unlock;
	}

	/* create atomic state to disable all CRTCs */
	state = drm_atomic_state_alloc(ddev);
	if (IS_ERR_OR_NULL(state)) {
		DRM_ERROR("failed to allocate crtc disable state\n");
		goto unlock;
	}

	state->acquire_ctx = &ctx;
	drm_for_each_connector(conn, ddev) {

		if (!conn->state || !conn->state->crtc ||
				conn->dpms != DRM_MODE_DPMS_ON)
			continue;

		/* force CRTC to be inactive */
		crtc_state = drm_atomic_get_crtc_state(state,
				conn->state->crtc);
		if (IS_ERR_OR_NULL(crtc_state)) {
			DRM_ERROR("failed to get crtc %d state\n",
					conn->state->crtc->base.id);
			drm_atomic_state_free(state);
			goto unlock;
		}
		crtc_state->active = false;
	}

	/* commit the "disable all" state */
	ret = drm_atomic_commit(state);
	if (ret < 0) {
		DRM_ERROR("failed to disable crtcs, %d\n", ret);
		drm_atomic_state_free(state);
	} else {
		priv->suspend_block = true;
	}
	kms = priv->kms;

unlock:
	if (ret == -EDEADLK) {
		drm_modeset_backoff(&ctx);
		goto retry;
	}
	drm_modeset_drop_locks(&ctx);
	drm_modeset_acquire_fini(&ctx);
	if (kms && kms->funcs && kms->funcs->pm_suspend)
		return kms->funcs->pm_suspend(dev);

	/* disable hot-plug polling */
	drm_kms_helper_poll_disable(ddev);
@@ -1756,7 +1689,7 @@ static int msm_pm_resume(struct device *dev)
{
	struct drm_device *ddev;
	struct msm_drm_private *priv;
	int ret;
	struct msm_kms *kms;

	if (!dev)
		return -EINVAL;
@@ -1766,26 +1699,10 @@ static int msm_pm_resume(struct device *dev)
		return -EINVAL;

	priv = ddev->dev_private;
	kms = priv->kms;

	SDE_EVT32(priv->suspend_state != NULL);

	drm_mode_config_reset(ddev);

	drm_modeset_lock_all(ddev);

	priv->suspend_block = false;

	if (priv->suspend_state) {
		priv->suspend_state->acquire_ctx =
			ddev->mode_config.acquire_ctx;
		ret = drm_atomic_commit(priv->suspend_state);
		if (ret < 0) {
			DRM_ERROR("failed to restore state, %d\n", ret);
			drm_atomic_state_free(priv->suspend_state);
		}
		priv->suspend_state = NULL;
	}
	drm_modeset_unlock_all(ddev);
	if (kms && kms->funcs && kms->funcs->pm_resume)
		return kms->funcs->pm_resume(dev);

	/* enable hot-plug polling */
	drm_kms_helper_poll_enable(ddev);
+4 −25
Original line number Diff line number Diff line
@@ -589,10 +589,6 @@ struct msm_drm_private {
	 */
	struct task_struct *struct_mutex_task;

	/* saved atomic state during system suspend */
	struct drm_atomic_state *suspend_state;
	bool suspend_block;

	/* list of clients waiting for events */
	struct list_head client_event_list;

@@ -603,12 +599,14 @@ struct msm_drm_private {
	struct dentry *debug_root;
};

/* get struct msm_kms * from drm_device * */
#define ddev_to_msm_kms(D) ((D) && (D)->dev_private ? \
		((struct msm_drm_private *)((D)->dev_private))->kms : NULL)

struct msm_format {
	uint32_t pixel_format;
};

int msm_atomic_check(struct drm_device *dev,
		     struct drm_atomic_state *state);
/* callback from wq once fence has passed: */
struct msm_fence_cb {
	struct work_struct work;
@@ -623,25 +621,6 @@ void __msm_fence_worker(struct work_struct *work);
		(_cb)->func = _func;                         \
	} while (0)

static inline bool msm_is_suspend_state(struct drm_device *dev)
{
	if (!dev || !dev->dev_private)
		return false;

	return ((struct msm_drm_private *)dev->dev_private)->suspend_state != 0;
}

static inline bool msm_is_suspend_blocked(struct drm_device *dev)
{
	if (!dev || !dev->dev_private)
		return false;

	if (!msm_is_suspend_state(dev))
		return false;

	return ((struct msm_drm_private *)dev->dev_private)->suspend_block != 0;
}

int msm_atomic_commit(struct drm_device *dev,
		struct drm_atomic_state *state, bool nonblock);

+3 −0
Original line number Diff line number Diff line
@@ -93,6 +93,9 @@ struct msm_kms_funcs {
	void (*lastclose)(struct msm_kms *kms);
	int (*register_events)(struct msm_kms *kms,
			struct drm_mode_object *obj, u32 event, bool en);
	/* pm suspend/resume hooks */
	int (*pm_suspend)(struct device *dev);
	int (*pm_resume)(struct device *dev);
	/* cleanup: */
	void (*destroy)(struct msm_kms *kms);
	/* get address space */
+16 −0
Original line number Diff line number Diff line
@@ -94,6 +94,22 @@ struct msm_property_state {
	struct list_head dirty_list;
};

/**
 * msm_property_index_to_drm_property - get drm property struct from prop index
 * @info: Pointer to property info container struct
 * @property_idx: Property index
 * Returns: drm_property pointer associated with property index
 */
static inline
struct drm_property *msm_property_index_to_drm_property(
		struct msm_property_info *info, uint32_t property_idx)
{
	if (!info || property_idx >= info->property_count)
		return NULL;

	return info->property_array[property_idx];
}

/**
 * msm_property_get_default - query default value of a property
 * @info: Pointer to property info container struct
+33 −0
Original line number Diff line number Diff line
@@ -972,6 +972,39 @@ int sde_connector_get_dpms(struct drm_connector *connector)
	return rc;
}

int sde_connector_set_property_for_commit(struct drm_connector *connector,
		struct drm_atomic_state *atomic_state,
		uint32_t property_idx, uint64_t value)
{
	struct drm_connector_state *state;
	struct drm_property *property;
	struct sde_connector *c_conn;

	if (!connector || !atomic_state) {
		SDE_ERROR("invalid argument(s), conn %d, state %d\n",
				connector != NULL, atomic_state != NULL);
		return -EINVAL;
	}

	c_conn = to_sde_connector(connector);
	property = msm_property_index_to_drm_property(
			&c_conn->property_info, property_idx);
	if (!property) {
		SDE_ERROR("invalid property index %d\n", property_idx);
		return -EINVAL;
	}

	state = drm_atomic_get_connector_state(atomic_state, connector);
	if (IS_ERR_OR_NULL(state)) {
		SDE_ERROR("failed to get conn %d state\n",
				connector->base.id);
		return -EINVAL;
	}

	return drm_atomic_connector_set_property(
			connector, state, property, value);
}

#ifdef CONFIG_DEBUG_FS
/**
 * sde_connector_init_debugfs - initialize connector debugfs
Loading