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

Commit f17a1716 authored by Kyle Yan's avatar Kyle Yan Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: enable dynamic hardware resource assignment" into msm-4.8

parents 3c64a5ba 11f3444c
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -37,6 +37,7 @@ msm-y := \
	sde/sde_encoder_phys_vid.o \
	sde/sde_encoder_phys_vid.o \
	sde/sde_encoder_phys_cmd.o \
	sde/sde_encoder_phys_cmd.o \
	sde/sde_irq.o \
	sde/sde_irq.o \
	sde/sde_rm.o \
	sde/sde_kms_utils.o \
	sde/sde_kms_utils.o \
	sde/sde_kms.o \
	sde/sde_kms.o \
	sde/sde_plane.o \
	sde/sde_plane.o \
+6 −0
Original line number Original line Diff line number Diff line
@@ -253,6 +253,12 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
		}
		}
	}
	}


	if (idx == CONNECTOR_PROP_TOPOLOGY_CONTROL) {
		rc = sde_rm_check_property_topctl(val);
		if (rc)
			SDE_ERROR("invalid topology_control: 0x%llX\n", val);
	}

	/* check for custom property handling */
	/* check for custom property handling */
	if (!rc && c_conn->ops.set_property) {
	if (!rc && c_conn->ops.set_property) {
		rc = c_conn->ops.set_property(connector,
		rc = c_conn->ops.set_property(connector,
+63 −136
Original line number Original line Diff line number Diff line
@@ -42,116 +42,6 @@ static struct sde_kms *get_kms(struct drm_crtc *crtc)
	return to_sde_kms(priv->kms);
	return to_sde_kms(priv->kms);
}
}


static int sde_crtc_reserve_hw_resources(struct drm_crtc *crtc)
{
	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
	struct sde_kms *sde_kms = get_kms(crtc);
	struct sde_encoder_hw_resources enc_hw_res;
	const struct sde_hw_res_map *plat_hw_res_map;
	enum sde_lm unused_lm_id[CRTC_DUAL_MIXERS] = {0};
	enum sde_lm lm_idx;
	int i, unused_lm_count = 0;

	if (!sde_kms) {
		DBG("[%s] invalid kms", __func__);
		return -EINVAL;
	}

	if (!sde_kms->mmio)
		return -EINVAL;

	/* Get unused LMs */
	for (i = sde_kms->catalog->mixer_count - 1; i >= 0; --i) {
		if (!sde_rm_get_mixer(sde_kms, LM(i))) {
			unused_lm_id[unused_lm_count++] = LM(i);
			if (unused_lm_count == CRTC_DUAL_MIXERS)
				break;
		}
	}

	/* query encoder resources */
	sde_encoder_get_hw_resources(sde_crtc->mixers[0].encoder, &enc_hw_res);

	/* parse encoder hw resources, find CTL paths */
	for (i = CTL_0; i <= sde_kms->catalog->ctl_count; i++) {
		WARN_ON(sde_crtc->num_ctls > CRTC_DUAL_MIXERS);
		if (enc_hw_res.ctls[i]) {
			struct sde_crtc_mixer *mixer  =
				&sde_crtc->mixers[sde_crtc->num_ctls];
			mixer->hw_ctl = sde_rm_get_ctl_path(sde_kms, i);
			if (IS_ERR_OR_NULL(mixer->hw_ctl)) {
				DRM_ERROR("Invalid ctl_path\n");
				return PTR_ERR(mixer->hw_ctl);
			}
			sde_crtc->num_ctls++;
		}
	}

	/* shortcut this process if encoder has no ctl paths */
	if (!sde_crtc->num_ctls)
		return 0;

	/*
	 * Get default LMs if specified in platform config
	 * other wise acquire the free LMs
	 */
	for (i = INTF_0; i <= sde_kms->catalog->intf_count; i++) {
		if (enc_hw_res.intfs[i]) {
			struct sde_crtc_mixer *mixer  =
				&sde_crtc->mixers[sde_crtc->num_mixers];
			plat_hw_res_map = sde_rm_get_res_map(sde_kms,
					i, SDE_NONE);

			lm_idx = plat_hw_res_map->lm;
			if (!lm_idx && unused_lm_count)
				lm_idx = unused_lm_id[--unused_lm_count];

			DBG("intf %d acquiring lm %d", i, lm_idx);
			mixer->hw_lm = sde_rm_acquire_mixer(sde_kms, lm_idx);
			if (IS_ERR_OR_NULL(mixer->hw_lm)) {
				DRM_ERROR("Invalid mixer\n");
				return -EACCES;
			}
			sde_crtc->num_mixers++;
		}
	}

	/*
	 * Get default LMs if specified in platform config,
	 * otherwise acquire the free LMs.
	 */
	for (i = WB_0; i < WB_MAX; i++) {
		if (enc_hw_res.wbs[i]) {
			struct sde_crtc_mixer *mixer =
				&sde_crtc->mixers[sde_crtc->num_mixers];
			plat_hw_res_map = sde_rm_get_res_map(sde_kms,
					SDE_NONE, i);

			lm_idx = plat_hw_res_map->lm;
			if (!lm_idx && unused_lm_count)
				lm_idx = unused_lm_id[--unused_lm_count];

			DBG("wb %d acquiring lm %d", i, lm_idx);
			mixer->hw_lm = sde_rm_acquire_mixer(sde_kms, lm_idx);
			if (IS_ERR_OR_NULL(mixer->hw_lm)) {
				DRM_ERROR("Invalid mixer\n");
				return -EACCES;
			}
			sde_crtc->num_mixers++;
		}
	}

	DBG("control paths %d, num_mixers %d, lm[0] %d, ctl[0] %d ",
			sde_crtc->num_ctls, sde_crtc->num_mixers,
			sde_crtc->mixers[0].hw_lm->idx,
			sde_crtc->mixers[0].hw_ctl->idx);
	if (sde_crtc->num_mixers > 1)
		DBG("lm[1] %d, ctl[1], %d",
			sde_crtc->mixers[1].hw_lm->idx,
			sde_crtc->mixers[1].hw_ctl->idx);
	return 0;
}

static void sde_crtc_destroy(struct drm_crtc *crtc)
static void sde_crtc_destroy(struct drm_crtc *crtc)
{
{
	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
@@ -561,6 +451,66 @@ static void _sde_crtc_wait_for_fences(struct drm_crtc *crtc)
	}
	}
}
}


