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

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

Merge "msm: mdss: add lineptr interrupt support for command mode panels"

parents 6de6d2c9 7a015c49
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1325,6 +1325,7 @@ static void mdss_panel_parse_te_params(struct device_node *np,
	rc = of_property_read_u32
		(np, "qcom,mdss-tear-check-rd-ptr-trigger-intr", &tmp);
	te->rd_ptr_irq = (!rc ? tmp : timing->yres + 1);
	te->wr_ptr_irq = 0;
}


+50 −0
Original line number Diff line number Diff line
@@ -190,6 +190,12 @@ struct mdss_mdp_vsync_handler {
	struct list_head list;
};

struct mdss_mdp_lineptr_handler {
	bool enabled;
	mdp_vsync_handler_t lineptr_handler;
	struct list_head list;
};

enum mdss_mdp_wb_ctl_type {
	MDSS_MDP_WB_CTL_TYPE_BLOCK = 1,
	MDSS_MDP_WB_CTL_TYPE_LINE
@@ -342,6 +348,8 @@ struct mdss_mdp_ctl {
	struct work_struct recover_work;
	struct work_struct remove_underrun_handler;

	struct mdss_mdp_lineptr_handler lineptr_handler;

	/*
	 * This ROI is aligned to as per following guidelines and
	 * sent to the panel driver.
@@ -659,7 +667,9 @@ struct mdss_mdp_wfd;

struct mdss_overlay_private {
	ktime_t vsync_time;
	ktime_t lineptr_time;
	struct kernfs_node *vsync_event_sd;
	struct kernfs_node *lineptr_event_sd;
	struct kernfs_node *hist_event_sd;
	struct kernfs_node *bl_event_sd;
	struct kernfs_node *ad_event_sd;
@@ -1186,6 +1196,46 @@ static inline int mdss_mdp_get_display_id(struct mdss_mdp_pipe *pipe)
	return (pipe && pipe->mfd) ? pipe->mfd->index : -1;
}

static inline bool mdss_mdp_is_full_frame_update(struct mdss_mdp_ctl *ctl)
{
	struct mdss_mdp_mixer *mixer;
	struct mdss_rect *roi;

	if (mdss_mdp_get_pu_type(ctl) != MDSS_MDP_DEFAULT_UPDATE)
		return false;

	if (ctl->mixer_left->valid_roi) {
		mixer = ctl->mixer_left;
		roi = &mixer->roi;
		if ((roi->x != 0) || (roi->y != 0) || (roi->w != mixer->width)
			|| (roi->h != mixer->height))
			return false;
	}

	if (ctl->mixer_right && ctl->mixer_right->valid_roi) {
		mixer = ctl->mixer_right;
		roi = &mixer->roi;
		if ((roi->x != 0) || (roi->y != 0) || (roi->w != mixer->width)
			|| (roi->h != mixer->height))
			return false;
	}

	return true;
}

static inline bool mdss_mdp_is_lineptr_supported(struct mdss_mdp_ctl *ctl)
{
	struct mdss_panel_info *pinfo;

	if (!ctl || !ctl->mixer_left || !ctl->is_master)
		return false;

	pinfo = &ctl->panel_data->panel_info;

	return (((pinfo->type == MIPI_CMD_PANEL)
			&& (pinfo->te.tear_check_en)) ? true : false);
}

irqreturn_t mdss_mdp_isr(int irq, void *ptr);
void mdss_mdp_irq_clear(struct mdss_data_type *mdata,
		u32 intr_type, u32 intf_num);
+233 −3
Original line number Diff line number Diff line
@@ -64,10 +64,12 @@ struct mdss_mdp_cmd_ctx {
	struct completion pp_done;
	wait_queue_head_t pp_waitq;
	struct list_head vsync_handlers;
	struct list_head lineptr_handlers;
	int panel_power_state;
	atomic_t koff_cnt;
	u32 intf_stopped;
	struct mutex mdp_rdptr_lock;
	struct mutex mdp_wrptr_lock;
	struct mutex clk_mtx;
	spinlock_t clk_lock;
	spinlock_t koff_lock;
@@ -90,6 +92,9 @@ struct mdss_mdp_cmd_ctx {
	struct completion autorefresh_done;

	int vsync_irq_cnt;
	int lineptr_irq_cnt;
	bool lineptr_enabled;
	u32 prev_wr_ptr_irq;

	struct mdss_intf_recovery intf_recovery;
	struct mdss_intf_recovery intf_mdp_callback;
@@ -286,9 +291,10 @@ static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_mixer *mixer,

	cfg |= vclks_line;

	pr_debug("%s: yres=%d vclks=%x height=%d init=%d rd=%d start=%d\n",
	pr_debug("%s: yres=%d vclks=%x height=%d init=%d rd=%d start=%d wr=%d\n",
		__func__, pinfo->yres, vclks_line, te->sync_cfg_height,
		te->vsync_init_val, te->rd_ptr_irq, te->start_pos);
		te->vsync_init_val, te->rd_ptr_irq, te->start_pos,
		te->wr_ptr_irq);
	pr_debug("thrd_start =%d thrd_cont=%d pp_split=%d\n",
		te->sync_threshold_start, te->sync_threshold_continue,
		ctx->pingpong_split_slave);
@@ -309,6 +315,9 @@ static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_mixer *mixer,
	mdss_mdp_pingpong_write(pingpong_base,
		MDSS_MDP_REG_PP_RD_PTR_IRQ,
		te ? te->rd_ptr_irq : 0);
	mdss_mdp_pingpong_write(pingpong_base,
		MDSS_MDP_REG_PP_WR_PTR_IRQ,
		te ? te->wr_ptr_irq : 0);
	mdss_mdp_pingpong_write(pingpong_base,
		MDSS_MDP_REG_PP_START_POS,
		te ? te->start_pos : 0);
@@ -1060,6 +1069,28 @@ static void mdss_mdp_cmd_intf_callback(void *data, int event)
	}
}

static void mdss_mdp_cmd_writeptr_done(void *arg)
{
	struct mdss_mdp_ctl *ctl = arg;
	struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
	struct mdss_mdp_lineptr_handler *tmp;
	ktime_t lineptr_time;

	if (!ctx) {
		pr_err("invalid ctx\n");
		return;
	}

	lineptr_time = ktime_get();

	spin_lock(&ctx->clk_lock);
	list_for_each_entry(tmp, &ctx->lineptr_handlers, list) {
		if (tmp->enabled)
			tmp->lineptr_handler(ctl, lineptr_time);
	}
	spin_unlock(&ctx->clk_lock);
}

static void mdss_mdp_cmd_intf_recovery(void *data, int event)
{
	struct mdss_mdp_cmd_ctx *ctx = data;
@@ -1172,6 +1203,178 @@ static void mdss_mdp_cmd_pingpong_done(void *arg)
	spin_unlock(&ctx->koff_lock);
}

static int mdss_mdp_setup_lineptr(struct mdss_mdp_cmd_ctx *ctx,
	bool enable)
{
	int changed = 0;

	mutex_lock(&ctx->mdp_wrptr_lock);

	if (enable) {
		if (ctx->lineptr_irq_cnt == 0)
			changed++;
		ctx->lineptr_irq_cnt++;
	} else {
		if (ctx->lineptr_irq_cnt) {
			ctx->lineptr_irq_cnt--;
			if (ctx->lineptr_irq_cnt == 0)
				changed++;
		} else {
			pr_warn("%pS->%s: wr_ptr can not be turned off\n",
				__builtin_return_address(0), __func__);
		}
	}

	if (changed)
		MDSS_XLOG(ctx->lineptr_irq_cnt, enable, current->pid);

	pr_debug("%pS->%s: lineptr_irq_cnt=%d changed=%d enable=%d ctl:%d pp:%d\n",
			__builtin_return_address(0), __func__,
			ctx->lineptr_irq_cnt, changed, enable,
			ctx->ctl->num, ctx->default_pp_num);

	if (changed) {
		if (enable) {
			/* enable clocks and irq */
			mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
			mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_WR_PTR,
				ctx->default_pp_num);
		} else {
			/* disable clocks and irq */
			mdss_mdp_irq_disable(MDSS_MDP_IRQ_PING_PONG_WR_PTR,
				ctx->default_pp_num);
			/*
			 * check the intr status and clear the irq before
			 * disabling the clocks
			 */
			mdss_mdp_intr_check_and_clear(
				MDSS_MDP_IRQ_PING_PONG_WR_PTR,
				ctx->default_pp_num);

			mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
		}
	}

	mutex_unlock(&ctx->mdp_wrptr_lock);
	return ctx->lineptr_irq_cnt;
}

