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

Commit 3f2cf42b authored by Chandan Uddaraju's avatar Chandan Uddaraju Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm/sde: add support to update DRM structures during bootup



For continuous splash use case, update the DRM
structures for encoder and CRTC using the
continuous splash data that is parsed during sde_kms
hardware initialization. Update the physical encoder
data structure with hardware blocks, irq settings
and cached_mode. When continuous splash is
enabled, update the CRTC-state and
connector/encoder-states with the configured DRM mode
and set the enable flags in these structures.

Change-Id: I251fcc9771e3463ad6b89429dd701cfd243b3ef6
Signed-off-by: default avatarChandan Uddaraju <chandanu@codeaurora.org>
Signed-off-by: default avatarShashank Babu Chinta Venkata <sbchin@codeaurora.org>
Signed-off-by: default avatarGovinda Rajulu Chenna <gchenna@codeaurora.org>
parent bf4927d3
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -65,7 +65,7 @@ static void convert_to_dsi_mode(const struct drm_display_mode *drm_mode,
		dsi_mode->dsi_mode_flags |= DSI_MODE_FLAG_VRR;
}

static void convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
void dsi_convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
				struct drm_display_mode *drm_mode)
{
	memset(drm_mode, 0, sizeof(*drm_mode));
@@ -298,7 +298,7 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,
			dsi_mode.dsi_mode_flags |= DSI_MODE_FLAG_DMS;
	}

	convert_to_drm_mode(&dsi_mode, adjusted_mode);
	dsi_convert_to_drm_mode(&dsi_mode, adjusted_mode);

	return true;
}
@@ -566,7 +566,7 @@ int dsi_connector_get_modes(struct drm_connector *connector,
		struct drm_display_mode *m;

		memset(&drm_mode, 0x0, sizeof(drm_mode));
		convert_to_drm_mode(&modes[i], &drm_mode);
		dsi_convert_to_drm_mode(&modes[i], &drm_mode);
		m = drm_mode_duplicate(connector->dev, &drm_mode);
		if (!m) {
			pr_err("failed to add mode %ux%u\n",
+8 −0
Original line number Diff line number Diff line
@@ -130,4 +130,12 @@ int dsi_conn_pre_kickoff(struct drm_connector *connector,
 */
int dsi_conn_post_kickoff(struct drm_connector *connector);

/**
 * dsi_convert_to_drm_mode - Update drm mode with dsi mode information
 * @dsi_mode: input parameter. structure having dsi mode information.
 * @drm_mode: output parameter. DRM mode set for the display
 */
void dsi_convert_to_drm_mode(const struct dsi_display_mode *dsi_mode,
				struct drm_display_mode *drm_mode);

#endif /* _DSI_DRM_H_ */
+12 −0
Original line number Diff line number Diff line
@@ -5865,3 +5865,15 @@ static int sde_crtc_idle_interrupt_handler(struct drm_crtc *crtc_drm,
{
	return 0;
}

/**
 * sde_crtc_update_cont_splash_mixer_settings - update mixer settings
 *	during device bootup for cont_splash use case
 * @crtc: Pointer to drm crtc structure
 */
void sde_crtc_update_cont_splash_mixer_settings(
		struct drm_crtc *crtc)
{
	_sde_crtc_setup_mixers(crtc);
	crtc->enabled = true;
}
+9 −0
Original line number Diff line number Diff line
@@ -729,4 +729,13 @@ int sde_crtc_helper_reset_custom_properties(struct drm_crtc *crtc,
 * @crtc: Pointer to crtc
 */
void sde_crtc_timeline_status(struct drm_crtc *crtc);

/**
 * sde_crtc_update_cont_splash_mixer_settings - update mixer settings
 *	during device bootup for cont_splash use case
 * @crtc: Pointer to drm crtc structure
 */
void sde_crtc_update_cont_splash_mixer_settings(
		struct drm_crtc *crtc);

#endif /* _SDE_CRTC_H_ */
+173 −0
Original line number Diff line number Diff line
@@ -4061,3 +4061,176 @@ enum sde_intf_mode sde_encoder_get_intf_mode(struct drm_encoder *encoder)

	return INTF_MODE_NONE;
}

/**
 * sde_encoder_update_caps_for_cont_splash - update encoder settings during
 *	device bootup when cont_splash is enabled
 * @drm_enc:    Pointer to drm encoder structure
 * @Return:	true if successful in updating the encoder structure
 */
int sde_encoder_update_caps_for_cont_splash(struct drm_encoder *encoder)
{
	struct sde_encoder_virt *sde_enc;
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;
	struct drm_connector *conn = NULL;
	struct sde_connector *sde_conn = NULL;
	struct sde_connector_state *sde_conn_state = NULL;
	struct drm_display_mode *drm_mode = NULL;
	struct sde_rm_hw_iter dsc_iter, pp_iter, ctl_iter;
	int ret = 0, i;

	if (!encoder) {
		SDE_ERROR("invalid drm enc\n");
		return -EINVAL;
	}

	if (!encoder->dev || !encoder->dev->dev_private) {
		SDE_ERROR("drm device invalid\n");
		return -EINVAL;
	}

	priv = encoder->dev->dev_private;
	if (!priv->kms) {
		SDE_ERROR("invalid kms\n");
		return -EINVAL;
	}

	sde_kms = to_sde_kms(priv->kms);
	sde_enc = to_sde_encoder_virt(encoder);
	if (!priv->num_connectors) {
		SDE_ERROR_ENC(sde_enc, "No connectors registered\n");
		return -EINVAL;
	}
	SDE_DEBUG_ENC(sde_enc,
			"num of connectors: %d\n", priv->num_connectors);

	for (i = 0; i < priv->num_connectors; i++) {
		SDE_DEBUG_ENC(sde_enc, "connector id: %d\n",
				priv->connectors[i]->base.id);
		sde_conn = to_sde_connector(priv->connectors[i]);
		if (!sde_conn->encoder) {
			SDE_DEBUG_ENC(sde_enc,
				"encoder not attached to connector\n");
			continue;
		}
		if (sde_conn->encoder->base.id
				== encoder->base.id) {
			conn = (priv->connectors[i]);
			break;
		}
	}

	if (!conn || !conn->state) {
		SDE_ERROR_ENC(sde_enc, "connector not found\n");
		return -EINVAL;
	}

	sde_conn_state = to_sde_connector_state(conn->state);

	if (!sde_conn->ops.get_mode_info) {
		SDE_ERROR_ENC(sde_enc, "conn: get_mode_info ops not found\n");
		return -EINVAL;
	}

	ret = sde_conn->ops.get_mode_info(&encoder->crtc->state->adjusted_mode,
				&sde_conn_state->mode_info,
				sde_kms->catalog->max_mixer_width,
				sde_conn->display);
	if (ret) {
		SDE_ERROR_ENC(sde_enc,
			"conn: ->get_mode_info failed. ret=%d\n", ret);
		return ret;
	}

	ret = sde_rm_reserve(&sde_kms->rm, encoder, encoder->crtc->state,
			conn->state, false);
	if (ret) {
		SDE_ERROR_ENC(sde_enc,
			"failed to reserve hw resources, %d\n", ret);
		return ret;
	}

	if (conn->encoder) {
		conn->state->best_encoder = conn->encoder;
		SDE_DEBUG_ENC(sde_enc,
			"configured cstate->best_encoder to ID = %d\n",
			conn->state->best_encoder->base.id);
	} else {
		SDE_ERROR_ENC(sde_enc, "No encoder mapped to connector=%d\n",
				conn->base.id);
	}

	SDE_DEBUG_ENC(sde_enc, "connector topology = %llu\n",
			sde_connector_get_topology_name(conn));
	drm_mode = &encoder->crtc->state->adjusted_mode;
	SDE_DEBUG_ENC(sde_enc, "hdisplay = %d, vdisplay = %d\n",
			drm_mode->hdisplay, drm_mode->vdisplay);
	drm_set_preferred_mode(conn, drm_mode->hdisplay, drm_mode->vdisplay);

	if (encoder->bridge) {
		SDE_DEBUG_ENC(sde_enc, "Bridge mapped to encoder\n");
		/*
		 * For cont-splash use case, we update the mode
		 * configurations manually. This will skip the
		 * usually mode set call when actual frame is
		 * pushed from framework. The bridge needs to
		 * be updated with the current drm mode by
		 * calling the bridge mode set ops.
		 */
		if (encoder->bridge->funcs) {
			SDE_DEBUG_ENC(sde_enc, "calling mode_set\n");
			encoder->bridge->funcs->mode_set(encoder->bridge,
						drm_mode, drm_mode);
		}
	} else {
		SDE_ERROR_ENC(sde_enc, "No bridge attached to encoder\n");
	}

	sde_rm_init_hw_iter(&pp_iter, encoder->base.id, SDE_HW_BLK_PINGPONG);
	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
		sde_enc->hw_pp[i] = NULL;
		if (!sde_rm_get_hw(&sde_kms->rm, &pp_iter))
			break;
		sde_enc->hw_pp[i] = (struct sde_hw_pingpong *) pp_iter.hw;
	}

	sde_rm_init_hw_iter(&dsc_iter, encoder->base.id, SDE_HW_BLK_DSC);
	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
		sde_enc->hw_dsc[i] = NULL;
		if (!sde_rm_get_hw(&sde_kms->rm, &dsc_iter))
			break;
		sde_enc->hw_dsc[i] = (struct sde_hw_dsc *) dsc_iter.hw;
	}

	sde_rm_init_hw_iter(&ctl_iter, encoder->base.id, SDE_HW_BLK_CTL);
	for (i = 0; i < sde_enc->num_phys_encs; i++) {
		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];

		phys->hw_ctl = NULL;
		if (!sde_rm_get_hw(&sde_kms->rm, &ctl_iter))
			break;
		phys->hw_ctl = (struct sde_hw_ctl *) ctl_iter.hw;
	}

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

		if (!phys) {
			SDE_ERROR_ENC(sde_enc,
				"phys encoders not initialized\n");
			return -EINVAL;
		}

		phys->hw_pp = sde_enc->hw_pp[i];
		if (phys->ops.cont_splash_mode_set)
			phys->ops.cont_splash_mode_set(phys, drm_mode);

		if (phys->ops.is_master && phys->ops.is_master(phys)) {
			phys->connector = conn;
			sde_enc->cur_master = phys;
		}
	}

	return ret;
}
Loading