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

Commit b25c65cb authored by Clarence Ip's avatar Clarence Ip
Browse files

msm: sde: support inline rotation start event



Inline rotations are triggered by the external DRM driver, so
the rotator driver needs to delay its 'is done' checking until
the DRM driver indicates that the commit has started.

This patch adds support for an 'inline start' command that may
be sent by the DRM driver to indicate that the hardware
commit is ready to begin.

CRs-Fixed: 2046958
Change-Id: I460fde8de1a3b815785f3ae7ea21c986b3ca68f1
Signed-off-by: default avatarClarence Ip <cip@codeaurora.org>
parent 22fed4cf
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -60,6 +60,9 @@
/* waiting for hw time out, 3 vsync for 30fps*/
#define ROT_HW_ACQUIRE_TIMEOUT_IN_MS 100

/* waiting for inline hw start */
#define ROT_INLINE_START_TIMEOUT_IN_MS 2000

/* default pixel per clock ratio */
#define ROT_PIXEL_PER_CLK_NUMERATOR	36
#define ROT_PIXEL_PER_CLK_DENOMINATOR	10
@@ -1508,6 +1511,8 @@ static void sde_rotator_commit_handler(struct work_struct *work)
	if (entry->item.ts)
		entry->item.ts[SDE_ROTATOR_TS_FLUSH] = ktime_get();

	SDEROT_EVTLOG(entry->item.session_id, 1);

	queue_work(entry->doneq->rot_work_queue, &entry->done_work);
	sde_rot_mgr_unlock(mgr);
	return;
