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

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

Merge "drm/msm/sde: add plane support for halt and rotate reset"

parents a5849b5c 2606dd63
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -588,6 +588,10 @@ static int sde_hw_rot_commit(struct sde_hw_rot *hw, struct sde_hw_rot_cmd *data,
		cmd_type = SDE_ROTATOR_INLINE_CMD_CLEANUP;
		priv_handle = data->priv_handle;
		break;
	case SDE_HW_ROT_CMD_RESET:
		cmd_type = SDE_ROTATOR_INLINE_CMD_ABORT;
		priv_handle = data->priv_handle;
		break;
	default:
		SDE_ERROR("invalid hw rotator command %d\n", hw_cmd);
		return -EINVAL;
+2 −0
Original line number Diff line number Diff line
@@ -28,12 +28,14 @@ struct sde_hw_rot;
 * @SDE_HW_ROT_CMD_COMMIT: commit/execute rotator command
 * @SDE_HW_ROT_CMD_START: mdp is ready to start
 * @SDE_HW_ROT_CMD_CLEANUP: cleanup rotator command after it is done
 * @SDE_HW_ROT_CMD_RESET: request rotator h/w reset
 */
enum sde_hw_rot_cmd_type {
	SDE_HW_ROT_CMD_VALIDATE,
	SDE_HW_ROT_CMD_COMMIT,
	SDE_HW_ROT_CMD_START,
	SDE_HW_ROT_CMD_CLEANUP,
	SDE_HW_ROT_CMD_RESET,
};

/**
+107 −0
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ enum sde_plane_qos {
 * @sbuf_mode: force stream buffer mode if set
 * @sbuf_writeback: force stream buffer writeback if set
 * @revalidate: force revalidation of all the plane properties
 * @xin_halt_forced_clk: whether or not clocks were forced on for xin halt
 * @blob_rot_caps: Pointer to rotator capability blob
 */
struct sde_plane {
@@ -128,6 +129,7 @@ struct sde_plane {
	u32 sbuf_mode;
	u32 sbuf_writeback;
	bool revalidate;
	bool xin_halt_forced_clk;

	struct sde_csc_cfg csc_cfg;
	struct sde_csc_cfg *csc_usr_ptr;
@@ -2489,6 +2491,111 @@ static void sde_plane_rot_atomic_update(struct drm_plane *plane,
	msm_framebuffer_cleanup(state->fb, pstate->aspace);
}

static bool _sde_plane_halt_requests(struct drm_plane *plane,
		uint32_t xin_id, bool halt_forced_clk, bool enable)
{
	struct sde_plane *psde;
	struct msm_drm_private *priv;
	struct sde_vbif_set_xin_halt_params halt_params;

	if (!plane || !plane->dev) {
		SDE_ERROR("invalid arguments\n");
		return false;
	}

	psde = to_sde_plane(plane);
	if (!psde->pipe_hw || !psde->pipe_hw->cap) {
		SDE_ERROR("invalid pipe reference\n");
		return false;
	}

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

	memset(&halt_params, 0, sizeof(halt_params));
	halt_params.vbif_idx = VBIF_RT;
	halt_params.xin_id = xin_id;
	halt_params.clk_ctrl = psde->pipe_hw->cap->clk_ctrl;
	halt_params.forced_on = halt_forced_clk;
	halt_params.enable = enable;

	return sde_vbif_set_xin_halt(to_sde_kms(priv->kms), &halt_params);
}

void sde_plane_halt_requests(struct drm_plane *plane, bool enable)
{
	struct sde_plane *psde;

	if (!plane) {
		SDE_ERROR("invalid plane\n");
		return;
	}

	psde = to_sde_plane(plane);
	if (!psde->pipe_hw || !psde->pipe_hw->cap) {
		SDE_ERROR("invalid pipe reference\n");
		return;
	}

	SDE_EVT32(DRMID(plane), psde->xin_halt_forced_clk, enable);

	psde->xin_halt_forced_clk =
		_sde_plane_halt_requests(plane, psde->pipe_hw->cap->xin_id,
				psde->xin_halt_forced_clk, enable);
}

int sde_plane_reset_rot(struct drm_plane *plane, struct drm_plane_state *state)
{
	struct sde_plane *psde;
	struct sde_plane_state *pstate;
	struct sde_plane_rot_state *rstate;
	bool halt_ret[MAX_BLOCKS] = {false};
	signed int i, count;

	if (!plane || !state) {
		SDE_ERROR("invalid plane\n");
		return -EINVAL;
	}

	psde = to_sde_plane(plane);
	pstate = to_sde_plane_state(state);
	rstate = &pstate->rot;

	/* do nothing if not master rotator plane */
	if (!rstate->out_sbuf || !rstate->rot_hw ||
			!rstate->rot_hw->caps || (rstate->out_xpos != 0))
		return 0;

	count = (signed int)rstate->rot_hw->caps->xin_count;
	if (count > ARRAY_SIZE(halt_ret))
		count = ARRAY_SIZE(halt_ret);

	SDE_DEBUG_PLANE(psde, "issuing reset for rotator\n");
	SDE_EVT32(DRMID(plane), count);

	for (i = 0; i < count; i++) {
		const struct sde_rot_vbif_cfg *cfg =
				&rstate->rot_hw->caps->vbif_cfg[i];

		halt_ret[i] = _sde_plane_halt_requests(plane, cfg->xin_id,
				false, true);
	}

	sde_plane_rot_submit_command(plane, state, SDE_HW_ROT_CMD_RESET);

	for (i = count - 1; i >= 0; --i) {
		const struct sde_rot_vbif_cfg *cfg =
				&rstate->rot_hw->caps->vbif_cfg[i];

		_sde_plane_halt_requests(plane, cfg->xin_id,
				halt_ret[i], false);
	}
	return 0;
}

int sde_plane_kickoff_rot(struct drm_plane *plane)
{
	struct sde_plane_state *pstate;
+17 −0
Original line number Diff line number Diff line
@@ -227,6 +227,23 @@ void sde_plane_restore(struct drm_plane *plane);
 */
void sde_plane_flush(struct drm_plane *plane);

/**
 * sde_plane_halt_requests - control halting of vbif transactions for this plane
 *	This function isn't thread safe. Plane halt enable/disable requests
 *	should always be made from the same commit cycle.
 * @plane: Pointer to drm plane structure
 * @enable: Whether to enable/disable halting of vbif transactions
 */
void sde_plane_halt_requests(struct drm_plane *plane, bool enable);

/**
 * sde_plane_reset_rot - reset rotator operations before commit kickoff
 * @plane: Pointer to drm plane structure
 * @state: Pointer to plane state associated with reset request
 * Returns: Zero on success
 */
int sde_plane_reset_rot(struct drm_plane *plane, struct drm_plane_state *state);

/**
 * sde_plane_kickoff_rot - final plane rotator operations before commit kickoff
 * @plane: Pointer to drm plane structure
+56 −2
Original line number Diff line number Diff line
@@ -230,13 +230,15 @@ void sde_vbif_set_ot_limit(struct sde_kms *sde_kms,

	for (i = 0; i < ARRAY_SIZE(sde_kms->hw_vbif); i++) {
		if (sde_kms->hw_vbif[i] &&
				sde_kms->hw_vbif[i]->idx == params->vbif_idx)
				sde_kms->hw_vbif[i]->idx == params->vbif_idx) {
			vbif = sde_kms->hw_vbif[i];
			break;
		}
	}

	if (!vbif || !mdp) {
		SDE_DEBUG("invalid arguments vbif %d mdp %d\n",
				vbif != 0, mdp != 0);
				vbif != NULL, mdp != NULL);
		return;
	}

@@ -275,6 +277,58 @@ void sde_vbif_set_ot_limit(struct sde_kms *sde_kms,
	return;
}

bool sde_vbif_set_xin_halt(struct sde_kms *sde_kms,
		struct sde_vbif_set_xin_halt_params *params)
{
	struct sde_hw_vbif *vbif = NULL;
	struct sde_hw_mdp *mdp;
	bool forced_on = false;
	int ret, i;

	if (!sde_kms || !params) {
		SDE_ERROR("invalid arguments\n");
		return false;
	}
	mdp = sde_kms->hw_mdp;

	for (i = 0; i < ARRAY_SIZE(sde_kms->hw_vbif); i++) {
		if (sde_kms->hw_vbif[i] &&
				sde_kms->hw_vbif[i]->idx == params->vbif_idx) {
			vbif = sde_kms->hw_vbif[i];
			break;
		}
	}

	if (!vbif || !mdp) {
		SDE_DEBUG("invalid arguments vbif %d mdp %d\n",
				vbif != NULL, mdp != NULL);
		return false;
	}

	if (!mdp->ops.setup_clk_force_ctrl ||
			!vbif->ops.set_halt_ctrl)
		return false;

	if (params->enable) {
		forced_on = mdp->ops.setup_clk_force_ctrl(mdp,
				params->clk_ctrl, true);

		vbif->ops.set_halt_ctrl(vbif, params->xin_id, true);

		ret = _sde_vbif_wait_for_xin_halt(vbif, params->xin_id);
		if (ret)
			SDE_EVT32(vbif->idx, params->xin_id, SDE_EVTLOG_ERROR);
	} else {
		vbif->ops.set_halt_ctrl(vbif, params->xin_id, false);

		if (params->forced_on)
			mdp->ops.setup_clk_force_ctrl(mdp,
					params->clk_ctrl, false);
	}

	return forced_on;
}

void sde_vbif_set_qos_remap(struct sde_kms *sde_kms,
		struct sde_vbif_set_qos_params *params)
{
Loading