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

Commit dbe614e9 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: dsi: fix NULL pointer access while changing resolution"

parents 5b9a0014 a9cbae28
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -384,6 +384,8 @@ Optional properties:
						go blank during transition.
					"dynamic-switch-immediate"= Switch on next frame update. Panel will
						not go blank for this transition.
					"dynamic-resolution-switch-immediate"= Switch the panel resolution. Panel will
						not go blank for this transition.
- qcom,mdss-dsi-post-mode-switch-on-command:		Multiple dcs packets used for turning on DSI panel
					after panel has switch modes.
					Refer to "qcom,mdss-dsi-on-command" section for adding commands.
@@ -453,6 +455,20 @@ Optional properites:
- qcom,adjust-timer-wakeup-ms:		An integer value to indicate the timer delay(in ms) to accommodate
					s/w delay while configuring the event timer wakeup logic.

- qcom,mdss-dsi-display-timings:	Parent node that lists the different resolutions that the panel supports.
					Each child represents timings settings for a specific resolution.

Additional properties added to the second level nodes that represent timings properties:
- qcom,mdss-dsi-timing-default:		Property that specifies the current child as the default
					timing configuration that will be used.
- qcom,mdss-dsi-timing-switch-command:	List of commands that need to be sent
					to panel when the resolution/timing switch happens dynamically.
					Refer to "qcom,mdss-dsi-on-command" section for adding commands.
- qcom,mdss-dsi-timing-switch-command-state:	String that specifies the ctrl state for sending resolution switch
					commands.
					"dsi_lp_mode" = DSI low power mode (default)
					"dsi_hs_mode" = DSI high speed mode

Note, if a given optional qcom,* binding is not present, then the driver will configure
the default values specified.

@@ -594,6 +610,31 @@ Example:
		qcom,mdss-dsi-force-clock-lane-hs;
		qcom,compression-mode = "dsc";
		qcom,adjust-timer-wakeup-ms = <1>;
		qcom,mdss-dsi-display-timings {
			wqhd {
				qcom,mdss-dsi-timing-default;
				qcom,mdss-dsi-panel-width = <720>;
				qcom,mdss-dsi-panel-height = <2560>;
				qcom,mdss-dsi-h-front-porch = <20>;
				qcom,mdss-dsi-h-back-porch = <8>;
				qcom,mdss-dsi-h-pulse-width = <8>;
				qcom,mdss-dsi-h-sync-skew = <0>;
				qcom,mdss-dsi-v-back-porch = <4>;
				qcom,mdss-dsi-v-front-porch = <728>;
				qcom,mdss-dsi-v-pulse-width = <4>;
				qcom,mdss-dsi-panel-framerate = <60>;
				qcom,mdss-dsi-panel-timings = [E6 38 26 00 68 6E 2A 3C 2C 03 04 00];
				qcom,mdss-dsi-t-clk-post = <0x02>;
				qcom,mdss-dsi-t-clk-pre = <0x2a>;
				qcom,mdss-dsi-on-command = [05 01 00 00 a0 00 02 11 00
					05 01 00 00 02 00 02 29 00];
				qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
				qcom,mdss-dsi-timing-switch-command = [
					29 00 00 00 00 00 02 B0 04
					29 00 00 00 00 00 02 F1 00];
				qcom,mdss-dsi-timing-switch-command-state = "dsi_lp_mode";
			};
		};
		qcom,panel-supply-entries {
			#address-cells = <1>;
			#size-cells = <0>;
+15 −47
Original line number Diff line number Diff line
@@ -1099,15 +1099,18 @@ int mdss_dsi_switch_mode(struct mdss_panel_data *pdata, int mode)
	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
		panel_data);

	if (pinfo->dms_mode != DYNAMIC_MODE_SWITCH_IMMEDIATE) {
	if ((pinfo->dms_mode != DYNAMIC_MODE_RESOLUTION_SWITCH_IMMEDIATE) &&
			(pinfo->dms_mode != DYNAMIC_MODE_SWITCH_IMMEDIATE)) {
		pr_debug("%s: Dynamic mode switch not enabled.\n", __func__);
		return -EPERM;
	}

	if (mode == MIPI_VIDEO_PANEL) {
		mode = DSI_VIDEO_MODE;
		mode = SWITCH_TO_VIDEO_MODE;
	} else if (mode == MIPI_CMD_PANEL) {
		mode = DSI_CMD_MODE;
		mode = SWITCH_TO_CMD_MODE;
	} else if (mode == SWITCH_RESOLUTION) {
		pr_debug("Resolution switch mode selected\n");
	} else {
		pr_err("Invalid mode selected, mode=%d\n", mode);
		return -EINVAL;
@@ -1115,6 +1118,7 @@ int mdss_dsi_switch_mode(struct mdss_panel_data *pdata, int mode)

	mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle,
			  MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON);
	mdss_dsi_ctrl_setup(ctrl_pdata);
	ctrl_pdata->switch_mode(pdata, mode);
	mdss_dsi_clk_ctrl(ctrl_pdata, ctrl_pdata->dsi_clk_handle,
			  MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_OFF);
@@ -1353,8 +1357,9 @@ static int mdss_dsi_unblank(struct mdss_panel_data *pdata)
				panel_data);
	mipi  = &pdata->panel_info.mipi;

	pr_debug("%s+: ctrl=%p ndx=%d cur_blank_state=%d\n", __func__,
		ctrl_pdata, ctrl_pdata->ndx, pdata->panel_info.blank_state);
	pr_debug("%s+: ctrl=%p ndx=%d cur_blank_state=%d ctrl_state=%x\n",
			__func__, ctrl_pdata, ctrl_pdata->ndx,
			pdata->panel_info.blank_state, ctrl_pdata->ctrl_state);

	if (mdss_dsi_is_ctrl_clk_master(ctrl_pdata))
		sctrl = mdss_dsi_get_ctrl_clk_slave();