static void _sde_crtc_setup_mixer_for_encoder(
		struct drm_crtc *crtc,
		struct drm_encoder *enc)
{
	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
	struct sde_kms *sde_kms = get_kms(crtc);
	struct sde_rm *rm = &sde_kms->rm;
	struct sde_crtc_mixer *mixer;
	int i;
	struct sde_rm_hw_iter lm_iter, ctl_iter;

	sde_rm_init_hw_iter(&lm_iter, enc->base.id, SDE_HW_BLK_LM);
	sde_rm_init_hw_iter(&ctl_iter, enc->base.id, SDE_HW_BLK_CTL);

	/* Set up the mixer for this encoder, checking all channels */
	for (i = sde_crtc->num_mixers; i < ARRAY_SIZE(sde_crtc->mixers); i++) {
		mixer = &sde_crtc->mixers[i];

		/* Add mixer if reservation exists on (encoder, chan) */
		if (!sde_rm_get_hw(rm, &lm_iter))
			break;
		mixer->hw_lm = (struct sde_hw_mixer *)lm_iter.hw;

		/* CTL may be null, not necessarily 1:1 with LM */
		(void) sde_rm_get_hw(rm, &ctl_iter);
		mixer->hw_ctl = (struct sde_hw_ctl *)ctl_iter.hw;

		mixer->flush_mask = 0;
		mixer->encoder = enc;

		sde_crtc->num_mixers++;
		SDE_DEBUG("setup mixer %d: lm %d\n",
				i, mixer->hw_lm->idx);

		if (mixer->hw_ctl) {
			sde_crtc->num_ctls++;
			SDE_DEBUG("setup mixer %d: ctl %d\n",
					i, mixer->hw_ctl->idx);
		}
	}
}

static void _sde_crtc_setup_mixers(struct drm_crtc *crtc)
{
	struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
	struct drm_encoder *enc;

	sde_crtc->num_ctls = 0;
	sde_crtc->num_mixers = 0;
	memset(sde_crtc->mixers, 0, sizeof(sde_crtc->mixers));

	/* Check for mixers on all encoders attached to this crtc */
	list_for_each_entry(enc, &crtc->dev->mode_config.encoder_list, head) {
		if (enc->crtc != crtc)
			continue;

		_sde_crtc_setup_mixer_for_encoder(crtc, enc);
	}
}