static int mdss_mdp_cmd_add_lineptr_handler(struct mdss_mdp_ctl *ctl,
		struct mdss_mdp_lineptr_handler *handle)
{
	struct mdss_mdp_cmd_ctx *ctx;
	unsigned long flags;
	int ret = 0;

	mutex_lock(&ctl->offlock);
	ctx = (struct mdss_mdp_cmd_ctx *) ctl->intf_ctx[MASTER_CTX];
	if (!ctx || !ctl->is_master) {
		ret = -EINVAL;
		goto done;
	}

	pr_debug("%pS->%s: ctl=%d\n",
		__builtin_return_address(0), __func__, ctl->num);

	MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt));

	spin_lock_irqsave(&ctx->clk_lock, flags);
	if (!handle->enabled) {
		handle->enabled = true;
		list_add(&handle->list, &ctx->lineptr_handlers);
	}
	spin_unlock_irqrestore(&ctx->clk_lock, flags);

	if (ctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY)
		mutex_lock(&cmd_clk_mtx);

	mdss_mdp_setup_lineptr(ctx, true);
	ctx->lineptr_enabled = true;

	if (ctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY)
		mutex_unlock(&cmd_clk_mtx);
done:
	mutex_unlock(&ctl->offlock);

	return ret;
}

static int mdss_mdp_cmd_remove_lineptr_handler(struct mdss_mdp_ctl *ctl,
		struct mdss_mdp_lineptr_handler *handle)
{
	struct mdss_mdp_cmd_ctx *ctx;
	unsigned long flags;
	bool disabled = true;

