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

Commit 4347ed7a authored by Alan Kwong's avatar Alan Kwong Committed by Steve Cohen
Browse files

drm/msm: add check for power handle enable failure



Add check for power handle enable failure so that
subsequent failures due to lack of power or clock
can be avoided.

Change-Id: I903c982d9ddd85a353a55879f5ad03436d0844da
Signed-off-by: default avatarAlan Kwong <akwong@codeaurora.org>
parent 42bc6748
Loading
Loading
Loading
Loading
+6 −3
Original line number Original line Diff line number Diff line
@@ -577,23 +577,26 @@ int sde_connector_pre_kickoff(struct drm_connector *connector)
	return rc;
	return rc;
}
}


void sde_connector_clk_ctrl(struct drm_connector *connector, bool enable)
int sde_connector_clk_ctrl(struct drm_connector *connector, bool enable)
{
{
	struct sde_connector *c_conn;
	struct sde_connector *c_conn;
	struct dsi_display *display;
	struct dsi_display *display;
	u32 state = enable ? DSI_CLK_ON : DSI_CLK_OFF;
	u32 state = enable ? DSI_CLK_ON : DSI_CLK_OFF;
	int rc = 0;


	if (!connector) {
	if (!connector) {
		SDE_ERROR("invalid connector\n");
		SDE_ERROR("invalid connector\n");
		return;
		return -EINVAL;
	}
	}


	c_conn = to_sde_connector(connector);
	c_conn = to_sde_connector(connector);
	display = (struct dsi_display *) c_conn->display;
	display = (struct dsi_display *) c_conn->display;


	if (display && c_conn->ops.clk_ctrl)
	if (display && c_conn->ops.clk_ctrl)
		c_conn->ops.clk_ctrl(display->mdp_clk_handle,
		rc = c_conn->ops.clk_ctrl(display->mdp_clk_handle,
				DSI_ALL_CLKS, state);
				DSI_ALL_CLKS, state);

	return rc;
}
}


