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

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

Merge "msm: mdp3: implement asynchronous frame events"

parents f0f3dd3b 02e76a99
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include "mdss_fb.h"

#define MDP_VSYNC_CLK_RATE	19200000
#define KOFF_TIMEOUT msecs_to_jiffies(84)

enum  {
	MDP3_CLK_AHB,
+89 −8
Original line number Diff line number Diff line
@@ -91,6 +91,36 @@ static int mdp3_bufq_count(struct mdp3_buffer_queue *bufq)
	return bufq->count;
}

void mdp3_ctrl_notifier_register(struct mdp3_session_data *ses,
	struct notifier_block *notifier)
{
	blocking_notifier_chain_register(&ses->notifier_head, notifier);
}

void mdp3_ctrl_notifier_unregister(struct mdp3_session_data *ses,
	struct notifier_block *notifier)
{
	blocking_notifier_chain_unregister(&ses->notifier_head, notifier);
}

int mdp3_ctrl_notify(struct mdp3_session_data *ses, int event)
{
	return blocking_notifier_call_chain(&ses->notifier_head, event, ses);
}

static void mdp3_dispatch_dma_done(struct work_struct *work)
{
	struct mdp3_session_data *session;

	pr_debug("%s\n", __func__);
	session = container_of(work, struct mdp3_session_data,
				dma_done_work);
	if (!session)
		return;

	mdp3_ctrl_notify(session, MDP_NOTIFY_FRAME_DONE);
}

static void mdp3_dispatch_clk_off(struct work_struct *work)
{
	struct mdp3_session_data *session;
@@ -121,6 +151,12 @@ void vsync_notify_handler(void *arg)
	sysfs_notify_dirent(session->vsync_event_sd);
}

void dma_done_notify_handler(void *arg)
{
	struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
	schedule_work(&session->dma_done_work);
}

void vsync_count_down(void *arg)
{
	struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
@@ -140,8 +176,8 @@ void mdp3_ctrl_reset_countdown(struct mdp3_session_data *session,
static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
{
	struct mdp3_session_data *mdp3_session;
	struct mdp3_vsync_notification vsync_client;
	struct mdp3_vsync_notification *arg = NULL;
	struct mdp3_notification vsync_client;
	struct mdp3_notification *arg = NULL;

	pr_debug("mdp3_ctrl_vsync_enable =%d\n", enable);
	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
@@ -464,6 +500,7 @@ static int mdp3_ctrl_dma_init(struct msm_fb_data_type *mfd,
	int frame_rate = mfd->panel_info->mipi.frame_rate;
	int vbp, vfp, vspw;
	int vtotal, vporch;
	struct mdp3_notification dma_done_callback;

	vbp = panel_info->lcdc.v_back_porch;
	vfp = panel_info->lcdc.v_front_porch;
@@ -499,6 +536,13 @@ static int mdp3_ctrl_dma_init(struct msm_fb_data_type *mfd,
		rc = dma->dma_config(dma, &sourceConfig, &outputConfig);
	else
		rc = -EINVAL;

	if (outputConfig.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
		dma_done_callback.handler = dma_done_notify_handler;
		dma_done_callback.arg = mfd->mdp.private1;
		dma->dma_done_notifier(dma, &dma_done_callback);
	}

	return rc;
}

@@ -527,6 +571,8 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd)
	}

	mdp3_batfet_ctrl(true);
	mdp3_ctrl_notifier_register(mdp3_session,
		&mdp3_session->mfd->mdp_sync_pt_data.notifier);

	rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
	if (rc) {
@@ -658,6 +704,8 @@ static int mdp3_ctrl_off(struct msm_fb_data_type *mfd)
	if (rc)
		pr_err("fail to dettach MDP DMA SMMU\n");

	mdp3_ctrl_notifier_unregister(mdp3_session,
		&mdp3_session->mfd->mdp_sync_pt_data.notifier);
	mdp3_batfet_ctrl(false);
	mdp3_session->vsync_enabled = 0;
	atomic_set(&mdp3_session->vsync_countdown, 0);
@@ -677,7 +725,7 @@ static int mdp3_ctrl_reset_cmd(struct msm_fb_data_type *mfd)
	struct mdp3_session_data *mdp3_session;
	struct mdp3_dma *mdp3_dma;
	struct mdss_panel_data *panel;
	struct mdp3_vsync_notification vsync_client;
	struct mdp3_notification vsync_client;

	pr_debug("mdp3_ctrl_reset_cmd\n");
	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
@@ -728,7 +776,7 @@ static int mdp3_ctrl_reset(struct msm_fb_data_type *mfd)
	struct mdp3_session_data *mdp3_session;
	struct mdp3_dma *mdp3_dma;
	struct mdss_panel_data *panel;
	struct mdp3_vsync_notification vsync_client;
	struct mdp3_notification vsync_client;

	pr_debug("mdp3_ctrl_reset\n");
	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
@@ -971,13 +1019,27 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd,
		return -EPERM;
	}

	mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_BEGIN);
	data = mdp3_bufq_pop(&mdp3_session->bufq_in);
	if (data) {
		mdp3_ctrl_reset_countdown(mdp3_session, mfd);
		mdp3_ctrl_clk_enable(mfd, 1);
		mdp3_session->dma->update(mdp3_session->dma,
		rc = mdp3_session->dma->update(mdp3_session->dma,
			(void *)(int)data->addr,
			mdp3_session->intf);
		/* This is for the previous frame */
		if (rc < 0) {
			mdp3_ctrl_notify(mdp3_session,
				MDP_NOTIFY_FRAME_TIMEOUT);
		} else {
			if (mdp3_ctrl_get_intf_type(mfd) ==
						MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) {
				mdp3_ctrl_notify(mdp3_session,
					MDP_NOTIFY_FRAME_DONE);
			}
		}

		mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_FLUSHED);
		mdp3_bufq_push(&mdp3_session->bufq_out, data);
	}

@@ -1001,7 +1063,7 @@ static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd,

	mdss_fb_update_notify_update(mfd);

	return rc;
	return 0;
}