	ctx = (struct mdss_mdp_cmd_ctx *) ctl->intf_ctx[MASTER_CTX];
	if (!ctx || !ctl->is_master || !ctx->lineptr_enabled)
		return -EINVAL;

	pr_debug("%pS->%s: ctl=%d\n",
		__builtin_return_address(0), __func__, ctl->num);

	MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt));

	spin_lock_irqsave(&ctx->clk_lock, flags);
	if (handle->enabled) {
		handle->enabled = false;
		list_del_init(&handle->list);
	} else {
		disabled = false;
	}
	spin_unlock_irqrestore(&ctx->clk_lock, flags);

	if (disabled)
		mdss_mdp_setup_lineptr(ctx, false);
	ctx->lineptr_enabled = false;
	ctx->prev_wr_ptr_irq = 0;

	return 0;
}

static int mdss_mdp_cmd_lineptr_ctrl(struct mdss_mdp_ctl *ctl, bool enable)
{
	struct mdss_mdp_pp_tear_check *te;
	struct mdss_mdp_cmd_ctx *ctx;
	int rc = 0;

	ctx = (struct mdss_mdp_cmd_ctx *) ctl->intf_ctx[MASTER_CTX];
	if (!ctx || !ctl->is_master)
		return -EINVAL;

	te = &ctl->panel_data->panel_info.te;
	pr_debug("%pS->%s: ctl=%d en=%d, prev_lineptr=%d, lineptr=%d\n",
			__builtin_return_address(0), __func__, ctl->num,
			enable, ctx->prev_wr_ptr_irq, te->wr_ptr_irq);

	if (enable) {
		/* update reg only if the value has changed */
		if (ctx->prev_wr_ptr_irq != te->wr_ptr_irq) {
			ctx->prev_wr_ptr_irq = te->wr_ptr_irq;
			mdss_mdp_pingpong_write(ctl->mixer_left->pingpong_base,
				MDSS_MDP_REG_PP_WR_PTR_IRQ, te->wr_ptr_irq);
		}

		/*
		 * add handler only when lineptr is not enabled
		 * and wr ptr is non zero
		 */
		if (!ctx->lineptr_enabled && te->wr_ptr_irq)
			rc = mdss_mdp_cmd_add_lineptr_handler(ctl,
				&ctl->lineptr_handler);
		/* Disable handler when the value is zero */
		else if (ctx->lineptr_enabled && !te->wr_ptr_irq)
			rc = mdss_mdp_cmd_remove_lineptr_handler(ctl,
				&ctl->lineptr_handler);
	} else {
		if (ctx->lineptr_enabled)
			rc = mdss_mdp_cmd_remove_lineptr_handler(ctl,
				&ctl->lineptr_handler);
	}

	return rc;
}