static void sde_connector_destroy(struct drm_connector *connector)
static void sde_connector_destroy(struct drm_connector *connector)
+2 −1
Original line number Original line Diff line number Diff line
@@ -547,8 +547,9 @@ int sde_connector_get_info(struct drm_connector *connector,
 * sde_connector_clk_ctrl - enables/disables the connector clks
 * sde_connector_clk_ctrl - enables/disables the connector clks
 * @connector: Pointer to drm connector object
 * @connector: Pointer to drm connector object
 * @enable: true/false to enable/disable
 * @enable: true/false to enable/disable
 * Returns: Zero on success
 */
 */
void sde_connector_clk_ctrl(struct drm_connector *connector, bool enable);
int sde_connector_clk_ctrl(struct drm_connector *connector, bool enable);


/**
/**
 * sde_connector_get_dpms - query dpms setting
 * sde_connector_get_dpms - query dpms setting
+18 −2
Original line number Original line Diff line number Diff line
@@ -460,6 +460,7 @@ void sde_core_irq_preinstall(struct sde_kms *sde_kms)
{
{
	struct msm_drm_private *priv;
	struct msm_drm_private *priv;
	int i;
	int i;
	int rc;


	if (!sde_kms) {
	if (!sde_kms) {
		SDE_ERROR("invalid sde_kms\n");
		SDE_ERROR("invalid sde_kms\n");
@@ -473,7 +474,14 @@ void sde_core_irq_preinstall(struct sde_kms *sde_kms)
	}
	}
	priv = sde_kms->dev->dev_private;
	priv = sde_kms->dev->dev_private;


	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
	rc = sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
			true);
	if (rc) {
		SDE_ERROR("failed to enable power resource %d\n", rc);
		SDE_EVT32(rc, SDE_EVTLOG_ERROR);
		return;
	}

	sde_clear_all_irqs(sde_kms);
	sde_clear_all_irqs(sde_kms);
	sde_disable_all_irqs(sde_kms);
	sde_disable_all_irqs(sde_kms);
	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
@@ -504,6 +512,7 @@ void sde_core_irq_uninstall(struct sde_kms *sde_kms)
{
{
	struct msm_drm_private *priv;
	struct msm_drm_private *priv;
	int i;
	int i;
	int rc;


	if (!sde_kms) {
	if (!sde_kms) {
		SDE_ERROR("invalid sde_kms\n");
		SDE_ERROR("invalid sde_kms\n");
@@ -517,7 +526,14 @@ void sde_core_irq_uninstall(struct sde_kms *sde_kms)
	}
	}
	priv = sde_kms->dev->dev_private;
	priv = sde_kms->dev->dev_private;


	sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
	rc = sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
			true);
	if (rc) {
		SDE_ERROR("failed to enable power resource %d\n", rc);
		SDE_EVT32(rc, SDE_EVTLOG_ERROR);
		return;
	}

	for (i = 0; i < sde_kms->irq_obj.total_irqs; i++)
	for (i = 0; i < sde_kms->irq_obj.total_irqs; i++)
		if (atomic_read(&sde_kms->irq_obj.enable_counts[i]) ||
		if (atomic_read(&sde_kms->irq_obj.enable_counts[i]) ||
				!list_empty(&sde_kms->irq_obj.irq_cb_tbl[i]))
				!list_empty(&sde_kms->irq_obj.irq_cb_tbl[i]))
+39 −3
Original line number Original line Diff line number Diff line
@@ -3053,6 +3053,11 @@ static void sde_crtc_atomic_begin(struct drm_crtc *crtc,
		return;
		return;
	}
	}


	if (!sde_kms_power_resource_is_enabled(crtc->dev)) {
		SDE_ERROR("power resource is not enabled\n");
		return;
	}

	SDE_DEBUG("crtc%d\n", crtc->base.id);
	SDE_DEBUG("crtc%d\n", crtc->base.id);


	sde_crtc = to_sde_crtc(crtc);
	sde_crtc = to_sde_crtc(crtc);
@@ -3142,6 +3147,11 @@ static void sde_crtc_atomic_flush(struct drm_crtc *crtc,
		return;
		return;
	}
	}


	if (!sde_kms_power_resource_is_enabled(crtc->dev)) {
		SDE_ERROR("power resource is not enabled\n");
		return;
	}

	SDE_DEBUG("crtc%d\n", crtc->base.id);
	SDE_DEBUG("crtc%d\n", crtc->base.id);


	sde_crtc = to_sde_crtc(crtc);
	sde_crtc = to_sde_crtc(crtc);
@@ -4055,6 +4065,12 @@ static void sde_crtc_disable(struct drm_crtc *crtc)
		SDE_ERROR("invalid crtc\n");
		SDE_ERROR("invalid crtc\n");
		return;
		return;
	}
	}

	if (!sde_kms_power_resource_is_enabled(crtc->dev)) {
		SDE_ERROR("power resource is not enabled\n");
		return;
	}

	sde_crtc = to_sde_crtc(crtc);
	sde_crtc = to_sde_crtc(crtc);
	cstate = to_sde_crtc_state(crtc->state);
	cstate = to_sde_crtc_state(crtc->state);
	priv = crtc->dev->dev_private;
	priv = crtc->dev->dev_private;
@@ -4170,6 +4186,11 @@ static void sde_crtc_enable(struct drm_crtc *crtc,
	}
	}
	priv = crtc->dev->dev_private;
	priv = crtc->dev->dev_private;


	if (!sde_kms_power_resource_is_enabled(crtc->dev)) {
		SDE_ERROR("power resource is not enabled\n");
		return;
	}

	SDE_DEBUG("crtc%d\n", crtc->base.id);
	SDE_DEBUG("crtc%d\n", crtc->base.id);
	SDE_EVT32_VERBOSE(DRMID(crtc));
	SDE_EVT32_VERBOSE(DRMID(crtc));
	sde_crtc = to_sde_crtc(crtc);
	sde_crtc = to_sde_crtc(crtc);
@@ -5830,8 +5851,15 @@ static int _sde_crtc_event_enable(struct sde_kms *kms,
	priv = kms->dev->dev_private;
	priv = kms->dev->dev_private;
	ret = 0;
	ret = 0;
	if (crtc_drm->enabled) {
	if (crtc_drm->enabled) {
		sde_power_resource_enable(&priv->phandle, kms->core_client,
		ret = sde_power_resource_enable(&priv->phandle,
				true);
				kms->core_client, true);
		if (ret) {
			SDE_ERROR("failed to enable power resource %d\n", ret);
			SDE_EVT32(ret, SDE_EVTLOG_ERROR);
			kfree(node);
			return ret;
		}

		INIT_LIST_HEAD(&node->irq.list);
		INIT_LIST_HEAD(&node->irq.list);
		ret = node->func(crtc_drm, true, &node->irq);
		ret = node->func(crtc_drm, true, &node->irq);
		sde_power_resource_enable(&priv->phandle, kms->core_client,
		sde_power_resource_enable(&priv->phandle, kms->core_client,
@@ -5885,7 +5913,15 @@ static int _sde_crtc_event_disable(struct sde_kms *kms,
		return 0;
		return 0;
	}
	}
	priv = kms->dev->dev_private;
	priv = kms->dev->dev_private;
	sde_power_resource_enable(&priv->phandle, kms->core_client, true);
	ret = sde_power_resource_enable(&priv->phandle, kms->core_client, true);
	if (ret) {
		SDE_ERROR("failed to enable power resource %d\n", ret);
		SDE_EVT32(ret, SDE_EVTLOG_ERROR);
		list_del(&node->list);
		kfree(node);
		return ret;
	}

	ret = node->func(crtc_drm, false, &node->irq);
	ret = node->func(crtc_drm, false, &node->irq);
	list_del(&node->list);
	list_del(&node->list);
	kfree(node);
	kfree(node);
+63 −7
Original line number Original line Diff line number Diff line
@@ -1670,12 +1670,13 @@ static void _sde_encoder_resource_control_rsc_update(
	}
	}
}
}


static void _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc,
static int _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc,
		bool enable)
		bool enable)
{
{
	struct msm_drm_private *priv;
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;
	struct sde_kms *sde_kms;
	struct sde_encoder_virt *sde_enc;
	struct sde_encoder_virt *sde_enc;
	int rc;


	sde_enc = to_sde_encoder_virt(drm_enc);
	sde_enc = to_sde_encoder_virt(drm_enc);
	priv = drm_enc->dev->dev_private;
	priv = drm_enc->dev->dev_private;
@@ -1686,16 +1687,28 @@ static void _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc,


	if (!sde_enc->cur_master) {
	if (!sde_enc->cur_master) {
		SDE_ERROR("encoder master not set\n");
		SDE_ERROR("encoder master not set\n");
		return;
		return -EINVAL;
	}
	}


	if (enable) {
	if (enable) {
		/* enable SDE core clks */
		/* enable SDE core clks */
		sde_power_resource_enable(&priv->phandle,
		rc = sde_power_resource_enable(&priv->phandle,
				sde_kms->core_client, true);
				sde_kms->core_client, true);
		if (rc) {
			SDE_ERROR("failed to enable power resource %d\n", rc);
			SDE_EVT32(rc, SDE_EVTLOG_ERROR);
			return rc;
		}


		/* enable DSI clks */
		/* enable DSI clks */
		sde_connector_clk_ctrl(sde_enc->cur_master->connector, true);
		rc = sde_connector_clk_ctrl(sde_enc->cur_master->connector,
				true);
		if (rc) {
			SDE_ERROR("failed to enable clk control %d\n", rc);
			sde_power_resource_enable(&priv->phandle,
					sde_kms->core_client, false);
			return rc;
		}


		/* enable all the irq */
		/* enable all the irq */
		_sde_encoder_irq_control(drm_enc, true);
		_sde_encoder_irq_control(drm_enc, true);
@@ -1712,6 +1725,7 @@ static void _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc,
				sde_kms->core_client, false);
				sde_kms->core_client, false);
	}
	}


	return 0;
}
}