@@ -1442,9 +1447,9 @@ static int mdss_dsi_blank(struct mdss_panel_data *pdata, int power_state)
		pr_info("%s: switching to %s mode\n", __func__,
			(pdata->panel_info.mipi.mode ? "video" : "command"));
		if (pdata->panel_info.type == MIPI_CMD_PANEL) {
			ctrl_pdata->switch_mode(pdata, DSI_VIDEO_MODE);
			ctrl_pdata->switch_mode(pdata, SWITCH_TO_VIDEO_MODE);
		} else if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
			ctrl_pdata->switch_mode(pdata, DSI_CMD_MODE);
			ctrl_pdata->switch_mode(pdata, SWITCH_TO_CMD_MODE);
			mdss_dsi_set_tear_off(ctrl_pdata);
		}
	}
@@ -1989,46 +1994,6 @@ int mdss_dsi_register_recovery_handler(struct mdss_dsi_ctrl_pdata *ctrl,
	return 0;
}

static int mdss_dsi_clk_refresh(struct mdss_panel_data *pdata)
{
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
	int rc = 0;

	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
							panel_data);
	rc = mdss_dsi_clk_div_config(&pdata->panel_info,
			pdata->panel_info.mipi.frame_rate);
	if (rc) {
		pr_err("%s: unable to initialize the clk dividers\n",
								__func__);
		return rc;
	}
	ctrl_pdata->refresh_clk_rate = false;
	ctrl_pdata->pclk_rate = pdata->panel_info.mipi.dsi_pclk_rate;
	ctrl_pdata->byte_clk_rate = pdata->panel_info.clk_rate / 8;
	pr_debug("%s ctrl_pdata->byte_clk_rate=%d ctrl_pdata->pclk_rate=%d\n",
		__func__, ctrl_pdata->byte_clk_rate, ctrl_pdata->pclk_rate);

	rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle,
		MDSS_DSI_LINK_BYTE_CLK, ctrl_pdata->byte_clk_rate,
		MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON);
	if (rc) {
		pr_err("%s: dsi_byte_clk - clk_set_rate failed\n",
				__func__);
		return rc;
	}

	rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle,
		MDSS_DSI_LINK_PIX_CLK, ctrl_pdata->pclk_rate,
		MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON);
	if (rc) {
		pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n",
			__func__);
		return rc;
	}
	return rc;
}