/**
 * mdss_mdp_cmd_autorefresh_pp_done() - pp done irq callback for autorefresh
 * @arg: void pointer to the controller context.
@@ -1207,14 +1410,20 @@ static void pingpong_done_work(struct work_struct *work)
	u32 status;
	struct mdss_mdp_cmd_ctx *ctx =
		container_of(work, typeof(*ctx), pp_done_work);
	struct mdss_mdp_ctl *ctl = ctx->ctl;

	if (ctx->ctl) {
	if (ctl) {
		while (atomic_add_unless(&ctx->pp_done_cnt, -1, 0))
			mdss_mdp_ctl_notify(ctx->ctl, MDP_NOTIFY_FRAME_DONE);

		status = mdss_mdp_ctl_perf_get_transaction_status(ctx->ctl);
		if (status == 0)
			mdss_mdp_ctl_perf_release_bw(ctx->ctl);

		if (!ctl->is_master)
			ctl = mdss_mdp_get_main_ctl(ctl);
		if (mdss_mdp_is_lineptr_supported(ctl))
			mdss_mdp_cmd_lineptr_ctrl(ctl, false);
	}
}

@@ -2468,6 +2677,13 @@ static int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
			PERF_SW_COMMIT_STATE, PERF_STATUS_DONE);
	}

	if (mdss_mdp_is_lineptr_supported(ctl)) {
		if (mdss_mdp_is_full_frame_update(ctl))
			mdss_mdp_cmd_lineptr_ctrl(ctl, true);
		else if (ctx->lineptr_enabled)
			mdss_mdp_cmd_lineptr_ctrl(ctl, false);
	}

	/* Kickoff */
	__mdss_mdp_kickoff(ctl, ctx);

@@ -2556,6 +2772,11 @@ int mdss_mdp_cmd_ctx_stop(struct mdss_mdp_ctl *ctl,
		while (mdss_mdp_setup_vsync(ctx, false))
			;
	}
	if (ctx->lineptr_irq_cnt) {
		WARN(1, "lineptr irq still enabled\n");
		while (mdss_mdp_setup_lineptr(ctx, false))
			;
	}

	if (!ctl->pending_mode_switch) {
		mdss_mdp_ctl_intf_event(ctl,
@@ -2583,6 +2804,8 @@ int mdss_mdp_cmd_ctx_stop(struct mdss_mdp_ctl *ctl,

	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR,
		ctx->default_pp_num, NULL, NULL);
	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_WR_PTR,
		ctx->default_pp_num, NULL, NULL);
	mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_PING_PONG_COMP,
		ctx->default_pp_num, NULL, NULL);

@@ -2639,6 +2862,8 @@ static int mdss_mdp_cmd_stop_sub(struct mdss_mdp_ctl *ctl,

	list_for_each_entry_safe(handle, tmp, &ctx->vsync_handlers, list)
		mdss_mdp_cmd_remove_vsync_handler(ctl, handle);
	if (mdss_mdp_is_lineptr_supported(ctl))
		mdss_mdp_cmd_lineptr_ctrl(ctl, false);
	MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), XLOG_FUNC_ENTRY);

	/* Command mode is supported only starting at INTF1 */