static int sde_encoder_resource_control(struct drm_encoder *drm_enc,
static int sde_encoder_resource_control(struct drm_encoder *drm_enc,
@@ -1790,7 +1804,19 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc,
			_sde_encoder_irq_control(drm_enc, true);
			_sde_encoder_irq_control(drm_enc, true);
		} else {
		} else {
			/* enable all the clks and resources */
			/* enable all the clks and resources */
			_sde_encoder_resource_control_helper(drm_enc, true);
			ret = _sde_encoder_resource_control_helper(drm_enc,
					true);
			if (ret) {
				SDE_ERROR_ENC(sde_enc,
						"sw_event:%d, rc in state %d\n",
						sw_event, sde_enc->rc_state);
				SDE_EVT32(DRMID(drm_enc), sw_event,
						sde_enc->rc_state,
						SDE_EVTLOG_ERROR);
				mutex_unlock(&sde_enc->rc_lock);
				return ret;
			}

			_sde_encoder_resource_control_rsc_update(drm_enc, true);
			_sde_encoder_resource_control_rsc_update(drm_enc, true);
		}
		}


@@ -1949,7 +1975,18 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc,
		/* return if the resource control is already in ON state */
		/* return if the resource control is already in ON state */
		if (sde_enc->rc_state != SDE_ENC_RC_STATE_ON) {
		if (sde_enc->rc_state != SDE_ENC_RC_STATE_ON) {
			/* enable all the clks and resources */
			/* enable all the clks and resources */
			_sde_encoder_resource_control_helper(drm_enc, true);
			ret = _sde_encoder_resource_control_helper(drm_enc,
					true);
			if (ret) {
				SDE_ERROR_ENC(sde_enc,
						"sw_event:%d, rc in state %d\n",
						sw_event, sde_enc->rc_state);
				SDE_EVT32(DRMID(drm_enc), sw_event,
						sde_enc->rc_state,
						SDE_EVTLOG_ERROR);
				mutex_unlock(&sde_enc->rc_lock);
				return ret;
			}


			_sde_encoder_resource_control_rsc_update(drm_enc, true);
			_sde_encoder_resource_control_rsc_update(drm_enc, true);


@@ -2078,6 +2115,11 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
		return;
		return;
	}
	}


	if (!sde_kms_power_resource_is_enabled(drm_enc->dev)) {
		SDE_ERROR("power resource is not enabled\n");
		return;
	}

	sde_enc = to_sde_encoder_virt(drm_enc);
	sde_enc = to_sde_encoder_virt(drm_enc);
	SDE_DEBUG_ENC(sde_enc, "\n");
	SDE_DEBUG_ENC(sde_enc, "\n");