static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
				  int event, void *arg)
{
@@ -2143,6 +2108,9 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
		if (ctrl_pdata->check_status)
			rc = ctrl_pdata->check_status(ctrl_pdata);
		break;
	case MDSS_EVENT_PANEL_TIMING_SWITCH:
		rc = mdss_dsi_panel_timing_switch(ctrl_pdata, arg);
		break;
	case MDSS_EVENT_FB_REGISTERED:
		mdss_dsi_debugfs_init(ctrl_pdata);
		break;
+18 −2
Original line number Diff line number Diff line
@@ -310,6 +310,18 @@ struct dsi_panel_cmds {
	int link_state;
};

struct dsi_panel_timing {
	struct mdss_panel_timing timing;
	uint32_t phy_timing[12];
	uint32_t phy_timing_8996[40];
	/* DSI_CLKOUT_TIMING_CTRL */
	char t_clk_post;
	char t_clk_pre;
	struct dsi_panel_cmds on_cmds;
	struct dsi_panel_cmds post_panel_on_cmds;
	struct dsi_panel_cmds switch_cmds;
};

struct dsi_kickoff_action {
	struct list_head act_entry;
	void (*action) (void *);
@@ -491,10 +503,10 @@ int dsi_panel_device_register(struct platform_device *ctrl_pdev,
	struct device_node *pan_node, struct mdss_dsi_ctrl_pdata *ctrl_pdata);

int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl,
		struct dsi_cmd_desc *cmds, int cnt);
		struct dsi_cmd_desc *cmds, int cnt, int use_dma_tpg);

int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl,
			struct dsi_cmd_desc *cmds, int rlen);
			struct dsi_cmd_desc *cmds, int rlen, int use_dma_tpg);

void mdss_dsi_host_init(struct mdss_panel_data *pdata);
void mdss_dsi_op_mode_config(int mode,
@@ -520,6 +532,7 @@ void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata);
void mdss_dsi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata);
int mdss_dsi_clk_div_config(struct mdss_panel_info *panel_info,
			    int frame_rate);
int mdss_dsi_clk_refresh(struct mdss_panel_data *pdata);
int mdss_dsi_link_clk_init(struct platform_device *pdev,
		      struct mdss_dsi_ctrl_pdata *ctrl_pdata);
void mdss_dsi_link_clk_deinit(struct device *dev,
@@ -570,6 +583,9 @@ u32 mdss_dsi_panel_cmd_read(struct mdss_dsi_ctrl_pdata *ctrl, char cmd0,
int mdss_dsi_panel_init(struct device_node *node,
		struct mdss_dsi_ctrl_pdata *ctrl_pdata,
		bool cmd_cfg_cont_splash);
int mdss_dsi_panel_timing_switch(struct mdss_dsi_ctrl_pdata *ctrl_pdata,
			struct mdss_panel_timing *timing);

int mdss_panel_parse_bl_settings(struct device_node *np,
			struct mdss_dsi_ctrl_pdata *ctrl_pdata);
int mdss_panel_get_dst_fmt(u32 bpp, char mipi_mode, u32 pixel_packing,
+1 −0
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ struct dsi_cmd_desc {
#define CMD_REQ_COMMIT  0x0002
#define CMD_CLK_CTRL    0x0004
#define CMD_REQ_UNICAST 0x0008
#define CMD_REQ_DMA_TPG 0x0040
#define CMD_REQ_NO_MAX_PKT_SIZE 0x0008
#define CMD_REQ_LP_MODE 0x0010
#define CMD_REQ_HS_MODE 0x0020
+163 −42
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@
#include "mdss_smmu.h"

#define VSYNC_PERIOD 17
#define DMA_TX_TIMEOUT 200
#define DMA_TPG_FIFO_LEN 64

struct mdss_dsi_ctrl_pdata *ctrl_list[DSI_CTRL_MAX];

@@ -1076,7 +1078,6 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata)
	struct mdss_panel_info *pinfo;
	struct mipi_panel_info *mipi;
	struct dsc_desc *dsc = NULL;
	u64 clk_rate;
	u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
	u32 ystride, bpp, dst_bpp, byte_num;
	u32 stream_ctrl, stream_total;
@@ -1090,9 +1091,6 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata)
	if (pinfo->compression_mode == COMPRESSION_DSC)
		dsc = &pinfo->dsc;

	clk_rate = pdata->panel_info.clk_rate;
	clk_rate = min(clk_rate, pdata->panel_info.clk_max);

	dst_bpp = pdata->panel_info.fbc.enabled ?
		(pdata->panel_info.fbc.target_bpp) : (pinfo->bpp);

@@ -1105,6 +1103,8 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata)
	width = mult_frac(pdata->panel_info.xres, dst_bpp,
			pdata->panel_info.bpp);
	height = pdata->panel_info.yres;
	pr_debug("%s: fbc=%d width=%d height=%d dst_bpp=%d\n", __func__,
			pdata->panel_info.fbc.enabled, width, height, dst_bpp);

	if (dsc)	/* compressed */
		width = dsc->pclk_per_line;
@@ -1117,11 +1117,11 @@ static void mdss_dsi_mode_setup(struct mdss_panel_data *pdata)
				pdata->panel_info.lcdc.border_bottom;
	}

	mipi = &pdata->panel_info.mipi;
	if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
		vsync_period = vspw + vbp + height + dummy_yres + vfp;
		hsync_period = hspw + hbp + width + dummy_xres + hfp;

	mipi = &pdata->panel_info.mipi;
	if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
		if (ctrl_pdata->shared_data->timing_db_mode)
			MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x1e8, 0x1);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x24,
