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

Commit 6dada373 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/mdm/sde: add plane fetch halt"

parents 7f5a328b ea808378
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -176,6 +176,7 @@ static bool sde_hw_setup_clk_force_ctrl(struct sde_hw_mdp *mdp,
		new_val = reg_val & ~BIT(bit_off);

	SDE_REG_WRITE(c, reg_off, new_val);
	wmb(); /* ensure write finished before progressing */

	clk_forced_on = !(reg_val & BIT(bit_off));

+57 −1
Original line number Diff line number Diff line
@@ -2868,20 +2868,76 @@ static int sde_plane_prepare_fb(struct drm_plane *plane,
	return 0;
}

/**
 * _sde_plane_fetch_halt - halts vbif transactions for a plane
 * @plane: Pointer to plane
 * Returns: 0 on success
 */
static int _sde_plane_fetch_halt(struct drm_plane *plane)
{
	struct sde_plane *psde;
	int xin_id;
	enum sde_clk_ctrl_type clk_ctrl;
	struct msm_drm_private *priv;
	struct sde_kms *sde_kms;

	psde = to_sde_plane(plane);
	if (!plane || !plane->dev || !psde->pipe_hw) {
		SDE_ERROR("invalid arguments\n");
		return -EINVAL;
	}

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

	sde_kms = to_sde_kms(priv->kms);
	clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
	xin_id = psde->pipe_hw->cap->xin_id;
	SDE_DEBUG_PLANE(psde, "pipe:%d xin_id:%d clk_ctrl:%d\n",
			psde->pipe - SSPP_VIG0, xin_id, clk_ctrl);
	SDE_EVT32_VERBOSE(psde, psde->pipe - SSPP_VIG0, xin_id, clk_ctrl);

	return sde_vbif_halt_plane_xin(sde_kms, xin_id, clk_ctrl);
}

static void sde_plane_cleanup_fb(struct drm_plane *plane,
		struct drm_plane_state *old_state)
{
	struct sde_plane *psde = to_sde_plane(plane);
	struct sde_plane_state *old_pstate;
	struct sde_plane_rot_state *old_rstate;
	int ret;

	if (!old_state || !old_state->fb)
	if (!old_state || !old_state->fb || !plane || !plane->state)
		return;

	old_pstate = to_sde_plane_state(old_state);

	SDE_DEBUG_PLANE(psde, "FB[%u]\n", old_state->fb->base.id);

	/*
	 * plane->state gets populated for next frame after swap_state. If
	 * plane->state->crtc pointer is not populated then it is not used in
	 * the next frame, hence making it an unused plane.
	 */
	if ((plane->state->crtc == NULL) && !psde->is_virtual) {
		SDE_DEBUG_PLANE(psde, "unused pipe:%u\n",
			       psde->pipe - SSPP_VIG0);

		/* halt this plane now */
		ret = _sde_plane_fetch_halt(plane);
		if (ret) {
			SDE_ERROR_PLANE(psde,
				       "unused pipe %u halt failed\n",
				       psde->pipe - SSPP_VIG0);
			SDE_EVT32(DRMID(plane), psde->pipe - SSPP_VIG0,
				       ret, SDE_EVTLOG_ERROR);
		}
	}

	old_rstate = &old_pstate->rot;

	msm_framebuffer_cleanup(old_rstate->out_fb, old_pstate->aspace);
+61 −0
Original line number Diff line number Diff line
@@ -60,6 +60,67 @@ static int _sde_vbif_wait_for_xin_halt(struct sde_hw_vbif *vbif, u32 xin_id)
	return rc;
}

int sde_vbif_halt_plane_xin(struct sde_kms *sde_kms, u32 xin_id, u32 clk_ctrl)
{
	struct sde_hw_vbif *vbif = NULL;
	struct sde_hw_mdp *mdp;
	bool forced_on = false;
	bool status;
	int rc = 0;

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

	vbif = sde_kms->hw_vbif[VBIF_RT];
	mdp = sde_kms->hw_mdp;
	if (!vbif || !mdp || !vbif->ops.get_halt_ctrl ||
		       !vbif->ops.set_halt_ctrl ||
		       !mdp->ops.setup_clk_force_ctrl) {
		SDE_ERROR("invalid vbif or mdp arguments\n");
		return -EINVAL;
	}

	/*
	 * If status is 0, then make sure client clock is not gated
	 * while halting by forcing it ON only if it was not previously
	 * forced on. If status is 1 then its already halted.
	 */
	status = vbif->ops.get_halt_ctrl(vbif, xin_id);
	if (status == 0)
		forced_on = mdp->ops.setup_clk_force_ctrl(mdp, clk_ctrl, true);
	else
		return 0;

	/* send halt request for unused plane's xin client */
	vbif->ops.set_halt_ctrl(vbif, xin_id, true);

	rc = _sde_vbif_wait_for_xin_halt(vbif, xin_id);
	if (rc) {
		SDE_ERROR(
		"wait failed for pipe halt:xin_id %u, clk_ctrl %u, rc %u\n",
			xin_id, clk_ctrl, rc);
		SDE_EVT32(xin_id, clk_ctrl, rc, SDE_EVTLOG_ERROR);
		return rc;
	}

	status = vbif->ops.get_halt_ctrl(vbif, xin_id);
	if (status == 0) {
		SDE_ERROR("halt failed for pipe xin_id %u halt clk_ctrl %u\n",
			       xin_id, clk_ctrl);
		SDE_EVT32(xin_id, clk_ctrl, SDE_EVTLOG_ERROR);
		return -ETIMEDOUT;
	}

	/* open xin client to enable transactions */
	vbif->ops.set_halt_ctrl(vbif, xin_id, false);
	if (forced_on)
		mdp->ops.setup_clk_force_ctrl(mdp, clk_ctrl, false);

	return 0;
}

/**
 * _sde_vbif_apply_dynamic_ot_limit - determine OT based on usecase parameters
 * @vbif:	Pointer to hardware vbif driver
+14 −0
Original line number Diff line number Diff line
@@ -78,6 +78,20 @@ void sde_vbif_clear_errors(struct sde_kms *sde_kms);
 */
void sde_vbif_init_memtypes(struct sde_kms *sde_kms);

/**
 * sde_vbif_halt_plane_xin - halts the xin client for the unused plane
 * On unused plane, check if the vbif for this plane is idle or not.
 * If not then first force_on the planes clock and then send the
 * halt request. Wait for some time then check for the vbif idle
 * or not again.
 * @sde_kms:	SDE handler
 * @xin_id:	xin id of the unused plane
 * @clk_ctrl:	clk ctrl type for the unused plane
 * Returns:	0 on success, error code otherwise
 */
int sde_vbif_halt_plane_xin(struct sde_kms *sde_kms, u32 xin_id,
	       u32 clk_ctrl);

#ifdef CONFIG_DEBUG_FS
int sde_debugfs_vbif_init(struct sde_kms *sde_kms, struct dentry *debugfs_root);
void sde_debugfs_vbif_destroy(struct sde_kms *sde_kms);