@@ -2888,6 +3113,7 @@ static int mdss_mdp_cmd_ctx_setup(struct mdss_mdp_ctl *ctl,
	spin_lock_init(&ctx->koff_lock);
	mutex_init(&ctx->clk_mtx);
	mutex_init(&ctx->mdp_rdptr_lock);
	mutex_init(&ctx->mdp_wrptr_lock);
	INIT_WORK(&ctx->gate_clk_work, clk_ctrl_gate_work);
	INIT_DELAYED_WORK(&ctx->delayed_off_clk_work,
		clk_ctrl_delayed_off_work);
@@ -2897,6 +3123,7 @@ static int mdss_mdp_cmd_ctx_setup(struct mdss_mdp_ctl *ctl,
	ctx->autorefresh_state = MDP_AUTOREFRESH_OFF;
	ctx->autorefresh_frame_cnt = 0;
	INIT_LIST_HEAD(&ctx->vsync_handlers);
	INIT_LIST_HEAD(&ctx->lineptr_handlers);

	ctx->intf_recovery.fxn = mdss_mdp_cmd_intf_recovery;
	ctx->intf_recovery.data = ctx;
@@ -2913,6 +3140,9 @@ static int mdss_mdp_cmd_ctx_setup(struct mdss_mdp_ctl *ctl,
	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR,
		ctx->default_pp_num, mdss_mdp_cmd_readptr_done, ctl);

	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_WR_PTR,
		ctx->default_pp_num, mdss_mdp_cmd_writeptr_done, ctl);

	ret = mdss_mdp_cmd_tearcheck_setup(ctx, false);
	if (ret)
		pr_err("tearcheck setup failed\n");
+112 −0
Original line number Diff line number Diff line
@@ -2619,6 +2619,30 @@ static void mdss_mdp_overlay_handle_vsync(struct mdss_mdp_ctl *ctl,
	sysfs_notify_dirent(mdp5_data->vsync_event_sd);
}

/* function is called in irq context should have minimum processing */
static void mdss_mdp_overlay_handle_lineptr(struct mdss_mdp_ctl *ctl,
						ktime_t t)
{
	struct mdss_overlay_private *mdp5_data = NULL;

	if (!ctl || !ctl->mfd) {
		pr_warn("Invalid handle for lineptr\n");
		return;
	}

	mdp5_data = mfd_to_mdp5_data(ctl->mfd);
	if (!mdp5_data) {
		pr_err("mdp5_data is NULL\n");
		return;
	}

	pr_debug("lineptr irq on fb%d play_cnt=%d\n",
			ctl->mfd->index, ctl->play_cnt);

	mdp5_data->lineptr_time = t;
	sysfs_notify_dirent(mdp5_data->lineptr_event_sd);
}

int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en)
{
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
@@ -2891,6 +2915,78 @@ static ssize_t mdss_mdp_vsync_show_event(struct device *dev,
	return ret;
}

static ssize_t mdss_mdp_lineptr_show_event(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct fb_info *fbi = dev_get_drvdata(dev);
	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
	u64 lineptr_ticks;
	int ret;

	if (!mdp5_data->ctl ||
		(!mdp5_data->ctl->panel_data->panel_info.cont_splash_enabled
			&& !mdss_mdp_ctl_is_power_on(mdp5_data->ctl)))
		return -EAGAIN;

	lineptr_ticks = ktime_to_ns(mdp5_data->lineptr_time);

	pr_debug("fb%d lineptr=%llu\n", mfd->index, lineptr_ticks);
	ret = scnprintf(buf, PAGE_SIZE, "LINEPTR=%llu\n", lineptr_ticks);

	return ret;
}

static ssize_t mdss_mdp_lineptr_show_value(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct fb_info *fbi = dev_get_drvdata(dev);
	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
	int ret, lineptr_val;

	if (!mdp5_data->ctl ||
		(!mdp5_data->ctl->panel_data->panel_info.cont_splash_enabled
			&& !mdss_mdp_ctl_is_power_on(mdp5_data->ctl)))
		return -EAGAIN;

	lineptr_val = mfd->panel_info->te.wr_ptr_irq;

	ret = scnprintf(buf, PAGE_SIZE, "%d\n", lineptr_val);

	return ret;
}

static ssize_t mdss_mdp_lineptr_set_value(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	struct fb_info *fbi = dev_get_drvdata(dev);
	struct msm_fb_data_type *mfd = fbi->par;
	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
	int ret, lineptr_value;

	ret = kstrtoint(buf, 10, &lineptr_value);
	if (ret) {
		pr_err("Invalid input for ad\n");
		return -EINVAL;
	}

	if (!mdp5_data->ctl ||
		(!mdp5_data->ctl->panel_data->panel_info.cont_splash_enabled
			&& !mdss_mdp_ctl_is_power_on(mdp5_data->ctl)))
		return -EAGAIN;

	if (!mdss_mdp_is_lineptr_supported(mdp5_data->ctl)) {
		pr_err("lineptr not supported\n");
		return -ENOTSUPP;
	}

	/* the new lineptr value will take effect in the next kickoff */
	mfd->panel_info->te.wr_ptr_irq = lineptr_value;

	return count;
}

static ssize_t mdss_mdp_bl_show_event(struct device *dev,
		struct device_attribute *attr, char *buf)
{
@@ -3224,6 +3320,9 @@ static DEVICE_ATTR(msm_misr_en, S_IRUGO | S_IWUSR,
static DEVICE_ATTR(msm_cmd_autorefresh_en, S_IRUGO | S_IWUSR,
	mdss_mdp_cmd_autorefresh_show, mdss_mdp_cmd_autorefresh_store);
static DEVICE_ATTR(vsync_event, S_IRUGO, mdss_mdp_vsync_show_event, NULL);
static DEVICE_ATTR(lineptr_event, S_IRUGO, mdss_mdp_lineptr_show_event, NULL);
static DEVICE_ATTR(lineptr_value, S_IRUGO | S_IWUSR | S_IWGRP,
		mdss_mdp_lineptr_show_value, mdss_mdp_lineptr_set_value);
static DEVICE_ATTR(ad, S_IRUGO | S_IWUSR | S_IWGRP, mdss_mdp_ad_show,
	mdss_mdp_ad_store);
static DEVICE_ATTR(dyn_pu, S_IRUGO | S_IWUSR | S_IWGRP, mdss_mdp_dyn_pu_show,
@@ -3235,6 +3334,8 @@ static DEVICE_ATTR(ad_bl_event, S_IRUGO, mdss_mdp_ad_bl_show_event, NULL);

static struct attribute *mdp_overlay_sysfs_attrs[] = {
	&dev_attr_vsync_event.attr,
	&dev_attr_lineptr_event.attr,
	&dev_attr_lineptr_value.attr,
	&dev_attr_ad.attr,
	&dev_attr_dyn_pu.attr,
	&dev_attr_msm_misr_en.attr,
@@ -4597,6 +4698,9 @@ static struct mdss_mdp_ctl *__mdss_mdp_overlay_ctl_init(
			mdss_mdp_recover_underrun_handler;
	ctl->recover_underrun_handler.cmd_post_flush = false;

	ctl->lineptr_handler.lineptr_handler =
					mdss_mdp_overlay_handle_lineptr;

	INIT_WORK(&ctl->remove_underrun_handler,
				remove_underrun_vsync_handler);

@@ -5361,6 +5465,14 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd)
		goto init_fail;
	}

	mdp5_data->lineptr_event_sd = sysfs_get_dirent(dev->kobj.sd,
						     "lineptr_event");
	if (!mdp5_data->lineptr_event_sd) {
		pr_err("lineptr_event sysfs lookup failed\n");
		rc = -ENODEV;
		goto init_fail;
	}

	mdp5_data->hist_event_sd = sysfs_get_dirent(dev->kobj.sd,
						    "hist_event");
	if (!mdp5_data->hist_event_sd) {
+19 −0
Original line number Diff line number Diff line
@@ -49,6 +49,10 @@ enum {
	MDP_INTR_PING_PONG_1_RD_PTR,
	MDP_INTR_PING_PONG_2_RD_PTR,
	MDP_INTR_PING_PONG_3_RD_PTR,
	MDP_INTR_PING_PONG_0_WR_PTR,
	MDP_INTR_PING_PONG_1_WR_PTR,
	MDP_INTR_PING_PONG_2_WR_PTR,
	MDP_INTR_PING_PONG_3_WR_PTR,
	MDP_INTR_WB_0,
	MDP_INTR_WB_1,
	MDP_INTR_WB_2,
@@ -83,6 +87,9 @@ static int mdss_mdp_intr2index(u32 intr_type, u32 intf_num)
	case MDSS_MDP_IRQ_PING_PONG_RD_PTR:
		index = MDP_INTR_PING_PONG_0_RD_PTR + intf_num;
		break;
	case MDSS_MDP_IRQ_PING_PONG_WR_PTR:
		index = MDP_INTR_PING_PONG_0_WR_PTR + intf_num;
		break;
	case MDSS_MDP_IRQ_WB_ROT_COMP:
		index = MDP_INTR_WB_0 + intf_num;
		break;
@@ -216,6 +223,18 @@ irqreturn_t mdss_mdp_isr(int irq, void *ptr)
	if (isr & MDSS_MDP_INTR_PING_PONG_3_RD_PTR)
		mdss_mdp_intr_done(MDP_INTR_PING_PONG_3_RD_PTR);

	if (isr & MDSS_MDP_INTR_PING_PONG_0_WR_PTR)
		mdss_mdp_intr_done(MDP_INTR_PING_PONG_0_WR_PTR);

	if (isr & MDSS_MDP_INTR_PING_PONG_1_WR_PTR)
		mdss_mdp_intr_done(MDP_INTR_PING_PONG_1_WR_PTR);

	if (isr & MDSS_MDP_INTR_PING_PONG_2_WR_PTR)
		mdss_mdp_intr_done(MDP_INTR_PING_PONG_2_WR_PTR);

	if (isr & MDSS_MDP_INTR_PING_PONG_3_WR_PTR)
		mdss_mdp_intr_done(MDP_INTR_PING_PONG_3_WR_PTR);

	if (isr & MDSS_MDP_INTR_INTF_0_VSYNC) {
		mdss_mdp_intr_done(MDP_INTR_VSYNC_INTF_0);
		mdss_misr_crc_collect(mdata, DISPLAY_MISR_EDP, true);
Loading