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

Commit c47a0691 authored by Clarence Ip's avatar Clarence Ip Committed by Narendra Muppalla
Browse files

drm/msm/sde: assign relative mixer stages based on zpos



Assign mixer stages based on relative zpos ordering rather than
using the zpos property value directly. This avoids problems caused
by the zpos property value being greater than the available number
of stages.

Change-Id: I9f5a5a12ba5be49fbe1fbee78ddc7fadfeaedc9d
Signed-off-by: default avatarClarence Ip <cip@codeaurora.org>
parent cf42ee08
Loading
Loading
Loading
Loading
+51 −9
Original line number Diff line number Diff line
@@ -784,8 +784,28 @@ static void sde_crtc_enable(struct drm_crtc *crtc)
struct plane_state {
	struct sde_plane_state *sde_pstate;
	struct drm_plane_state *drm_pstate;

	int stage;
};

static int pstate_cmp(const void *a, const void *b)
{
	struct plane_state *pa = (struct plane_state *)a;
	struct plane_state *pb = (struct plane_state *)b;
	int rc = 0;
	int pa_zpos, pb_zpos;

	pa_zpos = sde_plane_get_property(pa->sde_pstate, PLANE_PROP_ZPOS);
	pb_zpos = sde_plane_get_property(pb->sde_pstate, PLANE_PROP_ZPOS);

	if (pa_zpos != pb_zpos)
		rc = pa_zpos - pb_zpos;
	else
		rc = pa->drm_pstate->crtc_x - pb->drm_pstate->crtc_x;

	return rc;
}