static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
@@ -1011,6 +1073,7 @@ static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
	u32 offset;
	int bpp;
	struct mdss_panel_info *panel_info;
	int rc;

	pr_debug("mdp3_ctrl_pan_display\n");
	if (!mfd || !mfd->mdp.private1)
@@ -1049,10 +1112,23 @@ static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)

	if (mfd->fbi->screen_base) {
		mdp3_ctrl_reset_countdown(mdp3_session, mfd);
		mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_BEGIN);
		mdp3_ctrl_clk_enable(mfd, 1);
		mdp3_session->dma->update(mdp3_session->dma,
		rc = mdp3_session->dma->update(mdp3_session->dma,
				(void *)(int)(mfd->iova + offset),
				mdp3_session->intf);
		/* This is for the previous frame */
		if (rc < 0) {
			mdp3_ctrl_notify(mdp3_session,
				MDP_NOTIFY_FRAME_TIMEOUT);
		} else {
			if (mdp3_ctrl_get_intf_type(mfd) ==
						MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) {
				mdp3_ctrl_notify(mdp3_session,
					MDP_NOTIFY_FRAME_DONE);
			}
		}
		mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_FLUSHED);
	} else {
		pr_debug("mdp3_ctrl_pan_display no memory, stop interface");
		mdp3_clk_enable(1, 0);
@@ -1683,6 +1759,7 @@ int mdp3_ctrl_init(struct msm_fb_data_type *mfd)
	memset(mdp3_session, 0, sizeof(struct mdp3_session_data));
	mutex_init(&mdp3_session->lock);
	INIT_WORK(&mdp3_session->clk_off_work, mdp3_dispatch_clk_off);
	INIT_WORK(&mdp3_session->dma_done_work, mdp3_dispatch_dma_done);
	atomic_set(&mdp3_session->vsync_countdown, 0);
	mutex_init(&mdp3_session->histo_lock);
	mdp3_session->dma = mdp3_get_dma_pipe(MDP3_DMA_CAP_ALL);
@@ -1718,6 +1795,7 @@ int mdp3_ctrl_init(struct msm_fb_data_type *mfd)
	mdp3_bufq_init(&mdp3_session->bufq_out);
	mdp3_session->histo_status = 0;
	mdp3_session->lut_sel = 0;
	BLOCKING_INIT_NOTIFIER_HEAD(&mdp3_session->notifier_head);

	init_timer(&mdp3_session->vsync_timer);
	mdp3_session->vsync_timer.function = mdp3_vsync_timer_func;
@@ -1746,8 +1824,11 @@ int mdp3_ctrl_init(struct msm_fb_data_type *mfd)
	kobject_uevent(&dev->kobj, KOBJ_ADD);
	pr_debug("vsync kobject_uevent(KOBJ_ADD)\n");

	if (mdp3_get_cont_spash_en())
	if (mdp3_get_cont_spash_en()) {
		mdp3_session->clk_on = 1;
		mdp3_ctrl_notifier_register(mdp3_session,
			&mdp3_session->mfd->mdp_sync_pt_data.notifier);
	}

	if (splash_mismatch) {
		pr_err("splash memory mismatch, stop splash\n");
+2 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ struct mdp3_session_data {
	struct mdp3_buffer_queue bufq_in;
	struct mdp3_buffer_queue bufq_out;
	struct work_struct clk_off_work;
	struct work_struct dma_done_work;
	int histo_status;
	struct mutex histo_lock;
	int lut_sel;
@@ -56,6 +57,7 @@ struct mdp3_session_data {
	bool vsync_before_commit;
	bool first_commit;
	int clk_on;
	struct blocking_notifier_head notifier_head;

	int vsync_enabled;
	atomic_t vsync_countdown; /* Used to count down  */
+40 −7
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@
static void mdp3_vsync_intr_handler(int type, void *arg)
{
	struct mdp3_dma *dma = (struct mdp3_dma *)arg;
	struct mdp3_vsync_notification vsync_client;
	struct mdp3_notification vsync_client;
	unsigned int wait_for_next_vs;

	pr_debug("mdp3_vsync_intr_handler\n");
@@ -49,10 +49,16 @@ static void mdp3_vsync_intr_handler(int type, void *arg)
static void mdp3_dma_done_intr_handler(int type, void *arg)
{
	struct mdp3_dma *dma = (struct mdp3_dma *)arg;
	struct mdp3_notification dma_client;

	pr_debug("mdp3_dma_done_intr_handler\n");
	spin_lock(&dma->dma_lock);
	dma_client = dma->dma_notifier_client;
	complete(&dma->dma_comp);
	spin_unlock(&dma->dma_lock);
	mdp3_irq_disable_nosync(type);
	if (dma_client.handler)
		dma_client.handler(dma_client.arg);
}

static void mdp3_hist_done_intr_handler(int type, void *arg)
@@ -195,7 +201,7 @@ static int mdp3_dma_callback_setup(struct mdp3_dma *dma)
}

static void mdp3_dma_vsync_enable(struct mdp3_dma *dma,
				struct mdp3_vsync_notification *vsync_client)
				struct mdp3_notification *vsync_client)
{
	unsigned long flag;
	int updated = 0;
@@ -226,6 +232,21 @@ static void mdp3_dma_vsync_enable(struct mdp3_dma *dma,
	}
}

static void mdp3_dma_done_notifier(struct mdp3_dma *dma,
				struct mdp3_notification *dma_client)
{
	unsigned long flag;

	spin_lock_irqsave(&dma->dma_lock, flag);
	if (dma_client) {
		dma->dma_notifier_client = *dma_client;
	} else {
		dma->dma_notifier_client.handler = NULL;
		dma->dma_notifier_client.arg = NULL;
	}
	spin_unlock_irqrestore(&dma->dma_lock, flag);
}

static void mdp3_dma_clk_auto_gating(struct mdp3_dma *dma, int enable)
{
	u32 cgc;
@@ -552,13 +573,20 @@ static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf,
{
	unsigned long flag;
	int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
	int rc = 0;

	pr_debug("mdp3_dmap_update\n");

	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
		cb_type = MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
		if (intf->active)
			wait_for_completion_killable(&dma->dma_comp);
		if (intf->active) {
			rc = wait_for_completion_timeout(&dma->dma_comp,
				KOFF_TIMEOUT);
			if (rc <= 0) {
				WARN(1, "cmd kickoff timed out (%d)\n", rc);
				rc = -1;
			}
		}
	}
	spin_lock_irqsave(&dma->dma_lock, flag);
	MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)buf);
@@ -581,10 +609,14 @@ static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf,

	mdp3_dma_callback_enable(dma, cb_type);
	pr_debug("mdp3_dmap_update wait for vsync_comp in\n");
	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO)
		wait_for_completion_killable(&dma->vsync_comp);
	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) {
		rc = wait_for_completion_timeout(&dma->vsync_comp,
			KOFF_TIMEOUT);
		if (rc <= 0)
			rc = -1;
	}
	pr_debug("mdp3_dmap_update wait for vsync_comp out\n");
	return 0;
	return rc;
}

