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

Commit c6a6fa72 authored by Lloyd Atkinson's avatar Lloyd Atkinson Committed by Steve Cohen
Browse files

drm/msm/sde: remember topology to disable ppsplit correctly



Add memory of the topology in the previous atomic state to
properly handle disabling of ping pong split topology which
doesn't register the slave encoder for IRQs.

Change-Id: I3ff1bc470713721149d90d462bfb97d8beb55f95
Signed-off-by: default avatarLloyd Atkinson <latkinso@codeaurora.org>
parent 609ff236
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -363,6 +363,8 @@ struct sde_connector {
 * @property_blobs: blob properties
 * @mode_info: local copy of msm_mode_info struct
 * @hdr_meta: HDR metadata info passed from userspace
 * @old_topology_name: topology of previous atomic state. remove this in later
 *	kernel versions which provide drm_atomic_state old_state pointers
 */
struct sde_connector_state {
	struct drm_connector_state base;
@@ -374,6 +376,7 @@ struct sde_connector_state {
	struct drm_property_blob *property_blobs[CONNECTOR_PROP_BLOBCOUNT];
	struct msm_mode_info mode_info;
	struct drm_msm_ext_hdr_metadata hdr_meta;
	enum sde_rm_topology_name old_topology_name;
};

/**
@@ -425,6 +428,43 @@ static inline uint64_t sde_connector_get_topology_name(
			CONNECTOR_PROP_TOPOLOGY_NAME);
}

/**
 * sde_connector_get_old_topology_name - helper accessor to retrieve
 *	topology_name for the previous mode
 * @connector: pointer to drm connector state
 * Returns: cached value of the previous topology, or SDE_RM_TOPOLOGY_NONE
 */
static inline enum sde_rm_topology_name sde_connector_get_old_topology_name(
		struct drm_connector_state *state)
{
	struct sde_connector_state *c_state = to_sde_connector_state(state);

	if (!state)
		return SDE_RM_TOPOLOGY_NONE;

	return c_state->old_topology_name;
}

/**
 * sde_connector_set_old_topology_name - helper to cache value of previous
 *	mode's topology
 * @connector: pointer to drm connector state
 * Returns: 0 on success, negative errno on failure
 */
static inline int sde_connector_set_old_topology_name(
		struct drm_connector_state *state,
		enum sde_rm_topology_name top)
{
	struct sde_connector_state *c_state = to_sde_connector_state(state);

	if (!state)
		return -EINVAL;

	c_state->old_topology_name = top;

	return 0;
}

/**
 * sde_connector_get_lp - helper accessor to retrieve LP state
 * @connector: pointer to drm connector
+14 −0
Original line number Diff line number Diff line
@@ -830,6 +830,20 @@ static int sde_encoder_virt_atomic_check(
			return ret;
	}

	if (!ret) {
		/**
		 * record topology in previous atomic state to be able to handle
		 * topology transitions correctly.
		 */
		enum sde_rm_topology_name old_top;

		old_top  = sde_connector_get_property(conn_state,
				CONNECTOR_PROP_TOPOLOGY_NAME);
		ret = sde_connector_set_old_topology_name(conn_state, old_top);
		if (ret)
			return ret;
	}

	if (!ret && sde_conn && drm_atomic_crtc_needs_modeset(crtc_state)) {
		struct msm_display_topology *topology = NULL;

+24 −1
Original line number Diff line number Diff line
@@ -489,6 +489,21 @@ static bool _sde_encoder_phys_is_ppsplit_slave(
			phys_enc->split_role == ENC_ROLE_SLAVE;
}

static bool _sde_encoder_phys_is_disabling_ppsplit_slave(
		struct sde_encoder_phys *phys_enc)
{
	enum sde_rm_topology_name old_top;

	if (!phys_enc || !phys_enc->connector ||
			phys_enc->split_role != ENC_ROLE_SLAVE)
		return false;

	old_top = sde_connector_get_old_topology_name(
			phys_enc->connector->state);

	return old_top == SDE_RM_TOPOLOGY_PPSPLIT;
}

static int _sde_encoder_phys_cmd_poll_write_pointer_started(
		struct sde_encoder_phys *phys_enc)
{
@@ -678,7 +693,15 @@ void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc,
{
	struct sde_encoder_phys_cmd *cmd_enc;

	if (!phys_enc || _sde_encoder_phys_is_ppsplit_slave(phys_enc))
	if (!phys_enc)
		return;

	/**
	 * pingpong split slaves do not register for IRQs
	 * check old and new topologies
	 */
	if (_sde_encoder_phys_is_ppsplit_slave(phys_enc) ||
			_sde_encoder_phys_is_disabling_ppsplit_slave(phys_enc))
		return;

	cmd_enc = to_sde_encoder_phys_cmd(phys_enc);