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

Commit 5da6eb26 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" into msm-4.9

parents e57322e8 90b282d5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ enum msm_mdp_conn_property {
	CONNECTOR_PROP_TOPOLOGY_NAME,
	CONNECTOR_PROP_TOPOLOGY_CONTROL,
	CONNECTOR_PROP_AUTOREFRESH,
	CONNECTOR_PROP_LP,

	/* total # of properties */
	CONNECTOR_PROP_COUNT
+136 −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"
@@ -44,6 +44,12 @@ static const struct drm_prop_enum_list e_topology_control[] = {
	{SDE_RM_TOPCTL_FORCE_TILING,	"force_tiling"},
	{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"},
};

static int sde_backlight_device_update_status(struct backlight_device *bd)
{
@@ -294,6 +300,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);
@@ -541,6 +548,56 @@ static int _sde_connector_set_roi_v1(
	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,
@@ -567,8 +624,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);
@@ -598,12 +655,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_ROI_V1) {
@@ -719,6 +784,59 @@ sde_connector_detect(struct drm_connector *connector, bool force)
	return status;
}

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;
}

#ifdef CONFIG_DEBUG_FS
/**
 * sde_connector_init_debugfs - initialize connector debugfs
@@ -761,7 +879,7 @@ static void sde_connector_early_unregister(struct drm_connector *connector)
}

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,
@@ -885,6 +1003,10 @@ 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;

	/* cache mmu_id's for later */
	sde_kms = to_sde_kms(priv->kms);
	if (sde_kms->vbif[VBIF_NRT]) {
@@ -919,6 +1041,8 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
		goto error_cleanup_conn;
	}

	mutex_init(&c_conn->lock);

	rc = drm_mode_connector_attach_encoder(&c_conn->base, encoder);
	if (rc) {
		SDE_ERROR("failed to attach encoder to connector, %d\n", rc);
@@ -1006,6 +1130,10 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
			0, 1, e_topology_control,
			ARRAY_SIZE(e_topology_control),
			CONNECTOR_PROP_TOPOLOGY_CONTROL);
	msm_property_install_enum(&c_conn->property_info, "LP",
			0, 0, e_power_mode,
			ARRAY_SIZE(e_power_mode),
			CONNECTOR_PROP_LP);

	rc = msm_property_install_get_status(&c_conn->property_info);
	if (rc) {
@@ -1027,6 +1155,7 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
		drm_property_unreference_blob(c_conn->blob_hdr);
	msm_property_destroy(&c_conn->property_info);
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
@@ -169,6 +169,20 @@ struct sde_connector_ops {
	 * @enable: State of clks
	 */
	int (*clk_ctrl)(void *handle, u32 type, u32 state);

	/**
	 * 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);
};

/**
@@ -203,8 +217,12 @@ struct sde_connector_evt {
 * @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 context 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
@@ -226,8 +244,12 @@ struct sde_connector {

	char name[SDE_CONNECTOR_NAME_SIZE];

	struct mutex lock;
	struct sde_fence_context 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];
@@ -391,6 +413,13 @@ int sde_connector_get_info(struct drm_connector *connector,
 */
void sde_connector_clk_ctrl(struct drm_connector *connector, bool enable);

/**
 * 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);

/**
 * sde_connector_trigger_event - indicate that an event has occurred
 *	Any callbacks that have been registered against this event will
+12 −0
Original line number Diff line number Diff line
@@ -1946,6 +1946,14 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc)
	priv = sde_kms->dev->dev_private;
	cstate = to_sde_crtc_state(crtc->state);

	/*
	 * 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;

	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
		struct sde_encoder_kickoff_params params = { 0 };

@@ -2409,6 +2417,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;

	memset(pipe_staged, 0, sizeof(pipe_staged));

	mixer_width = sde_crtc_mixer_width(sde_crtc, mode);
+10 −0
Original line number Diff line number Diff line
@@ -356,4 +356,14 @@ struct sde_drm_roi_v1 {
	struct drm_clip_rect roi[SDE_MAX_ROI_V1];
};

/**
 * 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_ */