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

Commit fbedad9e authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: add connector support for power modes"

parents ce5aff17 3a40770d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -162,6 +162,7 @@ enum msm_mdp_conn_property {
	/* enum/bitmask properties */
	CONNECTOR_PROP_TOPOLOGY_NAME,
	CONNECTOR_PROP_TOPOLOGY_CONTROL,
	CONNECTOR_PROP_LP,

	/* total # of properties */
	CONNECTOR_PROP_COUNT
+140 −7
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@
 * GNU General Public License for more details.
 */

#define pr_fmt(fmt)	"sde-drm:[%s] " fmt, __func__
#define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__
#include "msm_drv.h"

#include "sde_kms.h"
@@ -38,6 +38,13 @@ static const struct drm_prop_enum_list e_topology_control[] = {
	{SDE_RM_TOPCTL_PPSPLIT,		"ppsplit"}
};

static const struct drm_prop_enum_list e_power_mode[] = {
	{SDE_MODE_DPMS_ON,      "ON"},
	{SDE_MODE_DPMS_LP1,     "LP1"},
	{SDE_MODE_DPMS_LP2,     "LP2"},
	{SDE_MODE_DPMS_OFF,     "OFF"},
};

int sde_connector_get_info(struct drm_connector *connector,
		struct msm_display_info *info)
{
@@ -155,6 +162,7 @@ static void sde_connector_destroy(struct drm_connector *connector)
	msm_property_destroy(&c_conn->property_info);

	drm_connector_unregister(connector);
	mutex_destroy(&c_conn->lock);
	sde_fence_deinit(&c_conn->retire_fence);
	drm_connector_cleanup(connector);
	kfree(c_conn);
@@ -353,6 +361,56 @@ static int _sde_connector_set_hdr_info(
	return 0;
}

static int _sde_connector_update_power_locked(struct sde_connector *c_conn)
{
	struct drm_connector *connector;
	void *display;
	int (*set_power)(struct drm_connector *, int, void *);
	int mode, rc = 0;

	if (!c_conn)
		return -EINVAL;
	connector = &c_conn->base;

	mode = c_conn->lp_mode;
	if (c_conn->dpms_mode != DRM_MODE_DPMS_ON)
		mode = SDE_MODE_DPMS_OFF;
	switch (c_conn->dpms_mode) {
	case DRM_MODE_DPMS_ON:
		mode = c_conn->lp_mode;
		break;
	case DRM_MODE_DPMS_STANDBY:
		mode = SDE_MODE_DPMS_STANDBY;
		break;
	case DRM_MODE_DPMS_SUSPEND:
		mode = SDE_MODE_DPMS_SUSPEND;
		break;
	case DRM_MODE_DPMS_OFF:
		mode = SDE_MODE_DPMS_OFF;
		break;
	default:
		mode = c_conn->lp_mode;
		SDE_ERROR("conn %d dpms set to unrecognized mode %d\n",
				connector->base.id, mode);
		break;
	}

	SDE_DEBUG("conn %d - dpms %d, lp %d, panel %d\n", connector->base.id,
			c_conn->dpms_mode, c_conn->lp_mode, mode);

	if (mode != c_conn->last_panel_power_mode && c_conn->ops.set_power) {
		display = c_conn->display;
		set_power = c_conn->ops.set_power;

		mutex_unlock(&c_conn->lock);
		rc = set_power(connector, mode, display);
		mutex_lock(&c_conn->lock);
	}
	c_conn->last_panel_power_mode = mode;

	return rc;
}

static int sde_connector_atomic_set_property(struct drm_connector *connector,
		struct drm_connector_state *state,
		struct drm_property *property,
@@ -379,8 +437,8 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,

	/* connector-specific property handling */
	idx = msm_property_index(&c_conn->property_info, property);

	if (idx == CONNECTOR_PROP_OUT_FB) {
	switch (idx) {
	case CONNECTOR_PROP_OUT_FB:
		/* clear old fb, if present */
		if (c_state->out_fb)
			_sde_connector_destroy_fb(c_conn, c_state);
@@ -404,12 +462,20 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
			if (rc)
				SDE_ERROR("prep fb failed, %d\n", rc);
		}
	}

	if (idx == CONNECTOR_PROP_TOPOLOGY_CONTROL) {
		break;
	case CONNECTOR_PROP_TOPOLOGY_CONTROL:
		rc = sde_rm_check_property_topctl(val);
		if (rc)
			SDE_ERROR("invalid topology_control: 0x%llX\n", val);
		break;
	case CONNECTOR_PROP_LP:
		mutex_lock(&c_conn->lock);
		c_conn->lp_mode = val;
		_sde_connector_update_power_locked(c_conn);
		mutex_unlock(&c_conn->lock);
		break;
	default:
		break;
	}

	if (idx == CONNECTOR_PROP_HDR_CONTROL) {
@@ -510,6 +576,60 @@ void sde_connector_complete_commit(struct drm_connector *connector)
	sde_fence_signal(&to_sde_connector(connector)->retire_fence, 0);
}

static int sde_connector_dpms(struct drm_connector *connector,
		int mode)
{
	struct sde_connector *c_conn;

	if (!connector) {
		SDE_ERROR("invalid connector\n");
		return -EINVAL;
	}
	c_conn = to_sde_connector(connector);

	/* validate incoming dpms request */
	switch (mode) {
	case DRM_MODE_DPMS_ON:
	case DRM_MODE_DPMS_STANDBY:
	case DRM_MODE_DPMS_SUSPEND:
	case DRM_MODE_DPMS_OFF:
		SDE_DEBUG("conn %d dpms set to %d\n",
			connector->base.id, mode);
		break;
	default:
		SDE_ERROR("conn %d dpms set to unrecognized mode %d\n",
			connector->base.id, mode);
		break;
	}

	mutex_lock(&c_conn->lock);
	c_conn->dpms_mode = mode;
	_sde_connector_update_power_locked(c_conn);
	mutex_unlock(&c_conn->lock);

	/* use helper for boilerplate handling */
	return drm_atomic_helper_connector_dpms(connector, mode);
}

int sde_connector_get_dpms(struct drm_connector *connector)
{
	struct sde_connector *c_conn;
	int rc;

	if (!connector) {
		SDE_DEBUG("invalid connector\n");
		return DRM_MODE_DPMS_OFF;
	}

	c_conn = to_sde_connector(connector);

	mutex_lock(&c_conn->lock);
	rc = c_conn->dpms_mode;
	mutex_unlock(&c_conn->lock);

	return rc;
}

static void sde_connector_update_hdr_props(struct drm_connector *connector)
{
	struct sde_connector *c_conn = to_sde_connector(connector);
@@ -558,7 +678,7 @@ sde_connector_detect(struct drm_connector *connector, bool force)
}

static const struct drm_connector_funcs sde_connector_ops = {
	.dpms =                   drm_atomic_helper_connector_dpms,
	.dpms =                   sde_connector_dpms,
	.reset =                  sde_connector_atomic_reset,
	.detect =                 sde_connector_detect,
	.destroy =                sde_connector_destroy,
@@ -681,6 +801,11 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
	c_conn->panel = panel;
	c_conn->display = display;

	c_conn->dpms_mode = DRM_MODE_DPMS_ON;
	c_conn->lp_mode = 0;
	c_conn->last_panel_power_mode = SDE_MODE_DPMS_ON;


	sde_kms = to_sde_kms(priv->kms);
	if (sde_kms->vbif[VBIF_NRT]) {
		c_conn->aspace[SDE_IOMMU_DOMAIN_UNSECURE] =
@@ -714,6 +839,8 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
		goto error_cleanup_conn;
	}

	mutex_init(&c_conn->lock);

	rc = drm_connector_register(&c_conn->base);
	if (rc) {
		SDE_ERROR("failed to register drm connector, %d\n", rc);
@@ -793,6 +920,11 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
			ARRAY_SIZE(e_topology_control),
			CONNECTOR_PROP_TOPOLOGY_CONTROL, 0);

	msm_property_install_enum(&c_conn->property_info, "LP",
			0, 0, e_power_mode,
			ARRAY_SIZE(e_power_mode),
			CONNECTOR_PROP_LP, 0);

	rc = msm_property_install_get_status(&c_conn->property_info);
	if (rc) {
		SDE_ERROR("failed to create one or more properties\n");
@@ -819,6 +951,7 @@ error_destroy_property:
error_unregister_conn:
	drm_connector_unregister(&c_conn->base);
error_cleanup_fence:
	mutex_destroy(&c_conn->lock);
	sde_fence_deinit(&c_conn->retire_fence);
error_cleanup_conn:
	drm_connector_cleanup(&c_conn->base);
+29 −0
Original line number Diff line number Diff line
@@ -153,6 +153,20 @@ struct sde_connector_ops {
	 */
	enum sde_csc_type (*get_csc_type)(struct drm_connector *connector,
		void *display);

	/**
	 * set_power - update dpms setting
	 * @connector: Pointer to drm connector structure
	 * @power_mode: One of the following,
	 *		SDE_MODE_DPMS_ON
	 *		SDE_MODE_DPMS_LP1
	 *		SDE_MODE_DPMS_LP2
	 *		SDE_MODE_DPMS_OFF
	 * @display: Pointer to private display structure
	 * Returns: Zero on success
	 */
	int (*set_power)(struct drm_connector *connector,
			int power_mode, void *display);
};

/**
@@ -165,8 +179,12 @@ struct sde_connector_ops {
 * @mmu_secure: MMU id for secure buffers
 * @mmu_unsecure: MMU id for unsecure buffers
 * @name: ASCII name of connector
 * @lock: Mutex lock object for this structure
 * @retire_fence: Retire fence reference
 * @ops: Local callback function pointer table
 * @dpms_mode: DPMS property setting from user space
 * @lp_mode: LP property setting from user space
 * @last_panel_power_mode: Last consolidated dpms/lp mode setting
 * @property_info: Private structure for generic property handling
 * @property_data: Array of private data for generic property handling
 * @blob_caps: Pointer to blob structure for 'capabilities' property
@@ -185,8 +203,12 @@ struct sde_connector {

	char name[SDE_CONNECTOR_NAME_SIZE];

	struct mutex lock;
	struct sde_fence retire_fence;
	struct sde_connector_ops ops;
	int dpms_mode;
	int lp_mode;
	int last_panel_power_mode;

	struct msm_property_info property_info;
	struct msm_property_data property_data[CONNECTOR_PROP_COUNT];
@@ -361,5 +383,12 @@ bool sde_connector_mode_needs_full_range(struct drm_connector *connector);
 */
enum sde_csc_type sde_connector_get_csc_type(struct drm_connector *conn);

/**
 * sde_connector_get_dpms - query dpms setting
 * @connector: Pointer to drm connector structure
 * Returns: Current DPMS setting for connector
 */
int sde_connector_get_dpms(struct drm_connector *connector);

#endif /* _SDE_CONNECTOR_H_ */
+13 −0
Original line number Diff line number Diff line
@@ -932,6 +932,15 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc)
	sde_kms = _sde_crtc_get_kms(crtc);
	priv = sde_kms->dev->dev_private;

	/*
	 * If no mixers has been allocated in sde_crtc_atomic_check(),
	 * it means we are trying to start a CRTC whose state is disabled:
	 * nothing else needs to be done.
	 */
	if (unlikely(!sde_crtc->num_mixers))
		return;


	SDE_ATRACE_BEGIN("crtc_commit");
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
		if (encoder->crtc != crtc)
@@ -1342,6 +1351,10 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
	mode = &state->adjusted_mode;
	SDE_DEBUG("%s: check", sde_crtc->name);

	/* force a full mode set if active state changed */
	if (state->active_changed)
		state->mode_changed = true;

	mixer_width = sde_crtc_mixer_width(sde_crtc, mode);

	 /* get plane state for all drm planes associated with crtc state */
+10 −0
Original line number Diff line number Diff line
@@ -337,4 +337,14 @@ struct sde_drm_wb_cfg {
	uint64_t modes;
};

/**
 * Define extended power modes supported by the SDE connectors.
 */
#define SDE_MODE_DPMS_ON       0
#define SDE_MODE_DPMS_LP1      1
#define SDE_MODE_DPMS_LP2      2
#define SDE_MODE_DPMS_STANDBY  3
#define SDE_MODE_DPMS_SUSPEND  4
#define SDE_MODE_DPMS_OFF      5

#endif /* _SDE_DRM_H_ */