@@ -1287,8 +1287,107 @@ static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl,
static int mdss_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
			struct dsi_buf *rp, int rlen);

static int mdss_dsi_cmd_dma_tpg_tx(struct mdss_dsi_ctrl_pdata *ctrl,
					struct dsi_buf *tp)
{
	int len, i, ret = 0, data = 0;
	u32 *bp, ctrl_rev;
	struct mdss_dsi_ctrl_pdata *mctrl = NULL;

	if (tp->len > DMA_TPG_FIFO_LEN) {
		pr_debug("command length more than FIFO length\n");
		return -EINVAL;
	}

	ctrl_rev = MIPI_INP(ctrl->ctrl_base);

	if (ctrl_rev < MDSS_DSI_HW_REV_103) {
		pr_err("CMD DMA TPG not supported for this DSI version\n");
		return -EINVAL;
	}

	bp = (u32 *)tp->data;
	len = ALIGN(tp->len, 4);

	reinit_completion(&ctrl->dma_comp);

	if (mdss_dsi_sync_wait_trigger(ctrl))
		mctrl = mdss_dsi_get_other_ctrl(ctrl);

	data = BIT(16) | BIT(17);	/* select CMD_DMA_PATTERN_SEL to 3 */
	data |= BIT(2);			/* select CMD_DMA_FIFO_MODE to 1 */
	data |= BIT(1);			/* enable CMD_DMA_TPG */

	MIPI_OUTP(ctrl->ctrl_base + 0x15c, data);
	if (mctrl)
		MIPI_OUTP(mctrl->ctrl_base + 0x15c, data);

	/*
	 * The DMA command parameters need to be programmed to the DMA_INIT_VAL
	 * register in the proper order. The 'len' value will be a multiple
	 * of 4, the padding bytes to make sure of this will be taken care of in
	 * mdss_dsi_cmd_dma_add API.
	 */
	for (i = 0; i < len; i += 4) {
		MIPI_OUTP(ctrl->ctrl_base + 0x17c, *bp);
		if (mctrl)
			MIPI_OUTP(mctrl->ctrl_base + 0x17c, *bp);
		wmb(); /* make sure write happens before writing next command */
		bp++;
	}

	/*
	 * The number of writes to the DMA_INIT_VAL register should be an even
	 * number of dwords (32 bits). In case 'len' is not a multiple of 8,
	 * we need to do make an extra write to the register with 0x00 to
	 * satisfy this condition.
	 */
	if ((len % 8) != 0) {
		MIPI_OUTP(ctrl->ctrl_base + 0x17c, 0x00);
		if (mctrl)
			MIPI_OUTP(mctrl->ctrl_base + 0x17c, 0x00);
	}

	if (mctrl) {
		MIPI_OUTP(mctrl->ctrl_base + 0x04c, len);
		MIPI_OUTP(mctrl->ctrl_base + 0x090, 0x01); /* trigger */
	}
	MIPI_OUTP(ctrl->ctrl_base + 0x04c, len);
	wmb(); /* make sure DMA length is programmed */