static int mdp3_dmas_update(struct mdp3_dma *dma, void *buf,
@@ -878,6 +910,7 @@ int mdp3_dma_init(struct mdp3_dma *dma)
		dma->get_histo = mdp3_dmap_histo_get;
		dma->histo_op = mdp3_dmap_histo_op;
		dma->vsync_enable = mdp3_dma_vsync_enable;
		dma->dma_done_notifier = mdp3_dma_done_notifier;
		dma->start = mdp3_dma_start;
		dma->stop = mdp3_dma_stop;
		dma->config_stride = mdp3_dma_stride_config;
+8 −3
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#ifndef MDP3_DMA_H
#define MDP3_DMA_H

#include <linux/notifier.h>
#include <linux/sched.h>

#define MDP_HISTOGRAM_BL_SCALE_MAX 1024
@@ -227,7 +228,7 @@ struct mdp3_dma_histogram_data {
	u32 extra[2];
};

struct mdp3_vsync_notification {
struct mdp3_notification {
	void (*handler)(void *arg);
	void *arg;
};
@@ -245,7 +246,8 @@ struct mdp3_dma {
	struct completion vsync_comp;
	struct completion dma_comp;
	struct completion histo_comp;
	struct mdp3_vsync_notification vsync_client;
	struct mdp3_notification vsync_client;
	struct mdp3_notification dma_notifier_client;

	struct mdp3_dma_output_config output_config;
	struct mdp3_dma_source source_config;
@@ -291,7 +293,10 @@ struct mdp3_dma {
	void (*config_stride)(struct mdp3_dma *dma, int stride);

	void (*vsync_enable)(struct mdp3_dma *dma,
			struct mdp3_vsync_notification *vsync_client);
			struct mdp3_notification *vsync_client);

	void (*dma_done_notifier)(struct mdp3_dma *dma,
			struct mdp3_notification *dma_client);
};

struct mdp3_video_intf_cfg {