static int sde_crtc_atomic_check(struct drm_crtc *crtc,
		struct drm_crtc_state *state)
{
@@ -820,16 +840,19 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
	 /* get plane state for all drm planes associated with crtc state */
	drm_atomic_crtc_state_for_each_plane(plane, state) {
		pstate = drm_atomic_get_plane_state(state->state, plane);
		if (IS_ERR(pstate)) {
			SDE_ERROR("%s: failed to get plane:%d state\n",
					sde_crtc->name,
					plane->base.id);
			rc = -EINVAL;
		if (IS_ERR_OR_NULL(pstate)) {
			rc = PTR_ERR(pstate);
			SDE_ERROR("%s: failed to get plane%d state, %d\n",
					sde_crtc->name, plane->base.id, rc);
			goto end;
		}
		if (cnt >= ARRAY_SIZE(pstates))
			continue;

		pstates[cnt].sde_pstate = to_sde_plane_state(pstate);
		pstates[cnt].drm_pstate = pstate;
		pstates[cnt].stage = sde_plane_get_property(
				pstates[cnt].sde_pstate, PLANE_PROP_ZPOS);
		cnt++;

		if (CHECK_LAYER_BOUNDS(pstate->crtc_y, pstate->crtc_h,
@@ -845,11 +868,30 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
		}
	}

	if (!sde_is_custom_client()) {
		int stage_old = pstates[0].stage;

		/* assign mixer stages based on sorted zpos property */
		sort(pstates, cnt, sizeof(pstates[0]), pstate_cmp, NULL);
		z_pos = 0;
		for (i = 0; i < cnt; i++) {
		z_pos = sde_plane_get_property(pstates[i].sde_pstate,
			PLANE_PROP_ZPOS);
			if (stage_old != pstates[i].stage)
				++z_pos;
			stage_old = pstates[i].stage;
			pstates[i].stage = z_pos;
		}
	}

		if (pstates[i].drm_pstate->crtc_x < mixer_width) {
	for (i = 0; i < cnt; i++) {
		z_pos = pstates[i].stage;

		/* verify z_pos setting before using it */
		if (z_pos >= SDE_STAGE_MAX) {
			SDE_ERROR("> %d plane stages assigned\n",
					SDE_STAGE_MAX - SDE_STAGE_0);
			rc = -EINVAL;
			goto end;
		} else if (pstates[i].drm_pstate->crtc_x < mixer_width) {
			if (left_crtc_zpos_cnt[z_pos] == 2) {
				SDE_ERROR("> 2 plane @ stage%d on left\n",
					z_pos);
@@ -866,7 +908,7 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
			}
			right_crtc_zpos_cnt[z_pos]++;
		}
		pstates[i].sde_pstate->stage = z_pos;
		pstates[i].sde_pstate->stage = z_pos + SDE_STAGE_0;
		SDE_DEBUG("%s: zpos %d", sde_crtc->name, z_pos);
	}

+19 −16
Original line number Diff line number Diff line
@@ -916,7 +916,7 @@ static int _sde_plane_color_fill(struct sde_plane *psde,
static int _sde_plane_mode_set(struct drm_plane *plane,
				struct drm_plane_state *state)
{
	uint32_t nplanes, src_flags, zpos, split_w;
	uint32_t nplanes, src_flags;
	struct sde_plane *psde;
	struct sde_plane_state *pstate;
	const struct sde_format *fmt;
@@ -1030,13 +1030,6 @@ static int _sde_plane_mode_set(struct drm_plane *plane,
		} else if (psde->pipe_hw->ops.setup_rects) {
			_sde_plane_setup_scaler(psde, fmt, pstate);

			/* base layer source split needs update */
			zpos = sde_plane_get_property(pstate, PLANE_PROP_ZPOS);
			if (zpos == SDE_STAGE_BASE) {
				split_w = get_crtc_split_width(crtc);
				if (psde->pipe_cfg.dst_rect.x >= split_w)
					psde->pipe_cfg.dst_rect.x -= split_w;
			}
			psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
					&psde->pipe_cfg, &psde->pixel_ext);
		}
@@ -1395,7 +1388,7 @@ static void sde_plane_atomic_update(struct drm_plane *plane,

/* helper to install properties which are common to planes and crtcs */
static void _sde_plane_install_properties(struct drm_plane *plane,
	u32 max_blendstages)
	struct sde_mdss_cfg *catalog)
{
	static const struct drm_prop_enum_list e_blend_op[] = {
		{SDE_DRM_BLEND_OP_NOT_DEFINED,    "not_defined"},
@@ -1409,6 +1402,8 @@ static void _sde_plane_install_properties(struct drm_plane *plane,
	const struct sde_format_extended *format_list;
	struct sde_kms_info *info;
	struct sde_plane *psde = to_sde_plane(plane);
	int zpos_max = 255;
	int zpos_def = 0;

	if (!plane || !psde) {
		SDE_ERROR("invalid plane\n");
@@ -1417,10 +1412,21 @@ static void _sde_plane_install_properties(struct drm_plane *plane,
		SDE_ERROR("invalid plane, pipe_hw %d pipe_sblk %d\n",
				psde->pipe_hw != 0, psde->pipe_sblk != 0);
		return;
	} else if (!catalog) {
		SDE_ERROR("invalid catalog\n");
		return;
	}

	if (sde_is_custom_client()) {
		if (catalog->mixer_count && catalog->mixer)
			zpos_max = catalog->mixer[0].sblk->maxblendstages;
	} else if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
		/* reserve zpos == 0 for primary planes */
		zpos_def = drm_plane_index(plane) + 1;
	}

	msm_property_install_range(&psde->property_info, "zpos", 0x0, 0,
		max_blendstages, SDE_STAGE_BASE, PLANE_PROP_ZPOS);
	msm_property_install_range(&psde->property_info, "zpos",
		0x0, 0, zpos_max, zpos_def, PLANE_PROP_ZPOS);

	msm_property_install_range(&psde->property_info, "alpha",
		0x0, 0, 255, 255, PLANE_PROP_ALPHA);
@@ -1887,7 +1893,7 @@ struct drm_plane *sde_plane_init(struct drm_device *dev,
	struct msm_drm_private *priv;
	struct sde_kms *kms;
	enum drm_plane_type type;
	int ret = -EINVAL, max_blendstages = 255;
	int ret = -EINVAL;

	if (!dev) {
		SDE_ERROR("[%u]device is NULL\n", pipe);
@@ -1943,9 +1949,6 @@ struct drm_plane *sde_plane_init(struct drm_device *dev,
		goto clean_sspp;
	}

	if (kms->catalog && kms->catalog->mixer_count && kms->catalog->mixer)
		max_blendstages = kms->catalog->mixer[0].sblk->maxblendstages;

	/* add plane to DRM framework */
	psde->nformats = sde_populate_formats(psde->pipe_sblk->format_list,
			psde->formats,
@@ -1976,7 +1979,7 @@ struct drm_plane *sde_plane_init(struct drm_device *dev,
			PLANE_PROP_COUNT, PLANE_PROP_BLOBCOUNT,
			sizeof(struct sde_plane_state));

	_sde_plane_install_properties(plane, max_blendstages);
	_sde_plane_install_properties(plane, kms->catalog);

	/* save user friendly pipe name for later */
	snprintf(psde->pipe_name, SDE_NAME_SIZE, "plane%u", plane->base.id);