static void sde_crtc_atomic_begin(struct drm_crtc *crtc,
static void sde_crtc_atomic_begin(struct drm_crtc *crtc,
		struct drm_crtc_state *old_crtc_state)
		struct drm_crtc_state *old_crtc_state)
{
{
@@ -579,6 +529,8 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc,
	sde_crtc = to_sde_crtc(crtc);
	sde_crtc = to_sde_crtc(crtc);
	dev = crtc->dev;
	dev = crtc->dev;


	_sde_crtc_setup_mixers(crtc);

	if (sde_crtc->event) {
	if (sde_crtc->event) {
		WARN_ON(sde_crtc->event);
		WARN_ON(sde_crtc->event);
	} else {
	} else {
@@ -832,7 +784,6 @@ static void sde_crtc_enable(struct drm_crtc *crtc)
	struct sde_hw_mixer_cfg cfg;
	struct sde_hw_mixer_cfg cfg;
	u32 mixer_width;
	u32 mixer_width;
	int i;
	int i;
	int rc;


	if (!crtc) {
	if (!crtc) {
		DRM_ERROR("invalid crtc\n");
		DRM_ERROR("invalid crtc\n");
@@ -851,20 +802,7 @@ static void sde_crtc_enable(struct drm_crtc *crtc)


	drm_mode_debug_printmodeline(mode);
	drm_mode_debug_printmodeline(mode);


	/*
	/* Update LMs for dual mode: mixer_width = half mode width */
	 * reserve mixer(s) if not already avaialable
	 * if dual mode, mixer_width = half mode width
	 * program mode configuration on mixer(s)
	 */
	if ((sde_crtc->num_ctls == 0) ||
		(sde_crtc->num_mixers == 0)) {
		rc = sde_crtc_reserve_hw_resources(crtc);
		if (rc) {
			DRM_ERROR("error reserving HW resource for CRTC\n");
			return;
		}
	}

	if (sde_crtc->num_mixers == CRTC_DUAL_MIXERS)
	if (sde_crtc->num_mixers == CRTC_DUAL_MIXERS)
		mixer_width = mode->hdisplay >> 1;
		mixer_width = mode->hdisplay >> 1;
	else
	else
@@ -1200,7 +1138,6 @@ static void _sde_crtc_init_debugfs(struct sde_crtc *sde_crtc,


/* initialize crtc */
/* initialize crtc */
struct drm_crtc *sde_crtc_init(struct drm_device *dev,
struct drm_crtc *sde_crtc_init(struct drm_device *dev,
		struct drm_encoder *encoder,
		struct drm_plane *plane,
		struct drm_plane *plane,
		int drm_crtc_id)
		int drm_crtc_id)
{
{
@@ -1208,7 +1145,6 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev,
	struct sde_crtc *sde_crtc = NULL;
	struct sde_crtc *sde_crtc = NULL;
	struct msm_drm_private *priv = NULL;
	struct msm_drm_private *priv = NULL;
	struct sde_kms *kms = NULL;
	struct sde_kms *kms = NULL;
	int i, rc;


	priv = dev->dev_private;
	priv = dev->dev_private;
	kms = to_sde_kms(priv->kms);
	kms = to_sde_kms(priv->kms);
@@ -1229,15 +1165,6 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev,
	drm_crtc_helper_add(crtc, &sde_crtc_helper_funcs);
	drm_crtc_helper_add(crtc, &sde_crtc_helper_funcs);
	plane->crtc = crtc;
	plane->crtc = crtc;


	for (i = 0; i < ARRAY_SIZE(sde_crtc->mixers); i++)
		sde_crtc->mixers[i].encoder = encoder;

	rc = sde_crtc_reserve_hw_resources(crtc);
	if (rc) {
		DRM_ERROR(" error reserving HW resource for this CRTC\n");
		return ERR_PTR(-EINVAL);
	}

	/* save user friendly CRTC name for later */
	/* save user friendly CRTC name for later */
	snprintf(sde_crtc->name, SDE_CRTC_NAME_SIZE, "crtc%u", crtc->base.id);
	snprintf(sde_crtc->name, SDE_CRTC_NAME_SIZE, "crtc%u", crtc->base.id);


+1 −0
Original line number Original line Diff line number Diff line
@@ -62,6 +62,7 @@ struct sde_crtc_mixer {
struct sde_crtc {
struct sde_crtc {
	struct drm_crtc base;
	struct drm_crtc base;
	char name[SDE_CRTC_NAME_SIZE];
	char name[SDE_CRTC_NAME_SIZE];

	int drm_crtc_id;
	int drm_crtc_id;


	spinlock_t lm_lock;	/* protect registers */
	spinlock_t lm_lock;	/* protect registers */
+69 −76
Original line number Original line Diff line number Diff line
@@ -70,6 +70,8 @@ struct sde_encoder_virt {
	spinlock_t spin_lock;
	spinlock_t spin_lock;
	uint32_t bus_scaling_client;
	uint32_t bus_scaling_client;


	uint32_t display_num_of_h_tiles;

	unsigned int num_phys_encs;
	unsigned int num_phys_encs;
	struct sde_encoder_phys *phys_encs[MAX_PHYS_ENCODERS_PER_VIRTUAL];
	struct sde_encoder_phys *phys_encs[MAX_PHYS_ENCODERS_PER_VIRTUAL];
	struct sde_encoder_phys *cur_master;
	struct sde_encoder_phys *cur_master;
@@ -155,14 +157,15 @@ static void bs_set(struct sde_encoder_virt *sde_enc, int idx)
#endif
#endif


void sde_encoder_get_hw_resources(struct drm_encoder *drm_enc,
void sde_encoder_get_hw_resources(struct drm_encoder *drm_enc,
				  struct sde_encoder_hw_resources *hw_res)
		struct sde_encoder_hw_resources *hw_res,
		struct drm_connector_state *conn_state)
{
{
	struct sde_encoder_virt *sde_enc = NULL;
	struct sde_encoder_virt *sde_enc = NULL;
	int i = 0;
	int i = 0;


	DBG("");
	DBG("");


	if (!hw_res || !drm_enc) {
	if (!hw_res || !drm_enc || !conn_state) {
		DRM_ERROR("Invalid pointer");
		DRM_ERROR("Invalid pointer");
		return;
		return;
	}
	}
@@ -171,11 +174,13 @@ void sde_encoder_get_hw_resources(struct drm_encoder *drm_enc,


	/* Query resources used by phys encs, expected to be without overlap */
	/* Query resources used by phys encs, expected to be without overlap */
	memset(hw_res, 0, sizeof(*hw_res));
	memset(hw_res, 0, sizeof(*hw_res));
	hw_res->display_num_of_h_tiles = sde_enc->display_num_of_h_tiles;

	for (i = 0; i < sde_enc->num_phys_encs; i++) {
	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];


		if (phys && phys->ops.get_hw_resources)
		if (phys && phys->ops.get_hw_resources)
			phys->ops.get_hw_resources(phys, hw_res);
			phys->ops.get_hw_resources(phys, hw_res, conn_state);
	}
	}
}
}


@@ -231,54 +236,14 @@ static void sde_encoder_destroy(struct drm_encoder *drm_enc)
	kfree(sde_enc);
	kfree(sde_enc);
}
}


static bool sde_encoder_virt_mode_fixup(struct drm_encoder *drm_enc,
static int sde_encoder_virt_atomic_check(
					const struct drm_display_mode *mode,
		struct drm_encoder *drm_enc,
					struct drm_display_mode *adj_mode)
{
	struct sde_encoder_virt *sde_enc = NULL;
	int i = 0;
	bool ret = true;

	DBG("");

	if (!drm_enc) {
		DRM_ERROR("Invalid pointer");
		return false;
	}

	sde_enc = to_sde_encoder_virt(drm_enc);
	MSM_EVT(drm_enc->dev, 0, 0);

	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];

		if (phys && phys->ops.mode_fixup) {
			ret = phys->ops.mode_fixup(phys, mode, adj_mode);
			if (!ret) {
				DRM_ERROR("Mode unsupported, phys_enc %d\n", i);
				break;
			}

			if (sde_enc->num_phys_encs > 1) {
				DBG("ModeFix only checking 1 phys_enc");
				break;
			}
		}
	}

	/* Call to populate mode->crtc* information required by framework */
	drm_mode_set_crtcinfo(adj_mode, 0);

	MSM_EVT(drm_enc->dev, adj_mode->flags, adj_mode->private_flags);

	return ret;
}

static int sde_encoder_virt_atomic_check(struct drm_encoder *drm_enc,
		struct drm_crtc_state *crtc_state,
		struct drm_crtc_state *crtc_state,
		struct drm_connector_state *conn_state)
		struct drm_connector_state *conn_state)
{
{
	struct sde_encoder_virt *sde_enc = NULL;
	struct sde_encoder_virt *sde_enc;
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;
	const struct drm_display_mode *mode;
	const struct drm_display_mode *mode;
	struct drm_display_mode *adj_mode;
	struct drm_display_mode *adj_mode;
	int i = 0;
	int i = 0;
@@ -292,6 +257,8 @@ static int sde_encoder_virt_atomic_check(struct drm_encoder *drm_enc,
	}
	}


	sde_enc = to_sde_encoder_virt(drm_enc);
	sde_enc = to_sde_encoder_virt(drm_enc);
	priv = drm_enc->dev->dev_private;
	sde_kms = to_sde_kms(priv->kms);
	mode = &crtc_state->mode;
	mode = &crtc_state->mode;
	adj_mode = &crtc_state->adjusted_mode;
	adj_mode = &crtc_state->adjusted_mode;
	MSM_EVT(drm_enc->dev, 0, 0);
	MSM_EVT(drm_enc->dev, 0, 0);
@@ -300,23 +267,25 @@ static int sde_encoder_virt_atomic_check(struct drm_encoder *drm_enc,
	for (i = 0; i < sde_enc->num_phys_encs; i++) {
	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];


		if (phys && phys->ops.atomic_check) {
		if (phys && phys->ops.atomic_check)
			ret = phys->ops.atomic_check(phys, crtc_state,
			ret = phys->ops.atomic_check(phys, crtc_state,
					conn_state);
					conn_state);
			if (ret)
		else if (phys && phys->ops.mode_fixup)
				DRM_ERROR("Mode unsupported, phys_enc %d.%d\n",
			if (!phys->ops.mode_fixup(phys, mode, adj_mode))
						drm_enc->base.id, i);
			break;
		} else if (phys && phys->ops.mode_fixup) {
			if (!phys->ops.mode_fixup(phys, mode, adj_mode)) {
				DRM_ERROR("Mode unsupported, phys_enc %d.%d\n",
						drm_enc->base.id, i);
				ret = -EINVAL;
				ret = -EINVAL;
			}

		if (ret) {
			SDE_ERROR("enc %d mode unsupported, phys %d\n",
					drm_enc->base.id, i);
			break;
			break;
		}
		}
	}
	}


	/* Reserve dynamic resources now. Indicating AtomicTest phase */
	if (!ret)
		ret = sde_rm_reserve(&sde_kms->rm, drm_enc, crtc_state,
				conn_state, true);

	/* Call to populate mode->crtc* information required by framework */
	/* Call to populate mode->crtc* information required by framework */
	drm_mode_set_crtcinfo(adj_mode, 0);
	drm_mode_set_crtcinfo(adj_mode, 0);


@@ -329,8 +298,12 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
				      struct drm_display_mode *mode,
				      struct drm_display_mode *mode,
				      struct drm_display_mode *adj_mode)
				      struct drm_display_mode *adj_mode)
{
{
	struct sde_encoder_virt *sde_enc = NULL;
	struct sde_encoder_virt *sde_enc;
	int i = 0;
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;
	struct list_head *connector_list;
	struct drm_connector *conn = NULL, *conn_iter;
	int i = 0, ret;


	DBG("");
	DBG("");


@@ -340,8 +313,31 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
	}
	}


	sde_enc = to_sde_encoder_virt(drm_enc);
	sde_enc = to_sde_encoder_virt(drm_enc);
	priv = drm_enc->dev->dev_private;
	sde_kms = to_sde_kms(priv->kms);
	connector_list = &sde_kms->dev->mode_config.connector_list;

	MSM_EVT(drm_enc->dev, 0, 0);
	MSM_EVT(drm_enc->dev, 0, 0);


	list_for_each_entry(conn_iter, connector_list, head)
		if (conn_iter->encoder == drm_enc)
			conn = conn_iter;

	if (!conn) {
		SDE_ERROR("enc %d failed to find attached connector\n",
				drm_enc->base.id);
		return;
	}

	/* Reserve dynamic resources now. Indicating non-AtomicTest phase */
	ret = sde_rm_reserve(&sde_kms->rm, drm_enc, drm_enc->crtc->state,
			conn->state, false);
	if (ret) {
		SDE_ERROR("enc %d failed to reserve hw resources, ret %d\n",
				drm_enc->base.id, ret);
		return;
	}

	for (i = 0; i < sde_enc->num_phys_encs; i++) {
	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];


@@ -390,6 +386,8 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
{
{
	struct sde_encoder_virt *sde_enc = NULL;
	struct sde_encoder_virt *sde_enc = NULL;
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;
	int i = 0;
	int i = 0;


	DBG("");
	DBG("");
@@ -400,6 +398,9 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
	}
	}


	sde_enc = to_sde_encoder_virt(drm_enc);
	sde_enc = to_sde_encoder_virt(drm_enc);
	priv = drm_enc->dev->dev_private;
	sde_kms = to_sde_kms(priv->kms);

	MSM_EVT(drm_enc->dev, 0, 0);
	MSM_EVT(drm_enc->dev, 0, 0);


	for (i = 0; i < sde_enc->num_phys_encs; i++) {
	for (i = 0; i < sde_enc->num_phys_encs; i++) {
@@ -413,10 +414,11 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
	DBG("clear phys enc master");
	DBG("clear phys enc master");


	bs_set(sde_enc, 0);
	bs_set(sde_enc, 0);

	sde_rm_release(&sde_kms->rm, drm_enc);
}
}


static const struct drm_encoder_helper_funcs sde_encoder_helper_funcs = {
static const struct drm_encoder_helper_funcs sde_encoder_helper_funcs = {
	.mode_fixup = sde_encoder_virt_mode_fixup,
	.mode_set = sde_encoder_virt_mode_set,
	.mode_set = sde_encoder_virt_mode_set,
	.disable = sde_encoder_virt_disable,
	.disable = sde_encoder_virt_disable,
	.enable = sde_encoder_virt_enable,
	.enable = sde_encoder_virt_enable,
@@ -699,6 +701,8 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc,


	WARN_ON(disp_info->num_of_h_tiles < 1);
	WARN_ON(disp_info->num_of_h_tiles < 1);


	sde_enc->display_num_of_h_tiles = disp_info->num_of_h_tiles;

	DBG("dsi_info->num_of_h_tiles %d", disp_info->num_of_h_tiles);
	DBG("dsi_info->num_of_h_tiles %d", disp_info->num_of_h_tiles);


	for (i = 0; i < disp_info->num_of_h_tiles && !ret; i++) {
	for (i = 0; i < disp_info->num_of_h_tiles && !ret; i++) {
@@ -707,7 +711,6 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc,
		 * h_tile_instance_ids[2] = {0, 1}; DSI0 = left, DSI1 = right
		 * h_tile_instance_ids[2] = {0, 1}; DSI0 = left, DSI1 = right
		 * h_tile_instance_ids[2] = {1, 0}; DSI1 = left, DSI0 = right
		 * h_tile_instance_ids[2] = {1, 0}; DSI1 = left, DSI0 = right
		 */
		 */
		const struct sde_hw_res_map *hw_res_map = NULL;
		u32 controller_id = disp_info->h_tile_instance[i];
		u32 controller_id = disp_info->h_tile_instance[i];


		if (disp_info->num_of_h_tiles > 1) {
		if (disp_info->num_of_h_tiles > 1) {
@@ -723,6 +726,7 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc,
				i, controller_id, phys_params.split_role);
				i, controller_id, phys_params.split_role);


		if (intf_type == INTF_WB) {
		if (intf_type == INTF_WB) {
			phys_params.intf_idx = INTF_MAX;
			phys_params.wb_idx = sde_encoder_get_wb(
			phys_params.wb_idx = sde_encoder_get_wb(
					sde_kms->catalog,
					sde_kms->catalog,
					intf_type, controller_id);
					intf_type, controller_id);
@@ -733,6 +737,7 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc,
				ret = -EINVAL;
				ret = -EINVAL;
			}
			}
		} else {
		} else {
			phys_params.wb_idx = WB_MAX;
			phys_params.intf_idx = sde_encoder_get_intf(
			phys_params.intf_idx = sde_encoder_get_intf(
					sde_kms->catalog, intf_type,
					sde_kms->catalog, intf_type,
					controller_id);
					controller_id);
@@ -744,18 +749,6 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc,
			}
			}
		}
		}


		hw_res_map = sde_rm_get_res_map(sde_kms, phys_params.intf_idx,
				phys_params.wb_idx);
		if (IS_ERR_OR_NULL(hw_res_map)) {
			DRM_ERROR("failed to get hw_res_map: %ld\n",
					PTR_ERR(hw_res_map));
			ret = -EINVAL;
		} else {
			phys_params.pp_idx = hw_res_map->pp;
			phys_params.ctl_idx = hw_res_map->ctl;
			phys_params.cdm_idx = hw_res_map->cdm;
		}

		if (!ret) {
		if (!ret) {
			if (intf_type == INTF_WB)
			if (intf_type == INTF_WB)
				ret = sde_encoder_virt_add_phys_enc_wb(sde_enc,
				ret = sde_encoder_virt_add_phys_enc_wb(sde_enc,
Loading