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

Commit 7cc68d4e authored by Carl Vanderlip's avatar Carl Vanderlip Committed by Ping Li
Browse files

msm: mdss: Add commit handler to writeback display



Add support for a "vsync handler" for writeback displays to be able to
schedule tasks to be run as soon as the frame has completed.

Change-Id: I8c6945a6e914e307de67b2ec6df25f4509a50da7
Signed-off-by: default avatarCarl Vanderlip <carlv@codeaurora.org>
Signed-off-by: default avatarPing Li <quicpingli@codeaurora.org>
parent f3552ca0
Loading
Loading
Loading
Loading
+78 −4
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ struct mdss_mdp_writeback_ctx {

	void (*callback_fnc) (void *arg);
	void *callback_arg;
	spinlock_t wb_lock;
	struct list_head vsync_handlers;
};

static struct mdss_mdp_writeback_ctx wb_ctx_list[MDSS_MDP_MAX_WRITEBACK] = {
@@ -300,14 +302,73 @@ static int mdss_mdp_writeback_prepare_rot(struct mdss_mdp_ctl *ctl, void *arg)
	return mdss_mdp_writeback_format_setup(ctx, format);
}

static int mdss_mdp_wb_add_vsync_handler(struct mdss_mdp_ctl *ctl,
		struct mdss_mdp_vsync_handler *handle)
{
	struct mdss_mdp_writeback_ctx *ctx;
	unsigned long flags;
	int ret = 0;

	if (!handle || !(handle->vsync_handler)) {
		ret = -EINVAL;
		goto exit;
	}

	ctx = (struct mdss_mdp_writeback_ctx *) ctl->priv_data;
	if (!ctx) {
		pr_err("invalid ctx for ctl=%d\n", ctl->num);
		ret = -ENODEV;
		goto exit;
	}

	spin_lock_irqsave(&ctx->wb_lock, flags);
	if (!handle->enabled) {
		handle->enabled = true;
		list_add(&handle->list, &ctx->vsync_handlers);
	}
	spin_unlock_irqrestore(&ctx->wb_lock, flags);
exit:
	return ret;
}

static int mdss_mdp_wb_remove_vsync_handler(struct mdss_mdp_ctl *ctl,
		struct mdss_mdp_vsync_handler *handle)
{
	struct mdss_mdp_writeback_ctx *ctx;
	unsigned long flags;
	int ret = 0;
	if (!handle || !(handle->vsync_handler)) {
		ret = -EINVAL;
		goto exit;
	}
	ctx = (struct mdss_mdp_writeback_ctx *) ctl->priv_data;
	if (!ctx) {
		pr_err("invalid ctx for ctl=%d\n", ctl->num);
		ret = -ENODEV;
		goto exit;
	}
	spin_lock_irqsave(&ctx->wb_lock, flags);
	if (handle->enabled) {
		handle->enabled = false;
		list_del_init(&handle->list);
	}
	spin_unlock_irqrestore(&ctx->wb_lock, flags);
exit:
	return ret;
}

static int mdss_mdp_writeback_stop(struct mdss_mdp_ctl *ctl)
{
	struct mdss_mdp_writeback_ctx *ctx;
	struct mdss_mdp_vsync_handler *t, *handle;

	pr_debug("stop ctl=%d\n", ctl->num);

	ctx = (struct mdss_mdp_writeback_ctx *) ctl->priv_data;
	if (ctx) {
		list_for_each_entry_safe(handle, t, &ctx->vsync_handlers, list)
			mdss_mdp_wb_remove_vsync_handler(ctl, handle);

		mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num,
				NULL, NULL);

@@ -320,13 +381,16 @@ static int mdss_mdp_writeback_stop(struct mdss_mdp_ctl *ctl)

static void mdss_mdp_writeback_intr_done(void *arg)
{
	struct mdss_mdp_writeback_ctx *ctx;
	struct mdss_mdp_ctl *ctl = arg;
	struct mdss_mdp_writeback_ctx *ctx = ctl->priv_data;
	struct mdss_mdp_vsync_handler *tmp;
	ktime_t vsync_time;

	ctx = (struct mdss_mdp_writeback_ctx *) arg;
	if (!ctx) {
		pr_err("invalid ctx\n");
		return;
	}
	vsync_time = ktime_get();

	pr_debug("intr wb_num=%d\n", ctx->wb_num);

@@ -335,6 +399,12 @@ static void mdss_mdp_writeback_intr_done(void *arg)
	if (ctx->callback_fnc)
		ctx->callback_fnc(ctx->callback_arg);

	spin_lock(&ctx->wb_lock);
	list_for_each_entry(tmp, &ctx->vsync_handlers, list) {
		tmp->vsync_handler(ctl, vsync_time);
	}
	spin_unlock(&ctx->wb_lock);

	complete_all(&ctx->wb_comp);
}

@@ -400,7 +470,7 @@ static int mdss_mdp_writeback_display(struct mdss_mdp_ctl *ctl, void *arg)
	}

	mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num,
		   mdss_mdp_writeback_intr_done, ctx);
		   mdss_mdp_writeback_intr_done, ctl);

	ctx->callback_fnc = wb_args->callback_fnc;
	ctx->callback_arg = wb_args->priv_data;
@@ -446,6 +516,8 @@ int mdss_mdp_writeback_start(struct mdss_mdp_ctl *ctl)
	ctx->base = ctl->wb_base;
	ctx->initialized = false;
	init_completion(&ctx->wb_comp);
	spin_lock_init(&ctx->wb_lock);
	INIT_LIST_HEAD(&ctx->vsync_handlers);

	if (ctx->type == MDSS_MDP_WRITEBACK_TYPE_ROTATOR)
		ctl->prepare_fnc = mdss_mdp_writeback_prepare_rot;
@@ -454,6 +526,8 @@ int mdss_mdp_writeback_start(struct mdss_mdp_ctl *ctl)
	ctl->stop_fnc = mdss_mdp_writeback_stop;
	ctl->display_fnc = mdss_mdp_writeback_display;
	ctl->wait_fnc = mdss_mdp_wb_wait4comp;
	ctl->add_vsync_handler = mdss_mdp_wb_add_vsync_handler;
	ctl->remove_vsync_handler = mdss_mdp_wb_remove_vsync_handler;

	return ret;
}