	MIPI_OUTP(ctrl->ctrl_base + 0x090, 0x01); /* trigger */
	wmb(); /* make sure DMA trigger happens */

	ret = wait_for_completion_timeout(&ctrl->dma_comp,
				msecs_to_jiffies(DMA_TX_TIMEOUT));
	if (ret == 0)
		ret = -ETIMEDOUT;
	else
		ret = tp->len;

	/* Reset the DMA TPG FIFO */
	MIPI_OUTP(ctrl->ctrl_base + 0x1ec, 0x1);
	wmb(); /* make sure FIFO reset happens */
	MIPI_OUTP(ctrl->ctrl_base + 0x1ec, 0x0);
	wmb(); /* make sure FIFO reset happens */
	/* Disable CMD_DMA_TPG */
	MIPI_OUTP(ctrl->ctrl_base + 0x15c, 0x0);

	if (mctrl) {
		/* Reset the DMA TPG FIFO */
		MIPI_OUTP(mctrl->ctrl_base + 0x1ec, 0x1);
		wmb(); /* make sure FIFO reset happens */
		MIPI_OUTP(mctrl->ctrl_base + 0x1ec, 0x0);
		wmb(); /* make sure FIFO reset happens */
		/* Disable CMD_DMA_TPG */
		MIPI_OUTP(mctrl->ctrl_base + 0x15c, 0x0);
	}

	return ret;
}

static int mdss_dsi_cmds2buf_tx(struct mdss_dsi_ctrl_pdata *ctrl,
			struct dsi_cmd_desc *cmds, int cnt)
			struct dsi_cmd_desc *cmds, int cnt, int use_dma_tpg)
{
	struct dsi_buf *tp;
	struct dsi_cmd_desc *cm;
@@ -1315,13 +1414,18 @@ static int mdss_dsi_cmds2buf_tx(struct mdss_dsi_ctrl_pdata *ctrl,
			wait = mdss_dsi_wait4video_eng_busy(ctrl);

			mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
			if (use_dma_tpg)
				len = mdss_dsi_cmd_dma_tpg_tx(ctrl, tp);
			else
				len = mdss_dsi_cmd_dma_tx(ctrl, tp);
			if (IS_ERR_VALUE(len)) {
				mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM);
				pr_err("%s: failed to call cmd_dma_tx for cmd = 0x%x\n",
					__func__,  cmds->payload[0]);
					__func__,  cm->payload[0]);
				return 0;
			}
			pr_debug("%s: cmd_dma_tx for cmd = 0x%x, len = %d\n",
					__func__,  cm->payload[0], len);

			if (!wait || dchdr->wait > VSYNC_PERIOD)
				usleep_range(dchdr->wait * 1000, dchdr->wait * 1000);
@@ -1373,7 +1477,7 @@ static inline bool __mdss_dsi_cmd_mode_config(
 * thread context only
 */
int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl,
		struct dsi_cmd_desc *cmds, int cnt)
		struct dsi_cmd_desc *cmds, int cnt, int use_dma_tpg)
{
	int len = 0;
	struct mdss_dsi_ctrl_pdata *mctrl = NULL;
@@ -1408,7 +1512,7 @@ int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl,
do_send:
	ctrl->cmd_cfg_restore = __mdss_dsi_cmd_mode_config(ctrl, 1);

	len = mdss_dsi_cmds2buf_tx(ctrl, cmds, cnt);
	len = mdss_dsi_cmds2buf_tx(ctrl, cmds, cnt, use_dma_tpg);
	if (!len)
		pr_err("%s: failed to call\n", __func__);

@@ -1449,7 +1553,7 @@ static struct dsi_cmd_desc pkt_size_cmd = {
 *
 */
int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl,
			struct dsi_cmd_desc *cmds, int rlen)
			struct dsi_cmd_desc *cmds, int rlen, int use_dma_tpg)
{
	int data_byte, rx_byte, dlen, end;
	int short_response, diff, pkt_size, ret = 0;
@@ -1531,6 +1635,9 @@ do_send:
		mdss_dsi_wait4video_eng_busy(ctrl);

		mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
		if (use_dma_tpg)
			ret = mdss_dsi_cmd_dma_tpg_tx(ctrl, tp);
		else
			ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
		if (IS_ERR_VALUE(ret)) {
			mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM);
@@ -1564,6 +1671,9 @@ do_send:
		mdss_dsi_wait4video_eng_busy(ctrl);	/* video mode only */
		mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
		/* transmit read comamnd to client */
		if (use_dma_tpg)
			ret = mdss_dsi_cmd_dma_tpg_tx(ctrl, tp);
		else
			ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
		if (IS_ERR_VALUE(ret)) {
			mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM);
@@ -1665,8 +1775,6 @@ end:
	return rp->read_cnt;
}

#define DMA_TX_TIMEOUT 200

static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl,
					struct dsi_buf *tp)
{
@@ -2096,7 +2204,8 @@ int mdss_dsi_cmdlist_tx(struct mdss_dsi_ctrl_pdata *ctrl,
			ctrl->do_unicast = true;
	}

	len = mdss_dsi_cmds_tx(ctrl, req->cmds, req->cmds_cnt);
	len = mdss_dsi_cmds_tx(ctrl, req->cmds, req->cmds_cnt,
				(req->flags & CMD_REQ_DMA_TPG));

	if (req->cb)
		req->cb(len);
@@ -2112,7 +2221,8 @@ int mdss_dsi_cmdlist_rx(struct mdss_dsi_ctrl_pdata *ctrl,

	if (req->rbuf) {
		rp = &ctrl->rx_buf;
		len = mdss_dsi_cmds_rx(ctrl, req->cmds, req->rlen);
		len = mdss_dsi_cmds_rx(ctrl, req->cmds, req->rlen,
				(req->flags & CMD_REQ_DMA_TPG));
		memcpy(req->rbuf, rp->data, rp->len);
		ctrl->rx_len = len;
	} else {
@@ -2133,6 +2243,7 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
	int ret = -EINVAL;
	int rc = 0;
	bool hs_req = false;
	u32 ctrl_rev;

	if (mdss_get_sd_client_cnt())
		return -EPERM;
@@ -2155,6 +2266,12 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
	/* make sure dsi_cmd_mdp is idle */
	mdss_dsi_cmd_mdp_busy(ctrl);

	ctrl_rev = MIPI_INP(ctrl->ctrl_base);

	/* For DSI versions less than 1.3.0, CMD DMA TPG is not supported */
	if (req && (ctrl_rev < MDSS_DSI_HW_REV_103))
		req->flags &= ~CMD_REQ_DMA_TPG;

	pr_debug("%s: ctrl=%d from_mdp=%d pid=%d\n", __func__,
				ctrl->ndx, from_mdp, current->pid);

@@ -2181,6 +2298,9 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)

	MDSS_XLOG(ctrl->ndx, req->flags, req->cmds_cnt, from_mdp, current->pid);

	pr_debug("%s:  from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);

	if (!(req->flags & CMD_REQ_DMA_TPG)) {
		/*
		* mdss interrupt is generated in mdp core clock domain
		* mdp clock need to be enabled to receive dsi interrupt
@@ -2195,8 +2315,6 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
			return rc;
		}

	pr_debug("%s:  from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);

		if (ctrl->mdss_util->iommu_ctrl) {
			rc = ctrl->mdss_util->iommu_ctrl(1);
			if (IS_ERR_VALUE(rc)) {
@@ -2205,6 +2323,7 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
				return rc;
			}
		}
	}

	mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle, MDSS_DSI_ALL_CLKS,
			  MDSS_DSI_CLK_ON);
@@ -2220,13 +2339,15 @@ int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
	if (req->flags & CMD_REQ_HS_MODE)
		mdss_dsi_set_tx_power_mode(1, &ctrl->panel_data);

	if (!(req->flags & CMD_REQ_DMA_TPG)) {
		if (ctrl->mdss_util->iommu_ctrl)
			ctrl->mdss_util->iommu_ctrl(0);

		(void)mdss_dsi_bus_bandwidth_vote(ctrl->shared_data, false);
		mdss_dsi_clk_ctrl(ctrl, ctrl->dsi_clk_handle, MDSS_DSI_ALL_CLKS,
			  MDSS_DSI_CLK_OFF);
	}

	(void)mdss_dsi_bus_bandwidth_vote(ctrl->shared_data, false);
need_lock:

	MDSS_XLOG(ctrl->ndx, from_mdp, ctrl->mdp_busy, current->pid,
Loading