@@ -2285,6 +2327,11 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
	}
	}
	sde_enc = to_sde_encoder_virt(drm_enc);
	sde_enc = to_sde_encoder_virt(drm_enc);


	if (!sde_kms_power_resource_is_enabled(drm_enc->dev)) {
		SDE_ERROR("power resource is not enabled\n");
		return;
	}

	ret = _sde_encoder_get_mode_info(drm_enc, &mode_info);
	ret = _sde_encoder_get_mode_info(drm_enc, &mode_info);
	if (ret) {
	if (ret) {
		SDE_ERROR_ENC(sde_enc, "failed to get mode info\n");
		SDE_ERROR_ENC(sde_enc, "failed to get mode info\n");
@@ -2379,6 +2426,11 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
		return;
		return;
	}
	}


	if (!sde_kms_power_resource_is_enabled(drm_enc->dev)) {
		SDE_ERROR("power resource is not enabled\n");
		return;
	}

	sde_enc = to_sde_encoder_virt(drm_enc);
	sde_enc = to_sde_encoder_virt(drm_enc);
	SDE_DEBUG_ENC(sde_enc, "\n");
	SDE_DEBUG_ENC(sde_enc, "\n");


@@ -3309,7 +3361,11 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc,
	}
	}
	SDE_ATRACE_END("enc_prepare_for_kickoff");
	SDE_ATRACE_END("enc_prepare_for_kickoff");


	sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_KICKOFF);
	rc = sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_KICKOFF);
	if (rc) {
		SDE_ERROR_ENC(sde_enc, "resource kickoff failed rc %d\n", rc);
		return rc;
	}


	/* if any phys needs reset, reset all phys, in-order */
	/* if any phys needs reset, reset all phys, in-order */
	if (needs_hw_reset) {
	if (needs_hw_reset) {
Loading