@@ -1564,6 +1569,13 @@ static void sde_rotator_done_handler(struct work_struct *work)
		entry->item.flags,
		entry->dnsc_factor_w, entry->dnsc_factor_h);

	wait_for_completion_timeout(
			&entry->item.inline_start,
			msecs_to_jiffies(ROT_INLINE_START_TIMEOUT_IN_MS));

	if (entry->item.ts)
		entry->item.ts[SDE_ROTATOR_TS_START] = ktime_get();

	SDEROT_EVTLOG(entry->item.session_id, 0);
	ret = mgr->ops_wait_for_entry(hw, entry);
	if (ret) {
@@ -2332,11 +2344,36 @@ struct sde_rot_entry_container *sde_rotator_req_init(
	for (i = 0; i < count; i++) {
		req->entries[i].item = items[i];
		req->entries[i].private = private;

		init_completion(&req->entries[i].item.inline_start);
		complete_all(&req->entries[i].item.inline_start);
	}

	return req;
}

void sde_rotator_req_reset_start(struct sde_rot_entry_container *req)
{
	int i;

	if (!req)
		return;

	for (i = 0; i < req->count; i++)
		reinit_completion(&req->entries[i].item.inline_start);
}

void sde_rotator_req_set_start(struct sde_rot_entry_container *req)
{
	int i;

	if (!req)
		return;

	for (i = 0; i < req->count; i++)
		complete_all(&req->entries[i].item.inline_start);
}

void sde_rotator_req_finish(struct sde_rot_mgr *mgr,
	struct sde_rot_file_private *private,
	struct sde_rot_entry_container *req)
+22 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/pm_runtime.h>
#include <linux/completion.h>

#include "sde_rotator_base.h"
#include "sde_rotator_util.h"
@@ -115,6 +116,7 @@ enum sde_rotator_ts {
	SDE_ROTATOR_TS_QUEUE,		/* wait for h/w resource */
	SDE_ROTATOR_TS_COMMIT,		/* prepare h/w command */
	SDE_ROTATOR_TS_FLUSH,		/* initiate h/w processing */
	SDE_ROTATOR_TS_START,		/* h/w triggered (if inline) */
	SDE_ROTATOR_TS_DONE,		/* receive h/w completion */
	SDE_ROTATOR_TS_RETIRE,		/* signal destination buffer fence */
	SDE_ROTATOR_TS_SRCDQB,		/* dequeue source buffer */
@@ -199,6 +201,9 @@ struct sde_rotation_item {

	/* Time stamp for profiling purposes */
	ktime_t		*ts;

	/* Completion structure for inline rotation */
	struct completion inline_start;
};

/*
@@ -603,6 +608,23 @@ struct sde_rot_entry_container *sde_rotator_req_init(
	struct sde_rotation_item *items,
	u32 count, u32 flags);

/*
 * sde_rotator_req_reset_start - reset inline h/w 'start' indicator
 *	For inline rotations, the time of rotation start is not controlled
 *	by the rotator driver. This function resets an internal 'start'
 *	indicator that allows the rotator to delay its rotator
 *	timeout waiting until such time as the inline rotation has
 *	really started.
 * @req: Pointer to rotation request
 */
void sde_rotator_req_reset_start(struct sde_rot_entry_container *req);

/*
 * sde_rotator_req_set_start - set inline h/w 'start' indicator
 * @req: Pointer to rotation request
 */
void sde_rotator_req_set_start(struct sde_rot_entry_container *req);

/*
 * sde_rotator_req_finish - notify manager that client is finished with the
 *	given request and manager can release the request as required
+4 −2
Original line number Diff line number Diff line
@@ -789,7 +789,7 @@ static int sde_rotator_stat_show(struct seq_file *s, void *data)
					start_time));

		seq_printf(s,
			"s:%d sq:%lld dq:%lld fe:%lld q:%lld c:%lld fl:%lld d:%lld sdq:%lld ddq:%lld t:%lld oht:%lld\n",
			"s:%d sq:%lld dq:%lld fe:%lld q:%lld c:%lld fl:%lld st:%lld d:%lld sdq:%lld ddq:%lld t:%lld oht:%lld\n",
			i,
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_FENCE],
					ts[SDE_ROTATOR_TS_SRCQB])),
@@ -801,8 +801,10 @@ static int sde_rotator_stat_show(struct seq_file *s, void *data)
					ts[SDE_ROTATOR_TS_QUEUE])),
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_FLUSH],
					ts[SDE_ROTATOR_TS_COMMIT])),
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_DONE],
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_START],
					ts[SDE_ROTATOR_TS_FLUSH])),
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_DONE],
					ts[SDE_ROTATOR_TS_START])),
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_RETIRE],
					ts[SDE_ROTATOR_TS_DONE])),
			ktime_to_us(ktime_sub(ts[SDE_ROTATOR_TS_SRCDQB],
+12 −1
Original line number Diff line number Diff line
@@ -1467,7 +1467,9 @@ int sde_rotator_inline_commit(void *handle, struct sde_rotator_inline_cmd *cmd,
		int scid = llcc_get_slice_id(ctx->slice);

		/* allocate slot for timestamp */
		ts = stats->ts[stats->count++ % SDE_ROTATOR_NUM_EVENTS];
		ts = stats->ts[stats->count % SDE_ROTATOR_NUM_EVENTS];
		if (cmd_type == SDE_ROTATOR_INLINE_CMD_COMMIT)
			stats->count++;

		if (cmd->rot90)
			flags |= SDE_ROTATION_90;
@@ -1644,6 +1646,15 @@ int sde_rotator_inline_commit(void *handle, struct sde_rotator_inline_cmd *cmd,
		/* save request in private handle */
		cmd->priv_handle = request;

	} else if (cmd_type == SDE_ROTATOR_INLINE_CMD_START) {
		if (!cmd->priv_handle) {
			ret = -EINVAL;
			SDEROT_ERR("invalid private handle\n");
			goto error_invalid_handle;
		}

		request = cmd->priv_handle;
		sde_rotator_req_set_start(request->req);
	} else if (cmd_type == SDE_ROTATOR_INLINE_CMD_CLEANUP) {
		if (!cmd->priv_handle) {
			ret = -EINVAL;
+2 −0
Original line number Diff line number Diff line
@@ -25,11 +25,13 @@
 * enum sde_rotator_inline_cmd_type - inline rotator command stages
 * @SDE_ROTATOR_INLINE_CMD_VALIDATE: validate command only
 * @SDE_ROTATOR_INLINE_CMD_COMMIT: commit command to hardware
 * @SDE_ROTATOR_INLINE_CMD_START: ready to start inline rotation
 * @SDE_ROTATOR_INLINE_CMD_CLEANUP: cleanup after commit is done
 */
enum sde_rotator_inline_cmd_type {
	SDE_ROTATOR_INLINE_CMD_VALIDATE,
	SDE_ROTATOR_INLINE_CMD_COMMIT,
	SDE_ROTATOR_INLINE_CMD_START,
	SDE_ROTATOR_INLINE_CMD_CLEANUP,
};