Exemple #1
0
int mdss_dsi_cont_splash_on(struct mdss_panel_data *pdata)
{
	int ret = 0;
	struct mipi_panel_info *mipi;
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;

	pr_info("%s:%d DSI on for continuous splash.\n", __func__, __LINE__);

	if (pdata == NULL) {
		pr_err("%s: Invalid input data\n", __func__);
		return -EINVAL;
	}

#if defined(CONFIG_FB_MSM_MDSS_S6E8AA0A_HD_PANEL)
		mdss_dsi_reset(pdata);
#endif

	mipi = &pdata->panel_info.mipi;

	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
				panel_data);

	pr_debug("%s+: ctrl=%p ndx=%d\n", __func__,
				ctrl_pdata, ctrl_pdata->ndx);

	WARN((ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT),
		"Incorrect Ctrl state=0x%x\n", ctrl_pdata->ctrl_state);

#if defined(CONFIG_FB_MSM_MDSS_SDC_WXGA_PANEL)
	ret = mdss_dsi_panel_power_on(pdata, 0);
	if (ret) {
		pr_err("%s: Panel power on with 0 failed\n", __func__);
		return ret;
	}
	mdelay(10);
	ret = mdss_dsi_panel_power_on(pdata, 1);
	if (ret) {
		pr_err("%s: Panel power on with 1 failed\n", __func__);
		return ret;
	}
#endif
	mdss_dsi_sw_reset(pdata);
	mdss_dsi_host_init(mipi, pdata);
#if RESET_IN_LP11 // add for LP11
	// LP11
	{
	u32 tmp;
	tmp = MIPI_INP((ctrl_pdata->ctrl_base) + 0xac);
	tmp &= ~(1<<28);
	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0xac, tmp);
	wmb();
	}
	// LP11

	(ctrl_pdata->panel_data).panel_reset_fn(pdata, 1);
#endif

	if (mipi->force_clk_lane_hs) {
		u32 tmp;

		tmp = MIPI_INP((ctrl_pdata->ctrl_base) + 0xac);
		tmp |= (1<<28);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0xac, tmp);
		wmb();
	}
	mdss_dsi_op_mode_config(mipi->mode, pdata);

	if (ctrl_pdata->on_cmds.link_state == DSI_LP_MODE) {
		ret = mdss_dsi_unblank(pdata);
		if (ret) {
			pr_err("%s: unblank failed\n", __func__);
			return ret;
		}
	}

	pr_debug("%s-:End\n", __func__);
	return ret;
}
int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl,
			struct dsi_cmd_desc *cmds, int rlen)
{
	int cnt, len, diff, pkt_size, ret = 0;
	struct dsi_buf *tp, *rp;
	int no_max_pkt_size;
	char cmd;
	u32 dsi_ctrl, data;
	int video_mode;
	u32 left_dsi_ctrl = 0;
	bool left_ctrl_restore = false;
	int rx_flags = 0;
	bool long_rd_rsp_chk = false;

	if (ctrl->shared_pdata.broadcast_enable) {
		if (ctrl->ndx == DSI_CTRL_0) {
			pr_debug("%s: Broadcast mode. 1st ctrl\n",
				 __func__);
			return 0;
		}
	}

	if (ctrl->shared_pdata.broadcast_enable) {
		if ((ctrl->ndx == DSI_CTRL_1)
		  && (left_ctrl_pdata != NULL)) {
			left_dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
								+ 0x0004);
			video_mode = left_dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
			if (video_mode) {
				data = left_dsi_ctrl | 0x04; /* CMD_MODE_EN */
				MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
						data);
				left_ctrl_restore = true;
			}
		}
	}

	/* turn on cmd mode
	* for video mode, do not send cmds more than
	* one pixel line, since it only transmit it
	* during BLLP.
	*/
	dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004);
	video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
	if (video_mode) {
		data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
		MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data);
	}

	no_max_pkt_size = rx_flags & CMD_REQ_NO_MAX_PKT_SIZE;
	if (no_max_pkt_size)
		rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */

	len = rlen;
	diff = 0;

	if (len < 2)
		cnt = 4;	/* short read */
	else if (len == 2) {
		/* Response could be a short or long read */
		cnt = 8;
		long_rd_rsp_chk = true;
	} else {
		if (len > MDSS_DSI_LEN)
			len = MDSS_DSI_LEN;	/* 8 bytes at most */

		len = ALIGN(len, 4); /* len 4 bytes align */
		diff = len - rlen;
		/*
		 * add extra 2 bytes to len to have overall
		 * packet size is multipe by 4. This also make
		 * sure 4 bytes dcs headerlocates within a
		 * 32 bits register after shift in.
		 * after all, len should be either 6 or 10.
		 */
		len += 2;
		cnt = len + 6; /* 4 bytes header + 2 bytes crc */
	}

	tp = &ctrl->tx_buf;
	rp = &ctrl->rx_buf;

	if (!no_max_pkt_size) {
		/* packet size need to be set at every read */
		pkt_size = len;
		max_pktsize[0] = pkt_size;
		mdss_dsi_buf_init(tp);
		ret = mdss_dsi_cmd_dma_add(tp, &pkt_size_cmd);
		if (!ret) {
			pr_err("%s: failed to call\n",
				__func__);
			rp->len = 0;
			goto end;
		}

		mdss_dsi_wait4video_eng_busy(ctrl);

		mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
		ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
		if (IS_ERR_VALUE(ret)) {
			mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM);
			pr_err("%s: failed to call\n",
				__func__);
			rp->len = 0;
			goto end;
		}
		pr_debug("%s: Max packet size sent\n", __func__);
	}
	mdss_dsi_buf_init(tp);
	ret = mdss_dsi_cmd_dma_add(tp, cmds);
	if (!ret) {
		pr_err("%s: failed to call cmd_dma_add for cmd = 0x%x\n",
			__func__,  cmds->payload[0]);
		rp->len = 0;
		goto end;
	}

	mdss_dsi_wait4video_eng_busy(ctrl);

	mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
	/* transmit read comamnd to client */
	ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
	if (IS_ERR_VALUE(ret)) {
		mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM);
		pr_err("%s: failed to call\n",
			__func__);
		rp->len = 0;
		goto end;
	}
	/*
	 * once cmd_dma_done interrupt received,
	 * return data from client is ready and stored
	 * at RDBK_DATA register already
	 */
	mdss_dsi_buf_init(rp);
	if (no_max_pkt_size) {
		/*
		 * expect rlen = n * 4
		 * short alignement for start addr
		 */
		rp->data += 2;
	}

	mdss_dsi_cmd_dma_rx(ctrl, rp, cnt);

	if (no_max_pkt_size) {
		/*
		 * remove extra 2 bytes from previous
		 * rx transaction at shift register
		 * which was inserted during copy
		 * shift registers to rx buffer
		 * rx payload start from long alignment addr
		 */
		rp->data += 2;
	}

	if (long_rd_rsp_chk &&
		rp->data[0] != DTYPE_GEN_LREAD_RESP &&
		rp->data[0] != DTYPE_DCS_LREAD_RESP)
		rp->data += 4;

	cmd = rp->data[0];
	switch (cmd) {
	case DTYPE_ACK_ERR_RESP:
		pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
		rp->len = 0;
	case DTYPE_GEN_READ1_RESP:
	case DTYPE_DCS_READ1_RESP:
		mdss_dsi_short_read1_resp(rp);
		break;
	case DTYPE_GEN_READ2_RESP:
	case DTYPE_DCS_READ2_RESP:
		mdss_dsi_short_read2_resp(rp);
		break;
	case DTYPE_GEN_LREAD_RESP:
	case DTYPE_DCS_LREAD_RESP:
		mdss_dsi_long_read_resp(rp);
		if (!long_rd_rsp_chk) {
			rp->len -= 2; /* extra 2 bytes added */
			rp->len -= diff; /* align bytes */
		}
		break;
	default:
		pr_warning("%s:Invalid response cmd\n", __func__);
		rp->len = 0;
	}
end:
	if (left_ctrl_restore)
		MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
					left_dsi_ctrl); /*restore */
	if (video_mode)
		MIPI_OUTP((ctrl->ctrl_base) + 0x0004,
					dsi_ctrl); /* restore */

	return rp->len;
}
void mdss_dsi_op_mode_config(int mode,
			     struct mdss_panel_data *pdata)
{
	u32 dsi_ctrl, intr_ctrl;
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
	struct mdss_dsi_ctrl_pdata *mctrl = NULL;

	if (pdata == NULL) {
		pr_err("%s: Invalid input data\n", __func__);
		return;
	}

	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
				panel_data);

	/*
	 * In broadcast mode, the configuration for master controller
	 * would be done when the slave controller is configured
	 */
	if (mdss_dsi_is_master_ctrl(ctrl_pdata)) {
		pr_debug("%s: Broadcast mode enabled. skipping config for ctrl%d\n",
			__func__, ctrl_pdata->ndx);
		return;
	}

	dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004);
	/*If Video enabled, Keep Video and Cmd mode ON */
	if (dsi_ctrl & 0x02)
		dsi_ctrl &= ~0x05;
	else
		dsi_ctrl &= ~0x07;

	if (mode == DSI_VIDEO_MODE) {
		dsi_ctrl |= 0x03;
		intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_BTA_DONE_MASK;
	} else {		/* command mode */
		dsi_ctrl |= 0x05;
		if (pdata->panel_info.type == MIPI_VIDEO_PANEL)
			dsi_ctrl |= 0x02;

		intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_ERROR_MASK |
			DSI_INTR_CMD_MDP_DONE_MASK | DSI_INTR_BTA_DONE_MASK;
	}

	/* Ensure that for slave controller, master is also configured */
	if (mdss_dsi_is_slave_ctrl(ctrl_pdata)) {
		mctrl = mdss_dsi_get_master_ctrl();
		if (mctrl) {
			pr_debug("%s: configuring ctrl%d\n", __func__,
				mctrl->ndx);
			MIPI_OUTP(mctrl->ctrl_base + 0x0110, intr_ctrl);
			MIPI_OUTP(mctrl->ctrl_base + 0x0004, dsi_ctrl);
		} else {
			pr_warn("%s: Unable to get master control\n",
				__func__);
		}
	}

	pr_debug("%s: configuring ctrl%d\n", __func__, ctrl_pdata->ndx);
	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0110, intr_ctrl);
	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl);
	wmb();
}
Exemple #4
0
int disp_ext_board_detect_board(struct msm_fb_data_type *mfd)
{
	int i;
	int ret = 0;
	int panel_found;
#ifndef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM
	uint32_t data;
#else
	uint32_t data[2];
#endif

    DISP_LOCAL_LOG_EMERG("DISP disp_ext_board_detect_board S\n");

	if( panel_detection != 0 ) {
		pr_debug("%s:panel Checked\n", __func__);
		DISP_LOCAL_LOG_EMERG("%s:panel Checked\n", __func__);
		return panel_detection;
	}
	mipi_dsi_op_mode_config(DSI_CMD_MODE);

#ifndef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM
	/* cmd1 select */
	ret = disp_ext_board_cmd_tx( detect_board_cmd1_select, sizeof(detect_board_cmd1_select), 0 );
	if ( ret != 0 ) {
		pr_err("%s:command send err1\n", __func__);
		mipi_dsi_op_mode_config(mfd->panel_info.mipi.mode);
		light_led_disp_set(LIGHT_MAIN_WLED_LCD_DIS);

		panel_detection = -1;
		return panel_detection;
	}
#endif

#ifdef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM
	mipi_dsi_clk_cfg(1);
#endif
	panel_found = 0;
	for( i = 0 ; i < DETECT_BOARD_NUM ; i++ ) {
		/* MIPI_DSI_MRPS, Maximum Return Packet Size */
		if (!mfd->panel_info.mipi.no_max_pkt_size) {
			disp_ext_board_cmd_tx( maximum_return_seze_set , sizeof(maximum_return_seze_set), 0 );
		}
		ret = disp_ext_board_cmd_tx( detect_board_mipi_lane_read , sizeof(detect_board_mipi_lane_read), 5 );
		if ( ret != 0 ) {
			pr_err("%s:ack no receive\n", __func__);
			mipi_dsi_op_mode_config(mfd->panel_info.mipi.mode);
			light_led_disp_set(LIGHT_MAIN_WLED_LCD_DIS);
			panel_detection = -1;
			return panel_detection;
		}
#ifndef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM
	    data = (uint32)MIPI_INP(MIPI_DSI_BASE + 0x68);

	    if( ((data >> 16) & 0xFF) == 0x02 ) {
			panel_found = 1;
			break;
		}
#else
		data[0] = (uint32)MIPI_INP(MIPI_DSI_BASE + 0x6C);
		data[1] = (uint32)MIPI_INP(MIPI_DSI_BASE + 0x68);
		data[1] &= 0xffff0000;
		pr_info("%s: device code=%04x %04x\n",
			 __func__,
			data[0],
			data[1]
			);

		if ( (data[0] == 0x01010101)&&(data[1] == 0x00ff0000) ) {
			panel_found = 1;
			break;
		}
		else if ( (data[0] == 0x02020202)&&(data[1] == 0x00ff0000) ) {
			panel_found = 2;
			break;
		}
#endif
	}
#ifndef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM
	if( panel_found != 1 ) {
#else
	mipi_dsi_clk_cfg(0);
	if( panel_found != 1 && panel_found != 2) {
#endif
		pr_debug("%s:panel not found\n", __func__);
		DISP_LOCAL_LOG_EMERG("%s:panel not found 2\n", __func__);
		mipi_dsi_op_mode_config(mfd->panel_info.mipi.mode);
		light_led_disp_set(LIGHT_MAIN_WLED_LCD_DIS);
		panel_detection = -1;
		return panel_detection;
	}
	pr_debug("%s:panel found\n", __func__);
	DISP_LOCAL_LOG_EMERG("%s:panel found\n", __func__);
	mipi_dsi_op_mode_config(mfd->panel_info.mipi.mode);
	light_led_disp_set(LIGHT_MAIN_WLED_LCD_EN);
	

    DISP_LOCAL_LOG_EMERG("DISP disp_ext_board_detect_board E\n");
#ifndef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM
	panel_detection = 1;
#else
	panel_detection = panel_found;
#endif
	return panel_detection;
}

int disp_ext_board_get_panel_detect(void)
{
    return panel_detection;
}
int mdss_dsi_on(struct mdss_panel_data *pdata)
{
	int ret = 0;
	u32 clk_rate;
	struct mdss_panel_info *pinfo;
	struct mipi_panel_info *mipi;
	u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
	u32 ystride, bpp, data, dst_bpp;
	u32 dummy_xres, dummy_yres;
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;

	if (pdata == NULL) {
		pr_err("%s: Invalid input data\n", __func__);
		return -EINVAL;
	}

	if (pdata->panel_info.panel_power_on) {
		pr_warn("%s:%d Panel already on.\n", __func__, __LINE__);
		return 0;
	}

	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
				panel_data);

	pr_info("%s+: ctrl=%p ndx=%d\n",
				__func__, ctrl_pdata, ctrl_pdata->ndx);

	pinfo = &pdata->panel_info;

	ret = mdss_dsi_panel_power_on(pdata, 1);
	if (ret) {
		pr_err("%s: Panel power on failed\n", __func__);
		return ret;
	}

	pdata->panel_info.panel_power_on = 1;

	ret = mdss_dsi_enable_bus_clocks(ctrl_pdata);
	if (ret) {
		pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__,
			ret);
		mdss_dsi_panel_power_on(pdata, 0);
		return ret;
	}
	mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base));
	mdss_dsi_phy_init(pdata);
	mdss_dsi_disable_bus_clocks(ctrl_pdata);

	mdss_dsi_clk_ctrl(ctrl_pdata, 1);

	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);

	hbp = mult_frac(pdata->panel_info.lcdc.h_back_porch, dst_bpp,
			pdata->panel_info.bpp);
	hfp = mult_frac(pdata->panel_info.lcdc.h_front_porch, dst_bpp,
			pdata->panel_info.bpp);
	vbp = mult_frac(pdata->panel_info.lcdc.v_back_porch, dst_bpp,
			pdata->panel_info.bpp);
	vfp = mult_frac(pdata->panel_info.lcdc.v_front_porch, dst_bpp,
			pdata->panel_info.bpp);
	hspw = mult_frac(pdata->panel_info.lcdc.h_pulse_width, dst_bpp,
			pdata->panel_info.bpp);
	vspw = pdata->panel_info.lcdc.v_pulse_width;
	width = mult_frac(pdata->panel_info.xres, dst_bpp,
			pdata->panel_info.bpp);
#ifdef CONFIG_OLED_SUPPORT
	height = pdata->panel_info.yres + pdata->panel_info.lcdc.yres_margin;
#else
	height = pdata->panel_info.yres;
#endif

	mipi  = &pdata->panel_info.mipi;
	if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
		dummy_xres = pdata->panel_info.lcdc.xres_pad;
		dummy_yres = pdata->panel_info.lcdc.yres_pad;

		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x24,
			((hspw + hbp + width + dummy_xres) << 16 |
			(hspw + hbp)));
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x28,
			((vspw + vbp + height + dummy_yres) << 16 |
			(vspw + vbp)));
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C,
			(vspw + vbp + height + dummy_yres +
				vfp - 1) << 16 | (hspw + hbp +
				width + dummy_xres + hfp - 1));

		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x30, (hspw << 16));
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x34, 0);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x38, (vspw << 16));

	} else {		/* command mode */
		if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
			bpp = 2;
		else
			bpp = 3;	/* Default format set to RGB888 */

		ystride = width * bpp + 1;

		/* DSI_COMMAND_MODE_MDP_STREAM_CTRL */
		data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE;
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x60, data);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x58, data);

		/* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */
		data = height << 16 | width;
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x64, data);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x5C, data);
	}

	mdss_dsi_sw_reset(pdata);
	mdss_dsi_host_init(mipi, pdata);

	if (mipi->force_clk_lane_hs) {
		u32 tmp;

		tmp = MIPI_INP((ctrl_pdata->ctrl_base) + 0xac);
		tmp |= (1<<28);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0xac, tmp);
		wmb();
	}

#if defined(CONFIG_MACH_LGE)
#if defined(CONFIG_OLED_SUPPORT)
	msleep(10);
	mdss_dsi_panel_reset(pdata, 1);
	msleep(20);
#else
	/* LGE_CHANGE_S
	 * power sequence for LGD_FHD panel
	 * 2013-04-05, [email protected]
	 */
	#if defined (CONFIG_MACH_MSM8974_VU3_KR)
		msleep(40);
	#else
		msleep(1);
	#endif
	mdss_dsi_panel_reset(pdata, 1);
#endif
#endif

	if (pdata->panel_info.type == MIPI_CMD_PANEL)
		mdss_dsi_clk_ctrl(ctrl_pdata, 0);

	pr_debug("%s-:\n", __func__);
	return 0;
}
Exemple #6
0
/*
 * mdss_dsi_cmds_tx:
 * thread context only
 */
int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl,
		struct dsi_cmd_desc *cmds, int cnt)
{
	struct dsi_buf *tp;
	struct dsi_cmd_desc *cm;
	struct dsi_ctrl_hdr *dchdr;
	u32 dsi_ctrl, data;
	int i, video_mode;
#ifdef CONFIG_OLED_SUPPORT
	struct timeval tv_start, tv_end;
	long tv_diff;
	int delay_count;
#endif

	if (ctrl->shared_pdata.broadcast_enable) {
		if (ctrl->ndx == DSI_CTRL_0) {
			pr_debug("%s: Broadcast mode. 1st ctrl\n",
				 __func__);
			return 0;
		}
	}

	if (ctrl->shared_pdata.broadcast_enable) {
		if ((ctrl->ndx == DSI_CTRL_1)
		  && (left_ctrl_pdata != NULL)) {
			dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
								+ 0x0004);
			video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
			if (video_mode) {
				data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
				MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
						data);
			}
		}
	}

	/* turn on cmd mode
	* for video mode, do not send cmds more than
	* one pixel line, since it only transmit it
	* during BLLP.
	*/
	dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004);
	video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
	if (video_mode) {
		data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
		MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data);
	}

	tp = &ctrl->tx_buf;
	cm = cmds;
	for (i = 0; i < cnt; i++) {
		mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
		mdss_dsi_buf_init(tp);
		mdss_dsi_cmd_dma_add(tp, cm);
		mdss_dsi_cmd_dma_tx(ctrl, tp);
		dchdr = &cm->dchdr;
#ifdef CONFIG_OLED_SUPPORT
		if(dchdr->wait) {
			delay_count = 0;
			do_gettimeofday(&tv_start);
			do {
				mdelay(1);
				do_gettimeofday(&tv_end);
				tv_diff = ((tv_end.tv_sec - tv_start.tv_sec) * 1000000) // sec
						+ (tv_end.tv_usec - tv_start.tv_usec);			// usec
				delay_count++;
			} while(dchdr->wait * 1000 > tv_diff);
			pr_info("%s: 0x%X needs %d(ms) delay and real delay is %ld(us), delay_count(%d).\n", __func__, cm->payload[0], (int)dchdr->wait, tv_diff, delay_count);
		}
#else
		if (dchdr->wait)
			usleep(dchdr->wait * 1000);
#endif
		cm++;
	}

	if (video_mode)
		MIPI_OUTP((ctrl->ctrl_base) + 0x0004,
					dsi_ctrl); /* restore */
	return cnt;
}
static int mipi_dsi_off(struct platform_device *pdev)
{
	int ret = 0;
	struct msm_fb_data_type *mfd;
	struct msm_panel_info *pinfo;
	uint32 dsi_ctrl;

#ifdef CONFIG_FB_MSM_LCD_NOTIFY
	lcd_notifier_call_chain(LCD_EVENT_OFF_START, NULL);
#endif
	pr_debug("%s+:\n", __func__);

	mfd = platform_get_drvdata(pdev);
	pinfo = &mfd->panel_info;

	if (mdp_rev >= MDP_REV_41)
		mutex_lock(&mfd->dma->ov_mutex);
	else
		down(&mfd->dma->mutex);

	if (mfd->panel_info.type == MIPI_CMD_PANEL) {
		mipi_dsi_prepare_clocks();
		mipi_dsi_ahb_ctrl(1);
		mipi_dsi_clk_enable();

		/* make sure dsi_cmd_mdp is idle */
		mipi_dsi_cmd_mdp_busy();
	}

	/*
	 * Desctiption: change to DSI_CMD_MODE since it needed to
	 * tx DCS dsiplay off comamnd to panel
	 * mipi_dsi_op_mode_config(DSI_CMD_MODE);
	 */

	if (mfd->panel_info.type == MIPI_CMD_PANEL) {
		if (pinfo->lcd.vsync_enable) {
			if (pinfo->lcd.hw_vsync_mode && vsync_gpio >= 0) {
				if (MDP_REV_303 != mdp_rev)
					gpio_free(vsync_gpio);
			}
			mipi_dsi_set_tear_off(mfd);
		}
	}

	ret = panel_next_off(pdev);

	spin_lock_bh(&dsi_clk_lock);
	
	mipi_dsi_clk_disable();

	/* disbale dsi engine */
	dsi_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0000);
	dsi_ctrl &= ~0x01;
	MIPI_OUTP(MIPI_DSI_BASE + 0x0000, dsi_ctrl);

	MIPI_OUTP(MIPI_DSI_BASE + 0x010c, 0); /* DSI_INTL_CTRL */
	MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);

	mipi_dsi_phy_ctrl(0);

	mipi_dsi_ahb_ctrl(0);
	spin_unlock_bh(&dsi_clk_lock);

	mipi_dsi_unprepare_clocks();

	usleep(5000);
#if  defined (CONFIG_MIPI_DSI_RESET_LP11)

	if (mipi_dsi_pdata && mipi_dsi_pdata->active_reset)
		mipi_dsi_pdata->active_reset(0); /* low */
#endif	

	usleep(2000); /*1ms delay(minimum) required between reset low and AVDD off*/
#if defined(CONFIG_SUPPORT_SECOND_POWER)
	if (mipi_dsi_pdata && mipi_dsi_pdata->panel_power_save)
		mipi_dsi_pdata->panel_power_save(0);
#endif
	if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
		mipi_dsi_pdata->dsi_power_save(0);

	if (mdp_rev >= MDP_REV_41)
		mutex_unlock(&mfd->dma->ov_mutex);
	else
		up(&mfd->dma->mutex);

#ifdef CONFIG_FB_MSM_LCD_NOTIFY
	lcd_notifier_call_chain(LCD_EVENT_OFF_END, NULL);
#endif
	pr_debug("%s-:\n", __func__);

	return ret;
}
/*
 * mdss_dsi_cmds_rx() - dcs read from panel
 * @ctrl: dsi controller
 * @cmds: read command descriptor
 * @len: number of bytes to read back
 *
 * controller have 4 registers can hold 16 bytes of rxed data
 * dcs packet: 4 bytes header + payload + 2 bytes crc
 * 2 padding bytes add to payload to have payload length is mutipled by 4
 * 1st read: 4 bytes header + 8 bytes payload + 2 padding + 2 crc
 * 2nd read: 12 bytes payload + 2 padding + 2 crc
 * 3rd read: 12 bytes payload + 2 padding + 2 crc
 *
 */
int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl,
			struct dsi_cmd_desc *cmds, int rlen)
{
	int data_byte, rx_byte, dlen, end;
	int short_response, diff, pkt_size, ret = 0;
	struct dsi_buf *tp, *rp;
	char cmd;
	u32 dsi_ctrl, data;
	int video_mode;
	u32 left_dsi_ctrl = 0;
	bool left_ctrl_restore = false;

	if (ctrl->shared_pdata.broadcast_enable) {
		if (ctrl->ndx == DSI_CTRL_0) {
			pr_debug("%s: Broadcast mode. 1st ctrl\n",
				 __func__);
			return 0;
		}
	}

	if (ctrl->shared_pdata.broadcast_enable) {
		if ((ctrl->ndx == DSI_CTRL_1)
		  && (left_ctrl_pdata != NULL)) {
			left_dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
								+ 0x0004);
			video_mode = left_dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
			if (video_mode) {
				data = left_dsi_ctrl | 0x04; /* CMD_MODE_EN */
				MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
						data);
				left_ctrl_restore = true;
			}
		}
	}

	/* turn on cmd mode
	* for video mode, do not send cmds more than
	* one pixel line, since it only transmit it
	* during BLLP.
	*/
	dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004);
	video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
	if (video_mode) {
		data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
		MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data);
	}
/*fix qcom bug*/
#ifdef CONFIG_HUAWEI_KERNEL
	if (rlen <= 2) {
#else		
	if (rlen == 0) {
#endif	
		short_response = 1;
		rx_byte = 4;
	} else {
		short_response = 0;
		data_byte = 8;	/* first read */
		/*
		 * add extra 2 padding bytes to have overall
		 * packet size is multipe by 4. This also make
		 * sure 4 bytes dcs headerlocates within a
		 * 32 bits register after shift in.
		 */
		pkt_size = data_byte + 2;
		rx_byte = data_byte + 8; /* 4 header + 2 crc  + 2 padding*/
	}


	tp = &ctrl->tx_buf;
	rp = &ctrl->rx_buf;

	end = 0;
	mdss_dsi_buf_init(rp);
	while (!end) {
		pr_debug("%s:  rlen=%d pkt_size=%d rx_byte=%d\n",
				__func__, rlen, pkt_size, rx_byte);
		 if (!short_response) {
			max_pktsize[0] = pkt_size;
			mdss_dsi_buf_init(tp);
			ret = mdss_dsi_cmd_dma_add(tp, &pkt_size_cmd);
			if (!ret) {
				pr_err("%s: failed to add max_pkt_size\n",
					__func__);
				rp->len = 0;
				goto end;
			}

			mdss_dsi_wait4video_eng_busy(ctrl);

			mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
			ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
			if (IS_ERR_VALUE(ret)) {
				mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM);
				pr_err("%s: failed to tx max_pkt_size\n",
					__func__);
				rp->len = 0;
				goto end;
			}
			pr_debug("%s: max_pkt_size=%d sent\n",
						__func__, pkt_size);
		}

		mdss_dsi_buf_init(tp);
		ret = mdss_dsi_cmd_dma_add(tp, cmds);
		if (!ret) {
			pr_err("%s: failed to add cmd = 0x%x\n",
				__func__,  cmds->payload[0]);
			rp->len = 0;
			goto end;
		}

		mdss_dsi_wait4video_eng_busy(ctrl);	/* video mode only */
		mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
		/* transmit read comamnd to client */
		ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
		if (IS_ERR_VALUE(ret)) {
			mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM);
			pr_err("%s: failed to tx cmd = 0x%x\n",
				__func__,  cmds->payload[0]);
			rp->len = 0;
			goto end;
		}
		/*
		 * once cmd_dma_done interrupt received,
		 * return data from client is ready and stored
		 * at RDBK_DATA register already
		 * since rx fifo is 16 bytes, dcs header is kept at first loop,
		 * after that dcs header lost during shift into registers
		 */
		dlen = mdss_dsi_cmd_dma_rx(ctrl, rp, rx_byte);

		if (short_response)
			break;

		if (rlen <= data_byte) {
			diff = data_byte - rlen;
			end = 1;
		} else {
			diff = 0;
			rlen -= data_byte;
		}

		dlen -= 2; /* 2 padding bytes */
		dlen -= 2; /* 2 crc */
		dlen -= diff;
		rp->data += dlen;	/* next start position */
		rp->len += dlen;
		data_byte = 12;	/* NOT first read */
		pkt_size += data_byte;
		pr_debug("%s: rp data=%x len=%d dlen=%d diff=%d\n",
			__func__, (int)rp->data, rp->len, dlen, diff);
	}

	rp->data = rp->start;	/* move back to start position */
	cmd = rp->data[0];
	switch (cmd) {
	case DTYPE_ACK_ERR_RESP:
		pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
		rp->len = 0;
	case DTYPE_GEN_READ1_RESP:
	case DTYPE_DCS_READ1_RESP:
		mdss_dsi_short_read1_resp(rp);
		break;
	case DTYPE_GEN_READ2_RESP:
	case DTYPE_DCS_READ2_RESP:
		mdss_dsi_short_read2_resp(rp);
		break;
	case DTYPE_GEN_LREAD_RESP:
	case DTYPE_DCS_LREAD_RESP:
		mdss_dsi_long_read_resp(rp);
		break;
	default:
		pr_warning("%s:Invalid response cmd\n", __func__);
		rp->len = 0;
	}
end:
	if (left_ctrl_restore)
		MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
					left_dsi_ctrl); /*restore */
	if (video_mode)
		MIPI_OUTP((ctrl->ctrl_base) + 0x0004,
					dsi_ctrl); /* restore */

	return rp->len;
}

#define DMA_TX_TIMEOUT 200
static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl,
					struct dsi_buf *tp)
{
	int len, ret = 0;
	int domain = MDSS_IOMMU_DOMAIN_UNSECURE;
	char *bp;
	unsigned long size, addr;
#ifdef CONFIG_HUAWEI_LCD
    bool iommu_attached = false;
#endif
	bp = tp->data;

	len = ALIGN(tp->len, 4);
	size = ALIGN(tp->len, SZ_4K);


	if (is_mdss_iommu_attached()) {
		int ret = msm_iommu_map_contig_buffer(tp->dmap,
					mdss_get_iommu_domain(domain), 0,
					size, SZ_4K, 0, &(addr));
		if (IS_ERR_VALUE(ret)) {
			pr_err("unable to map dma memory to iommu(%d)\n", ret);
			return -ENOMEM;
		}
    #ifdef CONFIG_HUAWEI_LCD
        iommu_attached = true;
    #endif
	} else {
		addr = tp->dmap;
    #ifdef CONFIG_HUAWEI_LCD
        iommu_attached = false;
    #endif
	}

	INIT_COMPLETION(ctrl->dma_comp);

	if (ctrl->shared_pdata.broadcast_enable)
		if ((ctrl->ndx == DSI_CTRL_1)
		  && (left_ctrl_pdata != NULL)) {
			MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x048, addr);
			MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x04c, len);
		}

	MIPI_OUTP((ctrl->ctrl_base) + 0x048, addr);
	MIPI_OUTP((ctrl->ctrl_base) + 0x04c, len);
	wmb();

	if (ctrl->shared_pdata.broadcast_enable)
		if ((ctrl->ndx == DSI_CTRL_1)
		  && (left_ctrl_pdata != NULL)) {
			MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x090, 0x01);
		}

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

	ret = wait_for_completion_timeout(&ctrl->dma_comp,
				msecs_to_jiffies(DMA_TX_TIMEOUT));
	if (ret == 0)
		ret = -ETIMEDOUT;
	else
		ret = tp->len;
#ifdef CONFIG_HUAWEI_LCD
    //unmap it when it have been maped at front
    if (is_mdss_iommu_attached() && iommu_attached)
#else
    if (is_mdss_iommu_attached())
#endif
		msm_iommu_unmap_contig_buffer(addr,
			mdss_get_iommu_domain(domain), 0, size);

	return ret;
}
Exemple #9
0
static int mipi_dsi_on(struct platform_device *pdev)
{
	int ret = 0;
	u32 clk_rate;
	struct msm_fb_data_type *mfd;
	struct fb_info *fbi;
	struct fb_var_screeninfo *var;
	struct msm_panel_info *pinfo;
	struct mipi_panel_info *mipi;
	u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
	u32 ystride, bpp, data;
	u32 dummy_xres, dummy_yres;
	int target_type = 0;

	pr_debug("%s+:\n", __func__);

	mfd = platform_get_drvdata(pdev);
	fbi = mfd->fbi;
	var = &fbi->var;
	pinfo = &mfd->panel_info;

	if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
		mipi_dsi_pdata->dsi_power_save(1);

	cont_splash_clk_ctrl(0);
	mipi_dsi_prepare_ahb_clocks();

	mipi_dsi_ahb_ctrl(1);

	clk_rate = mfd->fbi->var.pixclock;
	clk_rate = min(clk_rate, mfd->panel_info.clk_max);

	mipi_dsi_phy_ctrl(1);

	if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata)
		target_type = mipi_dsi_pdata->target_type;

	mipi_dsi_phy_init(0, &(mfd->panel_info), target_type);

	mipi_dsi_clk_enable();

	MIPI_OUTP(MIPI_DSI_BASE + 0x114, 1);
	MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0);

	hbp = var->left_margin;
	hfp = var->right_margin;
	vbp = var->upper_margin;
	vfp = var->lower_margin;
	hspw = var->hsync_len;
	vspw = var->vsync_len;
	width = mfd->panel_info.xres;
	height = mfd->panel_info.yres;

	mipi  = &mfd->panel_info.mipi;
	if (mfd->panel_info.type == MIPI_VIDEO_PANEL) {
		dummy_xres = mfd->panel_info.lcdc.xres_pad;
		dummy_yres = mfd->panel_info.lcdc.yres_pad;

		if (mdp_rev >= MDP_REV_41) {
			MIPI_OUTP(MIPI_DSI_BASE + 0x20,
				((hspw + hbp + width + dummy_xres) << 16 |
				(hspw + hbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x24,
				((vspw + vbp + height + dummy_yres) << 16 |
				(vspw + vbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x28,
				(vspw + vbp + height + dummy_yres +
					vfp - 1) << 16 | (hspw + hbp +
					width + dummy_xres + hfp - 1));
		} else {
			/* DSI_LAN_SWAP_CTRL */
			MIPI_OUTP(MIPI_DSI_BASE + 0x00ac, mipi->dlane_swap);

			MIPI_OUTP(MIPI_DSI_BASE + 0x20,
				((hbp + width + dummy_xres) << 16 | (hbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x24,
				((vbp + height + dummy_yres) << 16 | (vbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x28,
				(vbp + height + dummy_yres + vfp) << 16 |
					(hbp + width + dummy_xres + hfp));
		}

		MIPI_OUTP(MIPI_DSI_BASE + 0x2c, (hspw << 16));
		MIPI_OUTP(MIPI_DSI_BASE + 0x30, 0);
		MIPI_OUTP(MIPI_DSI_BASE + 0x34, (vspw << 16));

	} else {		/* command mode */
		if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
			bpp = 2;
		else
			bpp = 3;	/* Default format set to RGB888 */

		ystride = width * bpp + 1;

		/* DSI_COMMAND_MODE_MDP_STREAM_CTRL */
		data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE;
		MIPI_OUTP(MIPI_DSI_BASE + 0x5c, data);
		MIPI_OUTP(MIPI_DSI_BASE + 0x54, data);

		/* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */
		data = height << 16 | width;
		MIPI_OUTP(MIPI_DSI_BASE + 0x60, data);
		MIPI_OUTP(MIPI_DSI_BASE + 0x58, data);
	}

	mipi_dsi_host_init(mipi);

	if (mipi->force_clk_lane_hs) {
		u32 tmp;

		tmp = MIPI_INP(MIPI_DSI_BASE + 0xA8);
		tmp |= (1<<28);
		MIPI_OUTP(MIPI_DSI_BASE + 0xA8, tmp);
		wmb();
	}

	if (mdp_rev >= MDP_REV_41)
		mutex_lock(&mfd->dma->ov_mutex);
	else
		down(&mfd->dma->mutex);

	ret = panel_next_on(pdev);

	mipi_dsi_op_mode_config(mipi->mode);

	if (mfd->panel_info.type == MIPI_CMD_PANEL) {
		if (pinfo->lcd.vsync_enable) {
			if (pinfo->lcd.hw_vsync_mode && vsync_gpio >= 0) {
				if (mdp_rev >= MDP_REV_41) {
					if (gpio_request(vsync_gpio,
						"MDP_VSYNC") == 0)
						gpio_direction_input(
							vsync_gpio);
					else
						pr_err("%s: unable to \
							request gpio=%d\n",
							__func__, vsync_gpio);
				} else if (mdp_rev == MDP_REV_303) {
					if (!tlmm_settings && gpio_request(
						vsync_gpio, "MDP_VSYNC") == 0) {
						ret = gpio_tlmm_config(
							GPIO_CFG(
							vsync_gpio, 1,
							GPIO_CFG_INPUT,
							GPIO_CFG_PULL_DOWN,
							GPIO_CFG_2MA),
							GPIO_CFG_ENABLE);

						if (ret) {
							pr_err(
							"%s: unable to config \
							tlmm = %d\n",
							__func__, vsync_gpio);
						}
						tlmm_settings = TRUE;

						gpio_direction_input(
							vsync_gpio);
					} else {
						if (!tlmm_settings) {
							pr_err(
							"%s: unable to request \
							gpio=%d\n",
							__func__, vsync_gpio);
						}
					}
				}
Exemple #10
0
static int mipi_dsi_off(struct platform_device *pdev)
{
	int ret = 0;
	struct msm_fb_data_type *mfd;
	struct msm_panel_info *pinfo;
	uint32 dsi_ctrl;

	mfd = platform_get_drvdata(pdev);
	pinfo = &mfd->panel_info;

	if (mdp_rev >= MDP_REV_41)
		mutex_lock(&mfd->dma->ov_mutex);
	else
		down(&mfd->dma->mutex);

	mdp4_overlay_dsi_state_set(ST_DSI_SUSPEND);

	/*
	 * Description: dsi clock is need to perform shutdown.
	 * mdp4_dsi_cmd_dma_busy_wait() will enable dsi clock if disabled.
	 * also, wait until dma (overlay and dmap) finish.
	 */
	if (mfd->panel_info.type == MIPI_CMD_PANEL) {
		if (mdp_rev >= MDP_REV_41) {
			mdp4_dsi_cmd_dma_busy_wait(mfd);
			mdp4_dsi_blt_dmap_busy_wait(mfd);
			mipi_dsi_mdp_busy_wait(mfd);
		} else {
			mdp3_dsi_cmd_dma_busy_wait(mfd);
		}
	} else {
		/* video mode, wait until fifo cleaned */
		mipi_dsi_controller_cfg(0);
	}

	/*
	 * Desctiption: change to DSI_CMD_MODE since it needed to
	 * tx DCS dsiplay off comamnd to panel
	 */
	mipi_dsi_op_mode_config(DSI_CMD_MODE);

	if (mfd->panel_info.type == MIPI_CMD_PANEL) {
		if (pinfo->lcd.vsync_enable) {
			if (pinfo->lcd.hw_vsync_mode && vsync_gpio >= 0) {
				if (MDP_REV_303 != mdp_rev)
					gpio_free(vsync_gpio);
			}
			mipi_dsi_set_tear_off(mfd);
		}
	}

	ret = panel_next_off(pdev);

#ifdef CONFIG_MSM_BUS_SCALING
	mdp_bus_scale_update_request(0);
#endif

	local_bh_disable();
	mipi_dsi_clk_disable();
	local_bh_enable();

	/* disbale dsi engine */
	dsi_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0000);
	dsi_ctrl &= ~0x01;
	MIPI_OUTP(MIPI_DSI_BASE + 0x0000, dsi_ctrl);

	mipi_dsi_phy_ctrl(0);


	local_bh_disable();
	mipi_dsi_ahb_ctrl(0);
	local_bh_enable();

	if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
		mipi_dsi_pdata->dsi_power_save(0);
#if defined(CONFIG_FB_MSM_MIPI_PANEL_POWERON_LP11)
	if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_client_power_save)
		mipi_dsi_pdata->dsi_client_power_save(0);
#endif /* CONFIG_FB_MSM_MIPI_PANEL_POWERON_LP11 */
	if (mdp_rev >= MDP_REV_41)
		mutex_unlock(&mfd->dma->ov_mutex);
	else
		up(&mfd->dma->mutex);

	pr_debug("%s-:\n", __func__);

	return ret;
}
Exemple #11
0
static int mipi_dsi_off(struct platform_device *pdev)
{
	int ret = 0;
	struct msm_fb_data_type *mfd;
	struct msm_panel_info *pinfo;
	uint32 dsi_ctrl;

	pr_debug("%s+:\n", __func__);

	mfd = platform_get_drvdata(pdev);
	pinfo = &mfd->panel_info;

	if (mdp_rev >= MDP_REV_41)
		mutex_lock(&mfd->dma->ov_mutex);
	else
		down(&mfd->dma->mutex);

	if (mfd->panel_info.type == MIPI_CMD_PANEL) {
		mipi_dsi_prepare_clocks();
		mipi_dsi_ahb_ctrl(1);
		mipi_dsi_clk_enable();

		/* make sure dsi_cmd_mdp is idle */
		mipi_dsi_cmd_mdp_busy();
	}

	/*
	 * Desctiption: change to DSI_CMD_MODE since it needed to
	 * tx DCS dsiplay off comamnd to panel
	 * mipi_dsi_op_mode_config(DSI_CMD_MODE);
	 */

	if (mfd->panel_info.type == MIPI_CMD_PANEL) {
		if (pinfo->lcd.vsync_enable) {
			if (pinfo->lcd.hw_vsync_mode && vsync_gpio >= 0) {
				if (MDP_REV_303 != mdp_rev)
					gpio_free(vsync_gpio);
			}
			mipi_dsi_set_tear_off(mfd);
		}
	}

	ret = panel_next_off(pdev);

	spin_lock_bh(&dsi_clk_lock);
	
	mipi_dsi_clk_disable();

	/* disbale dsi engine */
	dsi_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0000);
	dsi_ctrl &= ~0x01;
	MIPI_OUTP(MIPI_DSI_BASE + 0x0000, dsi_ctrl);

	MIPI_OUTP(MIPI_DSI_BASE + 0x010c, 0); /* DSI_INTL_CTRL */
	MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);

	mipi_dsi_phy_ctrl(0);

	mipi_dsi_ahb_ctrl(0);
	spin_unlock_bh(&dsi_clk_lock);

	mipi_dsi_unprepare_clocks();

	usleep(5000);

	if (mipi_dsi_pdata && mipi_dsi_pdata->active_reset)
		mipi_dsi_pdata->active_reset(0); /* low */

	if (mipi_dsi_pdata && mipi_dsi_pdata->panel_power_save)
		mipi_dsi_pdata->panel_power_save(0);

	if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
		mipi_dsi_pdata->dsi_power_save(0);

	if (mdp_rev >= MDP_REV_41)
		mutex_unlock(&mfd->dma->ov_mutex);
	else
		up(&mfd->dma->mutex);

	pr_debug("%s-:\n", __func__);

	return ret;
}
Exemple #12
0
static int mipi_dsi_on(struct platform_device *pdev)
{
	int ret = 0;
	u32 clk_rate;
	struct msm_fb_data_type *mfd;
	struct fb_info *fbi;
	struct fb_var_screeninfo *var;
	struct msm_panel_info *pinfo;
	struct mipi_panel_info *mipi;
	u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
	u32 ystride, bpp, data;
	u32 dummy_xres, dummy_yres;
	int target_type = 0;

	mfd = platform_get_drvdata(pdev);
	fbi = mfd->fbi;
	var = &fbi->var;
	pinfo = &mfd->panel_info;
	if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
		mipi_dsi_pdata->dsi_power_save(1);
#if defined(CONFIG_FB_MSM_MIPI_PANEL_POWERON_LP11)
	/*
	 * Fix for floating state of VDD line in toshiba chip
	 * */
	if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_client_power_save)
		mipi_dsi_pdata->dsi_client_power_save(1);
#endif /* CONFIG_FB_MSM_MIPI_PANEL_POWERON_LP11 */

	cont_splash_clk_ctrl();
	local_bh_disable();
	mipi_dsi_ahb_ctrl(1);
	local_bh_enable();

	clk_rate = mfd->fbi->var.pixclock;
	clk_rate = min(clk_rate, mfd->panel_info.clk_max);

	MIPI_OUTP(MIPI_DSI_BASE + 0x114, 1);
	MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0);

	hbp = var->left_margin;
	hfp = var->right_margin;
	vbp = var->upper_margin;
	vfp = var->lower_margin;
	hspw = var->hsync_len;
	vspw = var->vsync_len;
	width = mfd->panel_info.xres;
	height = mfd->panel_info.yres;

	mipi_dsi_phy_ctrl(1);

	if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata)
		target_type = mipi_dsi_pdata->target_type;

	mipi_dsi_phy_init(0, &(mfd->panel_info), target_type);

	local_bh_disable();
	mipi_dsi_clk_enable();
	local_bh_enable();

	mipi  = &mfd->panel_info.mipi;
	if (mfd->panel_info.type == MIPI_VIDEO_PANEL) {
		dummy_xres = mfd->panel_info.mipi.xres_pad;
		dummy_yres = mfd->panel_info.mipi.yres_pad;

		if (mdp_rev >= MDP_REV_41) {
			MIPI_OUTP(MIPI_DSI_BASE + 0x20,
				((hspw + hbp + width + dummy_xres) << 16 |
				(hspw + hbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x24,
				((vspw + vbp + height + dummy_yres) << 16 |
				(vspw + vbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x28,
				(vspw + vbp + height + dummy_yres +
					vfp - 1) << 16 | (hspw + hbp +
					width + dummy_xres + hfp - 1));
		} else {
			/* DSI_LAN_SWAP_CTRL */
			MIPI_OUTP(MIPI_DSI_BASE + 0x00ac, mipi->dlane_swap);

			MIPI_OUTP(MIPI_DSI_BASE + 0x20,
				((hbp + width + dummy_xres) << 16 | (hbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x24,
				((vbp + height + dummy_yres) << 16 | (vbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x28,
				(vbp + height + dummy_yres + vfp) << 16 |
					(hbp + width + dummy_xres + hfp));
		}

		MIPI_OUTP(MIPI_DSI_BASE + 0x2c, (hspw << 16));
		MIPI_OUTP(MIPI_DSI_BASE + 0x30, 0);
		MIPI_OUTP(MIPI_DSI_BASE + 0x34, (vspw << 16));

	} else {		/* command mode */
		if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
			bpp = 2;
		else
			bpp = 3;	/* Default format set to RGB888 */

		ystride = width * bpp + 1;

		/* DSI_COMMAND_MODE_MDP_STREAM_CTRL */
		data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE;
		MIPI_OUTP(MIPI_DSI_BASE + 0x5c, data);
		MIPI_OUTP(MIPI_DSI_BASE + 0x54, data);

		/* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */
		data = height << 16 | width;
		MIPI_OUTP(MIPI_DSI_BASE + 0x60, data);
		MIPI_OUTP(MIPI_DSI_BASE + 0x58, data);
	}

	mipi_dsi_host_init(mipi);
#if defined(CONFIG_FB_MSM_MIPI_PANEL_POWERON_LP11)
	/*
	 * For TC358764 D2L IC, one of the requirement for power on
	 * is to maintain an LP11 state in data and clock lanes during
	 * power enabling and reset assertion. This change is to
	 * achieve that.
	 * */
	if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_client_power_save) {
		u32 tmp_reg0c, tmp_rega8;
		mipi_dsi_pdata->dsi_client_reset();
		udelay(200);
		/* backup register values */
		tmp_reg0c = MIPI_INP(MIPI_DSI_BASE + 0x000c);
		tmp_rega8 = MIPI_INP(MIPI_DSI_BASE + 0xA8);
		/* Clear HS  mode assertion and related flags */
		MIPI_OUTP(MIPI_DSI_BASE + 0x0c, 0x8000);
		MIPI_OUTP(MIPI_DSI_BASE + 0xA8, 0x0);
		wmb();
		mdelay(5);
		/* restore previous values */
		MIPI_OUTP(MIPI_DSI_BASE + 0x0c, tmp_reg0c);
		MIPI_OUTP(MIPI_DSI_BASE + 0xa8, tmp_rega8);
		wmb();
	}
#endif /* CONFIG_FB_MSM_MIPI_PANEL_POWERON_LP11 */


	if (mipi->force_clk_lane_hs) {
		u32 tmp;

		tmp = MIPI_INP(MIPI_DSI_BASE + 0xA8);
		tmp |= (1<<28);
		MIPI_OUTP(MIPI_DSI_BASE + 0xA8, tmp);
		wmb();
	}

	if (mdp_rev >= MDP_REV_41)
		mutex_lock(&mfd->dma->ov_mutex);
	else
		down(&mfd->dma->mutex);

	ret = panel_next_on(pdev);

	mipi_dsi_op_mode_config(mipi->mode);

	if (mfd->panel_info.type == MIPI_CMD_PANEL) {
		if (pinfo->lcd.vsync_enable) {
			if (pinfo->lcd.hw_vsync_mode && vsync_gpio >= 0) {
				if (mdp_rev >= MDP_REV_41) {
					if (gpio_request(vsync_gpio,
						"MDP_VSYNC") == 0)
						gpio_direction_input(
							vsync_gpio);
					else
						pr_err("%s: unable to request gpio=%d\n",
							__func__, vsync_gpio);
				} else if (mdp_rev == MDP_REV_303) {
					if (!tlmm_settings && gpio_request(
						vsync_gpio, "MDP_VSYNC") == 0) {
						ret = gpio_tlmm_config(
							GPIO_CFG(
							vsync_gpio, 1,
							GPIO_CFG_INPUT,
							GPIO_CFG_PULL_DOWN,
							GPIO_CFG_2MA),
							GPIO_CFG_ENABLE);

						if (ret) {
							pr_err("%s: unable to config tlmm = %d\n",
							__func__, vsync_gpio);
						}
						tlmm_settings = TRUE;

						gpio_direction_input(
							vsync_gpio);
					} else {
						if (!tlmm_settings) {
							pr_err("%s: unable to request gpio=%d\n",
							__func__, vsync_gpio);
						}
					}
				}
			}
			mipi_dsi_set_tear_on(mfd);
		}
	}

#ifdef CONFIG_MSM_BUS_SCALING
	mdp_bus_scale_update_request(2);
#endif

	mdp4_overlay_dsi_state_set(ST_DSI_RESUME);

	if (mdp_rev >= MDP_REV_41)
		mutex_unlock(&mfd->dma->ov_mutex);
	else
		up(&mfd->dma->mutex);

	pr_debug("%s-:\n", __func__);

	return ret;
}
void mdss_dsi_phy_init(struct mdss_panel_data *pdata)
{
	struct mdss_dsi_phy_ctrl *pd;
	int i, off, ln, offset;
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL, *temp_ctrl = NULL;

	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
				panel_data);
	if (!ctrl_pdata) {
		pr_err("%s: Invalid input data\n", __func__);
		return;
	}
	temp_ctrl = ctrl_pdata;

	pd = &(((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db);

	/* Strength ctrl 0 */
	MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0184, pd->strength[0]);

	/*
	 * Phy regulator ctrl settings.
	 * In dual dsi configuration, the second controller also uses
	 * the regulators of the first controller, irrespective of whether
	 * broadcast mode is enabled or not.
	 */
	if (ctrl_pdata->ndx == DSI_CTRL_1) {
		temp_ctrl = mdss_dsi_get_ctrl_by_index(DSI_CTRL_0);
		if (!temp_ctrl) {
			pr_err("%s: Unable to get master ctrl\n", __func__);
			return;
		}
	}

	if (pd->reg_ldo_mode) {
		/* Regulator ctrl 0 */
		MIPI_OUTP((temp_ctrl->phy_io.base) + 0x280, 0x0);
		/* Regulator ctrl - CAL_PWR_CFG */
		MIPI_OUTP((temp_ctrl->phy_io.base) + 0x298, pd->regulator[6]);
		/* Add H/w recommended delay */
		udelay(1000);
		/* Regulator ctrl - TEST */
		MIPI_OUTP((temp_ctrl->phy_io.base) + 0x294, pd->regulator[5]);
		/* Regulator ctrl 3 */
		MIPI_OUTP((temp_ctrl->phy_io.base) + 0x28c, pd->regulator[3]);
		/* Regulator ctrl 2 */
		MIPI_OUTP((temp_ctrl->phy_io.base) + 0x288, pd->regulator[2]);
		/* Regulator ctrl 1 */
		MIPI_OUTP((temp_ctrl->phy_io.base) + 0x284, pd->regulator[1]);
		/* Regulator ctrl 4 */
		MIPI_OUTP((temp_ctrl->phy_io.base) + 0x290, pd->regulator[4]);
		/* LDO ctrl */
		if (MIPI_INP(ctrl_pdata->ctrl_base) == MDSS_DSI_HW_REV_103_1)
			MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x1dc, 0x05);
		else
			MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x1dc, 0x0d);
	} else {
		/* Regulator ctrl 0 */
		MIPI_OUTP((temp_ctrl->phy_io.base) + 0x280, 0x0);
		/* Regulator ctrl - CAL_PWR_CFG */
		MIPI_OUTP((temp_ctrl->phy_io.base) + 0x298, pd->regulator[6]);
		/* Add H/w recommended delay */
		udelay(1000);
		/* Regulator ctrl 1 */
		MIPI_OUTP((temp_ctrl->phy_io.base) + 0x284, pd->regulator[1]);
		/* Regulator ctrl 2 */
		MIPI_OUTP((temp_ctrl->phy_io.base) + 0x288, pd->regulator[2]);
		/* Regulator ctrl 3 */
		MIPI_OUTP((temp_ctrl->phy_io.base) + 0x28c, pd->regulator[3]);
		/* Regulator ctrl 4 */
		MIPI_OUTP((temp_ctrl->phy_io.base) + 0x290, pd->regulator[4]);
		/* LDO ctrl */
		MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x1dc, 0x00);
		/* Regulator ctrl 0 */
		MIPI_OUTP((temp_ctrl->phy_io.base) + 0x280, pd->regulator[0]);
	}

	off = 0x0140;	/* phy timing ctrl 0 - 11 */
	for (i = 0; i < 12; i++) {
		MIPI_OUTP((ctrl_pdata->phy_io.base) + off, pd->timing[i]);
		wmb();
		off += 4;
	}

	/* MMSS_DSI_0_PHY_DSIPHY_CTRL_1 */
	MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0174, 0x00);
	/* MMSS_DSI_0_PHY_DSIPHY_CTRL_0 */
	MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0170, 0x5f);
	wmb();

	/* Strength ctrl 1 */
	MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0188, pd->strength[1]);
	wmb();

	/* 4 lanes + clk lane configuration */
	/* lane config n * (0 - 4) & DataPath setup */
	for (ln = 0; ln < 5; ln++) {
		off = (ln * 0x40);
		for (i = 0; i < 9; i++) {
			offset = i + (ln * 9);
			MIPI_OUTP((ctrl_pdata->phy_io.base) + off,
							pd->lanecfg[offset]);
			wmb();
			off += 4;
		}
	}

	/* MMSS_DSI_0_PHY_DSIPHY_CTRL_0 */
	MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0170, 0x5f);
	wmb();

	/* DSI_0_PHY_DSIPHY_GLBL_TEST_CTRL */
	if ((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1)
		MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x01d4, 0x01);
	else
		MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x01d4, 0x00);
	wmb();

	off = 0x01b4;	/* phy BIST ctrl 0 - 5 */
	for (i = 0; i < 6; i++) {
		MIPI_OUTP((ctrl_pdata->phy_io.base) + off, pd->bistctrl[i]);
		wmb();
		off += 4;
	}

}
Exemple #14
0
static int mipi_dsi_on(struct platform_device *pdev)
{
	int ret = 0;
	u32 clk_rate;
	struct msm_fb_data_type *mfd;
	struct fb_info *fbi;
	struct fb_var_screeninfo *var;
	struct msm_panel_info *pinfo;
	struct mipi_panel_info *mipi;
	u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
	u32 ystride, bpp, data;
	u32 dummy_xres, dummy_yres;
	int target_type = 0;

	printk("%s+:\n", __func__);

	mfd = platform_get_drvdata(pdev);
	fbi = mfd->fbi;
	var = &fbi->var;
	pinfo = &mfd->panel_info;
	esc_byte_ratio = pinfo->mipi.esc_byte_ratio;


	if (mfd->first_init_lcd == 0) {
		if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
			mipi_dsi_pdata->dsi_power_save(1);
	}

	cont_splash_clk_ctrl(0);
	mipi_dsi_prepare_clocks();

	mipi_dsi_ahb_ctrl(1);

	clk_rate = mfd->fbi->var.pixclock;
	clk_rate = min(clk_rate, mfd->panel_info.clk_max);

	mipi_dsi_phy_ctrl(1);

	if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata)
		target_type = mipi_dsi_pdata->target_type;

	mipi_dsi_phy_init(0, &(mfd->panel_info), target_type);

	mipi_dsi_clk_enable();

	MIPI_OUTP(MIPI_DSI_BASE + 0x114, 1);
	MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0);

	hbp = var->left_margin;
	hfp = var->right_margin;
	vbp = var->upper_margin;
	vfp = var->lower_margin;
	hspw = var->hsync_len;
	vspw = var->vsync_len;
	width = mfd->panel_info.xres;
	height = mfd->panel_info.yres;

	mipi  = &mfd->panel_info.mipi;
	if (mfd->panel_info.type == MIPI_VIDEO_PANEL) {
		dummy_xres = mfd->panel_info.lcdc.xres_pad;
		dummy_yres = mfd->panel_info.lcdc.yres_pad;

		if (mdp_rev >= MDP_REV_41) {
			MIPI_OUTP(MIPI_DSI_BASE + 0x20,
				((hspw + hbp + width + dummy_xres) << 16 |
				(hspw + hbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x24,
				((vspw + vbp + height + dummy_yres) << 16 |
				(vspw + vbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x28,
				(vspw + vbp + height + dummy_yres +
					vfp - 1) << 16 | (hspw + hbp +
					width + dummy_xres + hfp - 1));
		} else {
			
			MIPI_OUTP(MIPI_DSI_BASE + 0x00ac,
						mipi_dsi_pdata->dlane_swap);

			MIPI_OUTP(MIPI_DSI_BASE + 0x20,
				((hbp + width + dummy_xres) << 16 | (hbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x24,
				((vbp + height + dummy_yres) << 16 | (vbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x28,
				(vbp + height + dummy_yres + vfp) << 16 |
					(hbp + width + dummy_xres + hfp));
		}

		MIPI_OUTP(MIPI_DSI_BASE + 0x2c, (hspw << 16));
		MIPI_OUTP(MIPI_DSI_BASE + 0x30, 0);
		MIPI_OUTP(MIPI_DSI_BASE + 0x34, (vspw << 16));

	} else {		
		if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
			bpp = 2;
		else
			bpp = 3;	

		ystride = width * bpp + 1;

		
		data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE;
		MIPI_OUTP(MIPI_DSI_BASE + 0x5c, data);
		MIPI_OUTP(MIPI_DSI_BASE + 0x54, data);

		
		data = height << 16 | width;
		MIPI_OUTP(MIPI_DSI_BASE + 0x60, data);
		MIPI_OUTP(MIPI_DSI_BASE + 0x58, data);
	}

	mipi_dsi_host_init(mipi, mipi_dsi_pdata->dlane_swap);

	if (mipi->force_clk_lane_hs) {
		u32 tmp;

		tmp = MIPI_INP(MIPI_DSI_BASE + 0xA8);
		tmp |= (1<<28);
		MIPI_OUTP(MIPI_DSI_BASE + 0xA8, tmp);
		wmb();
	}

#if defined(CONFIG_MACH_DUMMY)
	if ((panel_type == PANEL_ID_PROTODCG_SHARP || panel_type == PANEL_ID_PROTODCG_SHARP_C1) &&
		mfd->first_init_lcd != 0) {
		protodcg_orise_lcd_pre_off(pdev);
		if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
			mipi_dsi_pdata->dsi_power_save(1);
	}
#elif defined(CONFIG_MACH_PROTOU)
	if ((panel_type == PANEL_ID_PROTOU_SHARP || panel_type == PANEL_ID_PROTOU_SHARP_C1) &&
		mfd->first_init_lcd != 0) {
		
		protou_orise_lcd_pre_off(pdev);
		if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
			mipi_dsi_pdata->dsi_power_save(1);
	}
#endif
	if (panel_type == PANEL_ID_URANUS_SONY_ORISE) {
		if(mfd->first_init_lcd != 0) {
			if (mipi_dsi_pdata && mipi_dsi_pdata->lcd_pre_off)
				mipi_dsi_pdata->lcd_pre_off(pdev);
			if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
				mipi_dsi_pdata->dsi_power_save(1);
		}

	}

	ret = panel_next_on(pdev);

	mipi_dsi_op_mode_config(mipi->mode);

	if (mfd->panel_info.type == MIPI_CMD_PANEL) {
		if (pinfo->lcd.vsync_enable) {
			if (pinfo->lcd.hw_vsync_mode && vsync_gpio >= 0) {
				if (mdp_rev >= MDP_REV_41) {
					if (gpio_request(vsync_gpio,
						"MDP_VSYNC") == 0)
						gpio_direction_input(
							vsync_gpio);
					else
						pr_err("%s: unable to \
							request gpio=%d\n",
							__func__, vsync_gpio);
				} else if (mdp_rev == MDP_REV_303) {
					if (!tlmm_settings && gpio_request(
						vsync_gpio, "MDP_VSYNC") == 0) {
						ret = gpio_tlmm_config(
							GPIO_CFG(
							vsync_gpio, 1,
							GPIO_CFG_INPUT,
							GPIO_CFG_PULL_DOWN,
							GPIO_CFG_2MA),
							GPIO_CFG_ENABLE);

						if (ret) {
							pr_err(
							"%s: unable to config \
							tlmm = %d\n",
							__func__, vsync_gpio);
						}
						tlmm_settings = TRUE;

						gpio_direction_input(
							vsync_gpio);
					} else {
						if (!tlmm_settings) {
							pr_err(
							"%s: unable to request \
							gpio=%d\n",
							__func__, vsync_gpio);
						}
					}
				}
Exemple #15
0
int mdss_dsi_on(struct mdss_panel_data *pdata)
{
	int ret = 0;
	struct mdss_panel_info *pinfo;
	struct mipi_panel_info *mipi;
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;

	if (pdata == NULL) {
		pr_err("%s: Invalid input data\n", __func__);
		return -EINVAL;
	}

	if (pdata->panel_info.panel_power_on) {
		pr_warn("%s:%d Panel already on.\n", __func__, __LINE__);
		return 0;
	}

	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
				panel_data);

	pr_debug("%s+: ctrl=%p ndx=%d\n",
				__func__, ctrl_pdata, ctrl_pdata->ndx);

	pinfo = &pdata->panel_info;
	mipi = &pdata->panel_info.mipi;

	ret = mdss_dsi_panel_power_on(pdata, 1);
	if (ret) {
		pr_err("%s:Panel power on failed. rc=%d\n", __func__, ret);
		return ret;
	}

	mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 1);
	if (ret) {
		pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__,
			ret);
		ret = mdss_dsi_panel_power_on(pdata, 0);
		if (ret) {
			pr_err("%s: Panel reset failed. rc=%d\n",
					__func__, ret);
			return ret;
		}
		pdata->panel_info.panel_power_on = 0;
		return ret;
	}
	pdata->panel_info.panel_power_on = 1;

	mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base));
	mdss_dsi_phy_init(pdata);
	mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 0);

	mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);

	__mdss_dsi_ctrl_setup(pdata);
	mdss_dsi_sw_reset(pdata);
	mdss_dsi_host_init(pdata);

	/*
	 * Issue hardware reset line after enabling the DSI clocks and data
	 * data lanes for LP11 init
	 */
	if (mipi->lp11_init)
		mdss_dsi_panel_reset(pdata, 1);

	if (mipi->init_delay)
		usleep(mipi->init_delay);

	if (mipi->force_clk_lane_hs) {
		u32 tmp;

		tmp = MIPI_INP((ctrl_pdata->ctrl_base) + 0xac);
		tmp |= (1<<28);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0xac, tmp);
		wmb();
	}

	if (pdata->panel_info.type == MIPI_CMD_PANEL)
		mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0);

	pr_debug("%s-:\n", __func__);
	return 0;
}
int mdss_dsi_on(struct mdss_panel_data *pdata)
{
	int ret = 0;
	u32 clk_rate;
	struct mdss_panel_info *pinfo;
	struct mipi_panel_info *mipi;
	u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
	u32 ystride, bpp, data, dst_bpp;
	u32 dummy_xres, dummy_yres;
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
	u32 hsync_period, vsync_period;

	if (pdata == NULL) {
		pr_err("%s: Invalid input data\n", __func__);
		return -EINVAL;
	}

	if (pdata->panel_info.panel_power_on) {
		pr_warn("%s:%d Panel already on.\n", __func__, __LINE__);
		return 0;
	}

	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
				panel_data);

	pr_debug("%s+: ctrl=%p ndx=%d\n",
				__func__, ctrl_pdata, ctrl_pdata->ndx);

	pinfo = &pdata->panel_info;

    //ASUS_BSP: Louis for display miniporting +++
#if 0
	ret = msm_dss_enable_vreg(ctrl_pdata->power_data.vreg_config,
				ctrl_pdata->power_data.num_vreg, 1);

	if (ret) {
		pr_err("%s:Failed to enable vregs. rc=%d\n", __func__, ret);
		return ret;
	}
#else
    ret = a90_mdss_dsi_panel_power_on(pdata, 1);
    
	if (ret) {
		pr_err("%s: Panel power on failed\n", __func__);
		return ret;
	}
#endif
//ASUS_BSP: Louis for display miniporting ---

	pdata->panel_info.panel_power_on = 1;

	if (!pdata->panel_info.mipi.lp11_init)
		mdss_dsi_panel_reset(pdata, 1);

	ret = mdss_dsi_enable_bus_clocks(ctrl_pdata);
	if (ret) {
		pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__,
			ret);
        //ASUS_BSP: Louis for display porting ++
		//mdss_dsi_panel_power_on(pdata, 0);
//#ifdef ASUS_A91_PROJECT
        a90_mdss_dsi_panel_power_on(pdata, 0);
//#elif defined ASUS_ME771KL_PROJECT
//        me771_mdss_dsi_panel_power_on(pdata, 0);
//#endif
        //ASUS_BSP: Louis for display porting --
		
		pdata->panel_info.panel_power_on = 0;

		return ret;
	}

	mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base));
	mdss_dsi_phy_init(pdata);
	mdss_dsi_disable_bus_clocks(ctrl_pdata);

	mdss_dsi_clk_ctrl(ctrl_pdata, 1);

	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);

	hbp = mult_frac(pdata->panel_info.lcdc.h_back_porch, dst_bpp,
			pdata->panel_info.bpp);
	hfp = mult_frac(pdata->panel_info.lcdc.h_front_porch, dst_bpp,
			pdata->panel_info.bpp);
	vbp = mult_frac(pdata->panel_info.lcdc.v_back_porch, dst_bpp,
			pdata->panel_info.bpp);
	vfp = mult_frac(pdata->panel_info.lcdc.v_front_porch, dst_bpp,
			pdata->panel_info.bpp);
	hspw = mult_frac(pdata->panel_info.lcdc.h_pulse_width, dst_bpp,
			pdata->panel_info.bpp);
	vspw = pdata->panel_info.lcdc.v_pulse_width;
	width = mult_frac(pdata->panel_info.xres, dst_bpp,
			pdata->panel_info.bpp);
	height = pdata->panel_info.yres;

	if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
		dummy_xres = pdata->panel_info.lcdc.xres_pad;
		dummy_yres = pdata->panel_info.lcdc.yres_pad;
	}

	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) {
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x24,
			((hspw + hbp + width + dummy_xres) << 16 |
			(hspw + hbp)));
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x28,
			((vspw + vbp + height + dummy_yres) << 16 |
			(vspw + vbp)));
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C,
				((vsync_period - 1) << 16)
				| (hsync_period - 1));

		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x30, (hspw << 16));
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x34, 0);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x38, (vspw << 16));

	} else {		/* command mode */
		if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
			bpp = 2;
		else
			bpp = 3;	/* Default format set to RGB888 */

		ystride = width * bpp + 1;

		/* DSI_COMMAND_MODE_MDP_STREAM_CTRL */
		data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE;
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x60, data);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x58, data);

		/* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */
		data = height << 16 | width;
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x64, data);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x5C, data);
	}

	mdss_dsi_sw_reset(pdata);
	mdss_dsi_host_init(mipi, pdata);

	/*
	 * Issue hardware reset line after enabling the DSI clocks and data
	 * data lanes for LP11 init
	 */
	if (pdata->panel_info.mipi.lp11_init)
		mdss_dsi_panel_reset(pdata, 1);

	if (pdata->panel_info.mipi.init_delay)
		usleep(pdata->panel_info.mipi.init_delay);

	if (mipi->force_clk_lane_hs) {
		u32 tmp;

		tmp = MIPI_INP((ctrl_pdata->ctrl_base) + 0xac);
		tmp |= (1<<28);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0xac, tmp);
		wmb();
	}

	if (pdata->panel_info.type == MIPI_CMD_PANEL)
		mdss_dsi_clk_ctrl(ctrl_pdata, 0);

	pr_debug("%s-:\n", __func__);
	return 0;
}
Exemple #17
0
static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps)
{
	int rc = 0;
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
	u32 dsi_ctrl;

	pr_debug("%s+:\n", __func__);

	if (pdata == NULL) {
		pr_err("%s: Invalid input data\n", __func__);
		return -EINVAL;
	}

	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
				panel_data);

	if (!ctrl_pdata->panel_data.panel_info.dynamic_fps) {
		pr_err("%s: Dynamic fps not enabled for this panel\n",
					__func__);
		return -EINVAL;
	}

	if (new_fps !=
		ctrl_pdata->panel_data.panel_info.mipi.frame_rate) {
		if (pdata->panel_info.dfps_update
			== DFPS_IMMEDIATE_PORCH_UPDATE_MODE) {
			u32 hsync_period, vsync_period;
			u32 new_dsi_v_total, current_dsi_v_total;
			vsync_period =
				mdss_panel_get_vtotal(&pdata->panel_info);
			hsync_period =
				mdss_panel_get_htotal(&pdata->panel_info);
			current_dsi_v_total =
				MIPI_INP((ctrl_pdata->ctrl_base) + 0x2C);
			new_dsi_v_total =
				((vsync_period - 1) << 16) | (hsync_period - 1);
			MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C,
				(current_dsi_v_total | 0x8000000));
			if (new_dsi_v_total & 0x8000000) {
				MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C,
					new_dsi_v_total);
			} else {
				MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C,
					(new_dsi_v_total | 0x8000000));
				MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C,
					(new_dsi_v_total & 0x7ffffff));
			}
			pdata->panel_info.mipi.frame_rate = new_fps;
		} else {
			rc = mdss_dsi_clk_div_config
				(&ctrl_pdata->panel_data.panel_info, new_fps);
			if (rc) {
				pr_err("%s: unable to initialize the clk dividers\n",
								__func__);
				return rc;
			}
			ctrl_pdata->pclk_rate =
				pdata->panel_info.mipi.dsi_pclk_rate;
			ctrl_pdata->byte_clk_rate =
				pdata->panel_info.clk_rate / 8;

			if (pdata->panel_info.dfps_update
					== DFPS_IMMEDIATE_CLK_UPDATE_MODE) {
				dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) +
						    0x0004);
				pdata->panel_info.mipi.frame_rate = new_fps;
				dsi_ctrl &= ~0x2;
				MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004,
								dsi_ctrl);
				mdss_dsi_controller_cfg(true, pdata);
				mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0);
				mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
				dsi_ctrl |= 0x2;
				MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004,
								dsi_ctrl);
			}
		}
	} else {
		pr_debug("%s: Panel is already at this FPS\n", __func__);
	}

	return rc;
}
Exemple #18
0
irqreturn_t mdss_dsi_isr(int irq, void *ptr)
{
	u32 isr;
	struct mdss_dsi_ctrl_pdata *ctrl =
			(struct mdss_dsi_ctrl_pdata *)ptr;

	if (!ctrl->ctrl_base)
		pr_err("%s:%d DSI base adr no Initialized",
				       __func__, __LINE__);

	isr = MIPI_INP(ctrl->ctrl_base + 0x0110);/* DSI_INTR_CTRL */
	MIPI_OUTP(ctrl->ctrl_base + 0x0110, isr);

	if (ctrl->shared_pdata.broadcast_enable)
		if ((ctrl->panel_data.panel_info.pdest == DISPLAY_2)
		    && (left_ctrl_pdata != NULL)) {
			u32 isr0;
			isr0 = MIPI_INP(left_ctrl_pdata->ctrl_base
						+ 0x0110);/* DSI_INTR_CTRL */
			if (isr0 & DSI_INTR_CMD_DMA_DONE)
				MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0110,
					DSI_INTR_CMD_DMA_DONE);
		}

	pr_debug("%s: ndx=%d isr=%x\n", __func__, ctrl->ndx, isr);

	if (isr & DSI_INTR_ERROR) {
		MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x97);
		pr_err("%s: ndx=%d isr=%x\n", __func__, ctrl->ndx, isr);
		mdss_dsi_error(ctrl);
	}

	if (isr & DSI_INTR_VIDEO_DONE) {
		spin_lock(&ctrl->mdp_lock);
		mdss_dsi_disable_irq_nosync(ctrl, DSI_VIDEO_TERM);
		complete(&ctrl->video_comp);
		spin_unlock(&ctrl->mdp_lock);
	}

	if (isr & DSI_INTR_CMD_DMA_DONE) {
		MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x98);
		spin_lock(&ctrl->mdp_lock);
		mdss_dsi_disable_irq_nosync(ctrl, DSI_CMD_TERM);
		complete(&ctrl->dma_comp);
		spin_unlock(&ctrl->mdp_lock);
	}

	if (isr & DSI_INTR_CMD_MDP_DONE) {
		MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x99);
		spin_lock(&ctrl->mdp_lock);
		ctrl->mdp_busy = false;
		mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM);
		complete(&ctrl->mdp_comp);
		spin_unlock(&ctrl->mdp_lock);
	}

	if (isr & DSI_INTR_BTA_DONE) {
		spin_lock(&ctrl->mdp_lock);
		mdss_dsi_disable_irq_nosync(ctrl, DSI_BTA_TERM);
		complete(&ctrl->bta_comp);
		spin_unlock(&ctrl->mdp_lock);
	}

	return IRQ_HANDLED;
}
Exemple #19
0
int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl,
			struct dsi_cmd_desc *cmds, int rlen, u32 rx_flags)
{
	int cnt, len, diff, pkt_size;
	struct dsi_buf *tp, *rp;
	int no_max_pkt_size;
	char cmd;
	u32 dsi_ctrl;
	u32 data;
	int video_mode;

	no_max_pkt_size = rx_flags & CMD_REQ_NO_MAX_PKT_SIZE;
	if (no_max_pkt_size)
		rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */

	len = rlen;
	diff = 0;

	if (len <= 2)
		cnt = 4;	/* short read */
	else {
		if (len > MDSS_DSI_LEN)
			len = MDSS_DSI_LEN;	/* 8 bytes at most */

		len = ALIGN(len, 4); /* len 4 bytes align */
		diff = len - rlen;
		/*
		 * add extra 2 bytes to len to have overall
		 * packet size is multipe by 4. This also make
		 * sure 4 bytes dcs headerlocates within a
		 * 32 bits register after shift in.
		 * after all, len should be either 6 or 10.
		 */
		len += 2;
		cnt = len + 6; /* 4 bytes header + 2 bytes crc */
	}

	dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004);
	video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
	if (video_mode) {
		data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
		MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data);
	}

	tp = &ctrl->tx_buf;
	rp = &ctrl->rx_buf;

	if (!no_max_pkt_size) {
		/* packet size need to be set at every read */
		pkt_size = len;
		max_pktsize[0] = pkt_size;
		mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
		mdss_dsi_buf_init(tp);
		mdss_dsi_cmd_dma_add(tp, &pkt_size_cmd);
		mdss_dsi_cmd_dma_tx(ctrl, tp);
		pr_debug("%s: Max packet size sent\n", __func__);
	}

	mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
	mdss_dsi_buf_init(tp);
	mdss_dsi_cmd_dma_add(tp, cmds);

	/* transmit read comamnd to client */
	mdss_dsi_cmd_dma_tx(ctrl, tp);
	/*
	 * once cmd_dma_done interrupt received,
	 * return data from client is ready and stored
	 * at RDBK_DATA register already
	 */
	mdss_dsi_buf_init(rp);
	if (no_max_pkt_size) {
		/*
		 * expect rlen = n * 4
		 * short alignement for start addr
		 */
		rp->data += 2;
	}

	mdss_dsi_cmd_dma_rx(ctrl, rp, cnt);

	if (video_mode)
		MIPI_OUTP((ctrl->ctrl_base) + 0x0004, dsi_ctrl); /* restore */
		
	if (no_max_pkt_size) {
		/*
		 * remove extra 2 bytes from previous
		 * rx transaction at shift register
		 * which was inserted during copy
		 * shift registers to rx buffer
		 * rx payload start from long alignment addr
		 */
		rp->data += 2;
	}

	cmd = rp->data[0];
	switch (cmd) {
	case DTYPE_ACK_ERR_RESP:
		pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
		break;
	case DTYPE_GEN_READ1_RESP:
	case DTYPE_DCS_READ1_RESP:
		mdss_dsi_short_read1_resp(rp);
		break;
	case DTYPE_GEN_READ2_RESP:
	case DTYPE_DCS_READ2_RESP:
		mdss_dsi_short_read2_resp(rp);
		break;
	case DTYPE_GEN_LREAD_RESP:
	case DTYPE_DCS_LREAD_RESP:
		mdss_dsi_long_read_resp(rp);
		rp->len -= 2; /* extra 2 bytes added */
		rp->len -= diff; /* align bytes */
		break;
	default:
		pr_debug("%s: Unknown cmd received\n", __func__);
		break;
	}

	return rp->len;
}
void dumpreg(void)
{
	u32 tmp0x0,tmp0x4,tmp0x8,tmp0xc;
	int i;

	if (dsi_ctrl_base == NULL) {
		pr_err("%s : dsi_ctrl_base is null!!..\n",__func__);
		return;
	}		

	pr_err("%s: =============DSI Reg DUMP==============\n", __func__);
#if defined (CONFIG_FB_MSM_MIPI_SAMSUNG_OCTA_CMD_WQHD_PT_PANEL)
	if (left_ctrl_pdata) {
		for (i=0; i< 91; i++) {
			tmp0x0 = MIPI_INP(left_ctrl_pdata->ctrl_base+(i*16)+0x0);
			tmp0x4 = MIPI_INP(left_ctrl_pdata->ctrl_base+(i*16)+0x4);
			tmp0x8 = MIPI_INP(left_ctrl_pdata->ctrl_base+(i*16)+0x8);
			tmp0xc = MIPI_INP(left_ctrl_pdata->ctrl_base+(i*16)+0xc);

			pr_err("[DSI0][%04x] : %08x %08x %08x %08x\n",i*16, tmp0x0,tmp0x4,tmp0x8,tmp0xc);
		}
	}
	for (i=0; i< 91; i++) {
		tmp0x0 = MIPI_INP(dsi_ctrl_base+(i*16)+0x0);
		tmp0x4 = MIPI_INP(dsi_ctrl_base+(i*16)+0x4);
		tmp0x8 = MIPI_INP(dsi_ctrl_base+(i*16)+0x8);
		tmp0xc = MIPI_INP(dsi_ctrl_base+(i*16)+0xc);

		pr_err("[DSI1][%04x] : %08x %08x %08x %08x\n",i*16, tmp0x0,tmp0x4,tmp0x8,tmp0xc);
	}
#else
	for(i=0; i< 91; i++){
		tmp0x0 = MIPI_INP(dsi_ctrl_base+(i*16)+0x0);
		tmp0x4 = MIPI_INP(dsi_ctrl_base+(i*16)+0x4);
		tmp0x8 = MIPI_INP(dsi_ctrl_base+(i*16)+0x8);
		tmp0xc = MIPI_INP(dsi_ctrl_base+(i*16)+0xc);

		pr_err("[%04x] : %08x %08x %08x %08x\n",i*16, tmp0x0,tmp0x4,tmp0x8,tmp0xc);
	}
#endif
	pr_err("%s: ============= END ==============\n", __func__);
}
static int mipi_dsi_on(struct platform_device *pdev)
{
	int ret = 0;
	u32 clk_rate;
	struct msm_fb_data_type *mfd;
	struct fb_info *fbi;
	struct fb_var_screeninfo *var;
	struct msm_panel_info *pinfo;
	struct mipi_panel_info *mipi;
	u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
	u32 ystride, bpp, data;
	u32 dummy_xres, dummy_yres;
	int target_type = 0;
	u32 tmp;
#if defined(CONFIG_FB_MSM_MIPI_RENESAS_TFT_VIDEO_FULL_HD_PT_PANEL)
	static int is_booting = 1;
#endif

#ifdef CONFIG_FB_MSM_LCD_NOTIFY
	lcd_notifier_call_chain(LCD_EVENT_ON_START, NULL);
#endif
	pr_debug("%s+:\n", __func__);

#if defined(CONFIG_MIPI_SAMSUNG_ESD_REFRESH) || defined(CONFIG_ESD_ERR_FG_RECOVERY)
	pdev_for_esd = pdev;
#endif
#if defined (CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_QHD_PT)
	if (get_lcd_attached() == 0)
		return ENODEV;
#endif
	mfd = platform_get_drvdata(pdev);
	fbi = mfd->fbi;
	var = &fbi->var;
	pinfo = &mfd->panel_info;
	esc_byte_ratio = pinfo->mipi.esc_byte_ratio;

	if (mipi_dsi_pdata && mipi_dsi_pdata->power_common)
		mipi_dsi_pdata->power_common();

#if defined(CONFIG_SUPPORT_SECOND_POWER)
#if defined(CONFIG_FB_MSM_MIPI_RENESAS_TFT_VIDEO_FULL_HD_PT_PANEL)
	if( is_booting == 1 )
	{
		is_booting = 0;
#if defined(CONFIG_MACH_JACTIVE_ATT) || defined(CONFIG_MACH_JACTIVE_EUR)
		usleep(5000);
		if (mipi_dsi_pdata && mipi_dsi_pdata->active_reset)
				mipi_dsi_pdata->active_reset(0); /* low */
		usleep(2000);

		if (mipi_dsi_pdata && mipi_dsi_pdata->panel_power_save)
			mipi_dsi_pdata->panel_power_save(0);
		msleep(10);
#endif
	}
#endif

	if (mipi_dsi_pdata && mipi_dsi_pdata->panel_power_save)
		mipi_dsi_pdata->panel_power_save(1);
#endif

#if !defined(CONFIG_SEC_PRODUCT_8930) && !defined(CONFIG_SEC_PRODUCT_8960)
	if (system_rev == 6)
		mdelay(500);
#endif

	if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
		mipi_dsi_pdata->dsi_power_save(1);

	cont_splash_clk_ctrl(0);
	mipi_dsi_prepare_clocks();

	mipi_dsi_ahb_ctrl(1);

	clk_rate = mfd->fbi->var.pixclock;
	clk_rate = min(clk_rate, mfd->panel_info.clk_max);

	mipi_dsi_phy_ctrl(1);

	if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata)
		target_type = mipi_dsi_pdata->target_type;

	mipi_dsi_phy_init(0, &(mfd->panel_info), target_type);

	mipi_dsi_clk_enable();
#if defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_QHD_PT_PANEL)
	mipi_dsi_configure_dividers(60);
#endif


	MIPI_OUTP(MIPI_DSI_BASE + 0x114, 1);
	MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0);

	hbp = var->left_margin;
	hfp = var->right_margin;
	vbp = var->upper_margin;
	vfp = var->lower_margin;
	hspw = var->hsync_len;
	vspw = var->vsync_len;
	width = mfd->panel_info.xres;
	height = mfd->panel_info.yres;

	mipi  = &mfd->panel_info.mipi;
	if (mfd->panel_info.type == MIPI_VIDEO_PANEL) {
		dummy_xres = mfd->panel_info.lcdc.xres_pad;
		dummy_yres = mfd->panel_info.lcdc.yres_pad;

		if (mdp_rev >= MDP_REV_41) {
			MIPI_OUTP(MIPI_DSI_BASE + 0x20,
				((hspw + hbp + width + dummy_xres) << 16 |
				(hspw + hbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x24,
				((vspw + vbp + height + dummy_yres) << 16 |
				(vspw + vbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x28,
				(vspw + vbp + height + dummy_yres +
					vfp - 1) << 16 | (hspw + hbp +
					width + dummy_xres + hfp - 1));
		} else {
			/* DSI_LAN_SWAP_CTRL */
			MIPI_OUTP(MIPI_DSI_BASE + 0x00ac, mipi->dlane_swap);

			MIPI_OUTP(MIPI_DSI_BASE + 0x20,
				((hbp + width + dummy_xres) << 16 | (hbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x24,
				((vbp + height + dummy_yres) << 16 | (vbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x28,
				(vbp + height + dummy_yres + vfp) << 16 |
					(hbp + width + dummy_xres + hfp));
		}

		MIPI_OUTP(MIPI_DSI_BASE + 0x2c, (hspw << 16));
		MIPI_OUTP(MIPI_DSI_BASE + 0x30, 0);
		MIPI_OUTP(MIPI_DSI_BASE + 0x34, (vspw << 16));

	} else {		/* command mode */
		if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
			bpp = 2;
		else
			bpp = 3;	/* Default format set to RGB888 */

		ystride = width * bpp + 1;

		/* DSI_COMMAND_MODE_MDP_STREAM_CTRL */
		data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE;
		MIPI_OUTP(MIPI_DSI_BASE + 0x5c, data);
		MIPI_OUTP(MIPI_DSI_BASE + 0x54, data);

		/* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */
		data = height << 16 | width;
		MIPI_OUTP(MIPI_DSI_BASE + 0x60, data);
		MIPI_OUTP(MIPI_DSI_BASE + 0x58, data);
	}

	mipi_dsi_host_init(mipi);
#if defined(CONFIG_FB_MSM_MIPI_SAMSUNG_OLED_VIDEO_HD_PT_PANEL)
	{
		u32 tmp_reg0c, tmp_rega8;
		udelay(200);
		/* backup register values */
		tmp_reg0c = MIPI_INP(MIPI_DSI_BASE + 0x000c);
		tmp_rega8 = MIPI_INP(MIPI_DSI_BASE + 0xA8);
		/* Clear HS  mode assertion and related flags */
		MIPI_OUTP(MIPI_DSI_BASE + 0x0c, 0x8000);
		MIPI_OUTP(MIPI_DSI_BASE + 0xA8, 0x0);
		wmb();
		mdelay(10);
		if (mipi_dsi_pdata && mipi_dsi_pdata->lcd_rst_up)
		mipi_dsi_pdata->lcd_rst_up();
		/* restore previous values */
		MIPI_OUTP(MIPI_DSI_BASE + 0x0c, tmp_reg0c);
		MIPI_OUTP(MIPI_DSI_BASE + 0xa8, tmp_rega8);
		wmb();
	}
#else
	msleep(10);
#if defined (CONFIG_MIPI_DSI_RESET_LP11)

	/* LP11 */
	tmp = MIPI_INP(MIPI_DSI_BASE + 0xA8);
	tmp &= ~(1<<28);
	MIPI_OUTP(MIPI_DSI_BASE + 0xA8, tmp);
	wmb();
	/* LP11 */

	usleep(5000);
	if (mipi_dsi_pdata && mipi_dsi_pdata->active_reset)
			mipi_dsi_pdata->active_reset(1); /* high */
	usleep(10000);
#endif
#if defined(CONFIG_MACH_LT02_SPR) || defined(CONFIG_MACH_LT02_ATT) || defined(CONFIG_MACH_LT02_TMO)
	if(system_rev)
		ret = panel_next_on(pdev);	
#elif defined(CONFIG_MACH_LT02_CHN_CTC)
        ret = panel_next_on(pdev);
#endif
#endif
	/* always high */
	if (mipi->force_clk_lane_hs) {
		tmp = MIPI_INP(MIPI_DSI_BASE + 0xA8);
		tmp |= (1<<28);
		MIPI_OUTP(MIPI_DSI_BASE + 0xA8, tmp);
		wmb();
	}

	if (mdp_rev >= MDP_REV_41)
		mutex_lock(&mfd->dma->ov_mutex);
	else
		down(&mfd->dma->mutex);
		
#if !defined(CONFIG_MACH_LT02_CHN_CTC)
#if defined(CONFIG_MACH_LT02_SPR) || defined(CONFIG_MACH_LT02_ATT) || defined(CONFIG_MACH_LT02_TMO)
	if(!system_rev)
		ret = panel_next_on(pdev);
#else
	ret = panel_next_on(pdev);
#endif
#endif
	mipi_dsi_op_mode_config(mipi->mode);

	if (mfd->panel_info.type == MIPI_CMD_PANEL) {
		if (pinfo->lcd.vsync_enable) {
			if (pinfo->lcd.hw_vsync_mode && vsync_gpio >= 0) {
				if (mdp_rev >= MDP_REV_41) {
					if (gpio_request(vsync_gpio,
						"MDP_VSYNC") == 0)
						gpio_direction_input(
							vsync_gpio);
					else
						pr_err("%s: unable to \
							request gpio=%d\n",
							__func__, vsync_gpio);
				} else if (mdp_rev == MDP_REV_303) {
					if (!tlmm_settings && gpio_request(
						vsync_gpio, "MDP_VSYNC") == 0) {
						ret = gpio_tlmm_config(
							GPIO_CFG(
							vsync_gpio, 1,
							GPIO_CFG_INPUT,
							GPIO_CFG_PULL_DOWN,
							GPIO_CFG_2MA),
							GPIO_CFG_ENABLE);

						if (ret) {
							pr_err(
							"%s: unable to config \
							tlmm = %d\n",
							__func__, vsync_gpio);
						}
						tlmm_settings = TRUE;

						gpio_direction_input(
							vsync_gpio);
					} else {
						if (!tlmm_settings) {
							pr_err(
							"%s: unable to request \
							gpio=%d\n",
							__func__, vsync_gpio);
						}
					}
				}
/*
 * mipi_dsi_cmds_single_tx:
 * thread context only
 */
int mdss_dsi_cmds_single_tx(struct mdss_dsi_ctrl_pdata *pdata,
		 struct dsi_cmd_desc *cmds,
								int cnt)
{
	struct dsi_cmd_desc *cm;
	unsigned int dsi_ctrl, ctrl;

	int i, j = 0, k = 0, cmd_len = 0, video_mode;
	char *cmds_tx;
	char *bp;
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = pdata;
	struct dsi_buf *tp = &ctrl_pdata->tx_buf;

	pr_debug("%s:++\n",__func__);

	/*Set Last Bit, only for last packet */
	for (i = 0; i < cnt; i++) {
		if(cmds[i].dchdr.dtype != DTYPE_GEN_LWRITE &&
			cmds[i].dchdr.dtype != DTYPE_DCS_LWRITE ) {
			pr_err("Single TX expects only Long Packets,"\
				"Short packet encountered, return fail\n");
			return -1;
		}
		cmds[i].dchdr.last = 0;
	}
	cmds[cnt-1].dchdr.last = 1;



	/* turn on cmd mode
	* for video mode, do not send cmds more than
	* one pixel line, since it only transmit it
	* during BLLP.
	*/
	if (ctrl_pdata->shared_pdata.broadcast_enable) {
		if ((ctrl_pdata->ndx == DSI_CTRL_1)

		  && (left_ctrl_pdata != NULL)) {
			dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
								+ 0x0004);
			video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
			if (video_mode) {
				int data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
				MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
						data);
			}
		}
	}

	dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004);
	video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
	if (video_mode) {
		ctrl = dsi_ctrl | 0x04; /* CMD_MODE_EN */
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, ctrl);
	}

	cm = cmds;
	cmds_tx = kmalloc((1024 + DSI_HOST_HDR_SIZE) * cnt, GFP_KERNEL);
	mdss_dsi_buf_init(tp);
	mdss_dsi_enable_irq(pdata, DSI_CMD_TERM);
	for (i = 0; i < cnt; i++) {
		mdss_dsi_buf_init(tp);
		mdss_dsi_cmd_dma_add(tp, cm);
		bp = tp->data;
		for (j = 0; j < tp->len; j++) {
			*(cmds_tx + k) = *bp++;
			k++;
		}
		cmd_len = cmd_len + tp->len;
		cm++;
	}
	tp->data = cmds_tx;
	tp->len = cmd_len;
	mdss_dsi_cmd_dma_tx(ctrl_pdata, tp);
	kfree(cmds_tx);

	if (video_mode)
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004,
					dsi_ctrl); /* restore */

	return cnt;
}
Exemple #23
0
/*
 * This software is contributed or developed by KYOCERA Corporation.
 * (C) 2012 KYOCERA Corporation
 *
 * drivers/video/msm/disp_ext_board.c
 *
 * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include "msm_fb.h"
#include "mipi_dsi.h"
#ifndef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM
#include "mipi_novatek_wxga.h"
#include <linux/mipi_novatek_wxga_ext.h>
#else
#include "mipi_renesas_cm.h"
#endif
#include "mdp4.h"
#include "disp_ext.h"
#ifdef CONFIG_DISP_EXT_BLC
#include <linux/leds-lm3533.h>
#endif /* CONFIG_DISP_EXT_BLC */

#define DETECT_BOARD_NUM 5

#ifndef CONFIG_FB_MSM_MIPI_DSI_RENESAS_CM
static char detect_board_cmd1_select[4]    = { 0xFF, 0x00, DTYPE_DCS_WRITE1, 0x80 };
static char detect_board_mipi_lane_read[4] = { 0xBA, 0x00, DTYPE_DCS_READ  , 0xA0 };
static char maximum_return_seze_set[4] = { 0x01, 0x00, DTYPE_MAX_PKTSIZE  , 0x80 };
#else
static char detect_board_mipi_lane_read[4] = { 0xA1, 0x00, DTYPE_DCS_READ  , 0xA0 };
static char maximum_return_seze_set[4] = { 0x06, 0x00, DTYPE_MAX_PKTSIZE  , 0x80 };
#endif
extern struct device dsi_dev;
static int panel_detection=0;       /* -1:not panel 0:Not test 1:panel found */
static int disp_ext_board_cmd_tx( char *cm , int size ,int time )
{
	char pload[256];
	int video_mode;
	uint32 dsi_ctrl, ctrl;
	uint32_t off;
	uint32_t ReadValue;
	uint32_t count = 0;

	dma_addr_t dmap;
	
	pr_debug("%s:S\n", __func__);
    DISP_LOCAL_LOG_EMERG("DISP disp_ext_board_cmd_tx S\n");

	/* Align pload at 8 byte boundry */
	off = (uint32_t)pload;
	off &= 0x07;
	if (off) {
		off = 8 - off;
	}
	off += (uint32_t)pload;
	memcpy((void *)off, cm, size);
	ctrl = 0;
	dsi_ctrl = MIPI_INP(MIPI_DSI_BASE + 0x0000);
	video_mode = dsi_ctrl & 0x02;                       /* VIDEO_MODE_EN */
	if (video_mode) {
		ctrl = dsi_ctrl | 0x04;                         /* CMD_MODE_EN */
		MIPI_OUTP(MIPI_DSI_BASE + 0x0000, ctrl);
	}
	dmap = dma_map_single(&dsi_dev, (char *)off, size, DMA_TO_DEVICE);
	
	MIPI_OUTP(MIPI_DSI_BASE + 0x0044, dmap);             /* DSI1_DMA_CMD_OFFSET */
	MIPI_OUTP(MIPI_DSI_BASE + 0x0048, size);            /* DSI1_DMA_CMD_LENGTH */
	wmb();
	MIPI_OUTP(MIPI_DSI_BASE + 0x08c, 0x01);             /* trigger */
	wmb();
	udelay(1);

	if( time != 0 ) {
		pr_debug("%s:wait %d ms\n", __func__,time);
		mdelay(time);
	}
	ReadValue = MIPI_INP(MIPI_DSI_BASE + 0x010C) & 0x00000001;
	pr_debug("%s:S MIPI_INP(MIPI_DSI_BASE + 0x010C)=%x\n", __func__,MIPI_INP(MIPI_DSI_BASE + 0x010C));
	if( time != 0 && ReadValue != 0x00000001 ) {
		pr_err("%s:send command timeout(%d ms)\n", __func__,time);
		dma_unmap_single(&dsi_dev, dmap, size, DMA_TO_DEVICE);
		return -1;
	}

	while (ReadValue != 0x00000001) {
		ReadValue = MIPI_INP(MIPI_DSI_BASE + 0x010C) & 0x00000001;
		count++;
		if (count > 0xffff) {
			pr_err("%s:send command timeout__\n", __func__);
			dma_unmap_single(&dsi_dev, dmap, size, DMA_TO_DEVICE);
			return -1;
		}
	}
	mdelay(5);

	MIPI_OUTP(MIPI_DSI_BASE + 0x010C, MIPI_INP(MIPI_DSI_BASE + 0x010C) | 0x01000001);

	if (video_mode) {
		MIPI_OUTP(MIPI_DSI_BASE + 0x0000, dsi_ctrl);    /* restore */
	}
	dma_unmap_single(&dsi_dev, dmap, size, DMA_TO_DEVICE);
	pr_debug("%s:E\n", __func__);
    DISP_LOCAL_LOG_EMERG("DISP disp_ext_board_cmd_tx E\n");
	return 0;
}
irqreturn_t mdss_dsi_isr(int irq, void *ptr)
{
	u32 isr;
	u32 isr0 = 0;
	struct mdss_dsi_ctrl_pdata *ctrl =
			(struct mdss_dsi_ctrl_pdata *)ptr;

	if (!ctrl) {
		pr_err("%s unable to access ctrl\n", __func__);
		return IRQ_HANDLED;
	}

	if (!ctrl->ctrl_base) {
		pr_err("%s:%d DSI base adr no Initialized",
				       __func__, __LINE__);
		return IRQ_HANDLED;
	}

	isr = MIPI_INP(ctrl->ctrl_base + 0x0110);/* DSI_INTR_CTRL */
	MIPI_OUTP(ctrl->ctrl_base + 0x0110, isr);

	if (ctrl->shared_pdata.broadcast_enable)
		if ((ctrl->panel_data.panel_info.pdest == DISPLAY_2)
		    && (left_ctrl_pdata != NULL)) {
			isr0 = MIPI_INP(left_ctrl_pdata->ctrl_base
						+ 0x0110);/* DSI_INTR_CTRL */
			MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0110, isr0 & (~DSI_INTR_CMD_MDP_DONE));
		}

	pr_debug("%s: isr=%x, isr0=%x", __func__, isr, isr0);

	if (isr & DSI_INTR_ERROR) {
#if defined (CONFIG_FB_MSM_MDSS_DSI_DBG)
	xlog(__func__, ctrl->ndx, ctrl->mdp_busy, isr, 0, 0, 0x97);
#endif
		pr_err("%s: isr[%d]=%x %x", __func__, ctrl->ndx, isr, (int)DSI_INTR_ERROR);
		mdss_dsi_error(ctrl);
	}

	if (isr & DSI_INTR_VIDEO_DONE) {
		spin_lock(&ctrl->mdp_lock);
		mdss_dsi_disable_irq_nosync(ctrl, DSI_VIDEO_TERM);
		complete(&ctrl->video_comp);
		spin_unlock(&ctrl->mdp_lock);
	}

	if (isr & DSI_INTR_CMD_DMA_DONE) {
		spin_lock(&ctrl->mdp_lock);
#if defined (CONFIG_FB_MSM_MDSS_DSI_DBG)
	xlog(__func__,ctrl->ndx, ctrl->mdp_busy, isr, 0, 0, 0x98);
#endif
		mdss_dsi_disable_irq_nosync(ctrl, DSI_CMD_TERM);
		complete(&ctrl->dma_comp);
		spin_unlock(&ctrl->mdp_lock);
	}

	if (isr & DSI_INTR_CMD_MDP_DONE) {
		spin_lock(&ctrl->mdp_lock);
#if defined (CONFIG_FB_MSM_MDSS_DSI_DBG)
	xlog(__func__, ctrl->ndx, ctrl->mdp_busy, isr, 0, 0, 0x99);
#endif
		ctrl->mdp_busy = false;
		mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM);
		complete(&ctrl->mdp_comp);
		spin_unlock(&ctrl->mdp_lock);
	}

	if (isr & DSI_INTR_BTA_DONE) {
		spin_lock(&ctrl->mdp_lock);
		mdss_dsi_disable_irq_nosync(ctrl, DSI_BTA_TERM);
		complete(&ctrl->bta_comp);
		spin_unlock(&ctrl->mdp_lock);
	}

	return IRQ_HANDLED;
}
/*
 * mdss_dsi_cmds_rx() - dcs read from panel
 * @ctrl: dsi controller
 * @cmds: read command descriptor
 * @len: number of bytes to read back
 *
 * controller have 4 registers can hold 16 bytes of rxed data
 * dcs packet: 4 bytes header + payload + 2 bytes crc
 * 2 padding bytes add to payload to have payload length is mutipled by 4
 * 1st read: 4 bytes header + 8 bytes payload + 2 padding + 2 crc
 * 2nd read: 12 bytes payload + 2 padding + 2 crc
 * 3rd read: 12 bytes payload + 2 padding + 2 crc
 *
 */
int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl,
			struct dsi_cmd_desc *cmds, int rlen)
{
	int data_byte, rx_byte, dlen, end;
	int short_response, diff, pkt_size, ret = 0;
	struct dsi_buf *tp, *rp;
	char cmd;
	u32 dsi_ctrl, data;
	int video_mode;
	u32 left_dsi_ctrl = 0;
	bool left_ctrl_restore = false;

	if (ctrl->shared_pdata.broadcast_enable) {
		if (ctrl->ndx == DSI_CTRL_0) {
			pr_debug("%s: Broadcast mode. 1st ctrl\n",
				 __func__);
			return 0;
		}
	}

	if (ctrl->shared_pdata.broadcast_enable) {
		if ((ctrl->ndx == DSI_CTRL_1)
		  && (left_ctrl_pdata != NULL)) {
			left_dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
								+ 0x0004);
			video_mode = left_dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
			if (video_mode) {
				data = left_dsi_ctrl | 0x04; /* CMD_MODE_EN */
				MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
						data);
				left_ctrl_restore = true;
			}
		}
	}

	/* turn on cmd mode
	* for video mode, do not send cmds more than
	* one pixel line, since it only transmit it
	* during BLLP.
	*/
	dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004);
	video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
	if (video_mode) {
		data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
		MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data);
	}

	if (rlen == 0) {
		short_response = 1;
		rx_byte = 4;
	} else {
		short_response = 0;
		data_byte = 8;	/* first read */
		/*
		 * add extra 2 padding bytes to have overall
		 * packet size is multipe by 4. This also make
		 * sure 4 bytes dcs headerlocates within a
		 * 32 bits register after shift in.
		 */
		pkt_size = data_byte + 2;
		rx_byte = data_byte + 8; /* 4 header + 2 crc  + 2 padding*/
	}


	tp = &ctrl->tx_buf;
	rp = &ctrl->rx_buf;

	end = 0;
	mdss_dsi_buf_init(rp);
	while (!end) {
		pr_debug("%s:  rlen=%d pkt_size=%d rx_byte=%d\n",
				__func__, rlen, pkt_size, rx_byte);
		 if (!short_response) {
			max_pktsize[0] = pkt_size;
			mdss_dsi_buf_init(tp);
			ret = mdss_dsi_cmd_dma_add(tp, &pkt_size_cmd);
			if (!ret) {
				pr_err("%s: failed to add max_pkt_size\n",
					__func__);
				rp->len = 0;
				goto end;
			}

			mdss_dsi_wait4video_eng_busy(ctrl);

			mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
			ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
			if (IS_ERR_VALUE(ret)) {
				mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM);
				pr_err("%s: failed to tx max_pkt_size\n",
					__func__);
				rp->len = 0;
				goto end;
			}
			pr_debug("%s: max_pkt_size=%d sent\n",
						__func__, pkt_size);
		}

		mdss_dsi_buf_init(tp);
		ret = mdss_dsi_cmd_dma_add(tp, cmds);
		if (!ret) {
			pr_err("%s: failed to add cmd = 0x%x\n",
				__func__,  cmds->payload[0]);
			rp->len = 0;
			goto end;
		}

		mdss_dsi_wait4video_eng_busy(ctrl);	/* video mode only */
		mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
		/* transmit read comamnd to client */
		ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
		if (IS_ERR_VALUE(ret)) {
			mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM);
			pr_err("%s: failed to tx cmd = 0x%x\n",
				__func__,  cmds->payload[0]);
			rp->len = 0;
			goto end;
		}
		/*
		 * once cmd_dma_done interrupt received,
		 * return data from client is ready and stored
		 * at RDBK_DATA register already
		 * since rx fifo is 16 bytes, dcs header is kept at first loop,
		 * after that dcs header lost during shift into registers
		 */
		dlen = mdss_dsi_cmd_dma_rx(ctrl, rp, rx_byte);

		if (short_response)
			break;

		if (rlen <= data_byte) {
			diff = data_byte - rlen;
			end = 1;
		} else {
			diff = 0;
			rlen -= data_byte;
		}

		dlen -= 2; /* 2 padding bytes */
		dlen -= 2; /* 2 crc */
		dlen -= diff;
		rp->data += dlen;	/* next start position */
		rp->len += dlen;
		data_byte = 12;	/* NOT first read */
		pkt_size += data_byte;
		pr_debug("%s: rp data=%x len=%d dlen=%d diff=%d\n",
			__func__, (int)rp->data, rp->len, dlen, diff);
	}

	rp->data = rp->start;	/* move back to start position */
	cmd = rp->data[0];
	switch (cmd) {
	case DTYPE_ACK_ERR_RESP:
		pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
		rp->len = 0;
	case DTYPE_GEN_READ1_RESP:
	case DTYPE_DCS_READ1_RESP:
		mdss_dsi_short_read1_resp(rp);
		break;
	case DTYPE_GEN_READ2_RESP:
	case DTYPE_DCS_READ2_RESP:
		mdss_dsi_short_read2_resp(rp);
		break;
	case DTYPE_GEN_LREAD_RESP:
	case DTYPE_DCS_LREAD_RESP:
		mdss_dsi_long_read_resp(rp);
		break;
	default:
		pr_warning("%s:Invalid response cmd\n", __func__);
		rp->len = 0;
	}
end:
	if (left_ctrl_restore)
		MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
					left_dsi_ctrl); /*restore */
	if (video_mode)
		MIPI_OUTP((ctrl->ctrl_base) + 0x0004,
					dsi_ctrl); /* restore */

	return rp->len;
}
/*
 * mdss_dsi_cmds_tx:
 * thread context only
 */
int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl,
		struct dsi_cmd_desc *cmds, int cnt)
{
	u32 dsi_ctrl, data;
	int video_mode, ret = 0;
	u32 left_dsi_ctrl = 0;
	bool left_ctrl_restore = false;

	pr_debug("%s : ++ ctrl->ndx (%d) cmd cnt (%d)\n",__func__,ctrl->ndx,cnt);

	if (ctrl->shared_pdata.broadcast_enable) {
		if (ctrl->ndx == DSI_CTRL_0) {
			pr_debug("%s: Broadcast mode. 1st ctrl\n",
				 __func__);
			return 0;
		}
	}

	if (ctrl->shared_pdata.broadcast_enable) {
		if ((ctrl->ndx == DSI_CTRL_1)
		  && (left_ctrl_pdata != NULL)) {
			left_dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
								+ 0x0004);
			video_mode =
				left_dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
			if (video_mode) {
				data = left_dsi_ctrl | 0x04; /* CMD_MODE_EN */
				MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
						data);
				left_ctrl_restore = true;
			}
		} else {
			pr_err("%s no left_ctrl_pdata...\n",__func__);
		}
	}

	/* turn on cmd mode
	* for video mode, do not send cmds more than
	* one pixel line, since it only transmit it
	* during BLLP.
	*/
	dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004);
	video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
	if (video_mode) {
		data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
		MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data);
	}

	ret = mdss_dsi_cmds2buf_tx(ctrl, cmds, cnt);
	if (IS_ERR_VALUE(ret)) {
		pr_err("%s: failed to call\n",
			__func__);
		cnt = -EINVAL;
	}

	if (left_ctrl_restore)
		MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
					left_dsi_ctrl); /*restore */

	if (video_mode)
		MIPI_OUTP((ctrl->ctrl_base) + 0x0004,
					dsi_ctrl); /* restore */

	return cnt;
}
irqreturn_t mdss_dsi_isr(int irq, void *ptr)
{
	u32 isr;
	struct mdss_dsi_ctrl_pdata *ctrl =
			(struct mdss_dsi_ctrl_pdata *)ptr;
	struct mdss_dsi_ctrl_pdata *mctrl = NULL;

	if (!ctrl->ctrl_base) {
		pr_err("%s:%d DSI base adr no Initialized",
						__func__, __LINE__);
		return IRQ_HANDLED;
	}

	isr = MIPI_INP(ctrl->ctrl_base + 0x0110);/* DSI_INTR_CTRL */
	MIPI_OUTP(ctrl->ctrl_base + 0x0110, isr);

	if (mdss_dsi_is_slave_ctrl(ctrl)) {
		mctrl = mdss_dsi_get_master_ctrl();
		if (mctrl) {
			u32 isr0;
			isr0 = MIPI_INP(mctrl->ctrl_base + 0x0110);
			if (isr0 & DSI_INTR_CMD_DMA_DONE)
				MIPI_OUTP(mctrl->ctrl_base + 0x0110,
					DSI_INTR_CMD_DMA_DONE);
		} else {
			pr_warn("%s: Unable to get master control\n",
				__func__);
		}
	}

	pr_debug("%s: ndx=%d isr=%x\n", __func__, ctrl->ndx, isr);

	if (isr & DSI_INTR_ERROR) {
		MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x97);
		pr_err("%s: ndx=%d isr=%x\n", __func__, ctrl->ndx, isr);
		mdss_dsi_error(ctrl);
	}

	if (isr & DSI_INTR_VIDEO_DONE) {
		spin_lock(&ctrl->mdp_lock);
		mdss_dsi_disable_irq_nosync(ctrl, DSI_VIDEO_TERM);
		complete(&ctrl->video_comp);
		spin_unlock(&ctrl->mdp_lock);
	}

	if (isr & DSI_INTR_CMD_DMA_DONE) {
		MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x98);
		spin_lock(&ctrl->mdp_lock);
		mdss_dsi_disable_irq_nosync(ctrl, DSI_CMD_TERM);
		complete(&ctrl->dma_comp);
		spin_unlock(&ctrl->mdp_lock);
	}

	if (isr & DSI_INTR_CMD_MDP_DONE) {
		MDSS_XLOG(ctrl->ndx, ctrl->mdp_busy, isr, 0x99);
		spin_lock(&ctrl->mdp_lock);
		ctrl->mdp_busy = false;
		mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM);
		complete(&ctrl->mdp_comp);
		spin_unlock(&ctrl->mdp_lock);
	}

	if (isr & DSI_INTR_BTA_DONE) {
		spin_lock(&ctrl->mdp_lock);
		mdss_dsi_disable_irq_nosync(ctrl, DSI_BTA_TERM);
		complete(&ctrl->bta_comp);
		spin_unlock(&ctrl->mdp_lock);
	}

	return IRQ_HANDLED;
}
Exemple #28
0
int mdss_dsi_ulps_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata, int enable)
{
	int ret = 0;
	struct mdss_panel_data *pdata = NULL;
	struct mdss_panel_info *pinfo;
	struct mipi_panel_info *mipi;
	u32 lane_status = 0, regval;
	u32 active_lanes = 0, clamp_reg;

	if (!ctrl_pdata) {
		pr_err("%s: invalid input\n", __func__);
		return -EINVAL;
	}

	if (&ctrl_pdata->mmss_misc_io == NULL) {
		pr_err("%s: mmss_misc_io is NULL. ULPS not valid\n", __func__);
		return -EINVAL;
	}

	pdata = &ctrl_pdata->panel_data;
	if (!pdata) {
		pr_err("%s: Invalid panel data\n", __func__);
		return -EINVAL;
	}
	pinfo = &pdata->panel_info;
	mipi = &pinfo->mipi;

	if (!mdss_dsi_ulps_feature_enabled(pdata)) {
		pr_debug("%s: ULPS feature not supported. enable=%d\n",
			__func__, enable);
		return -ENOTSUPP;
	}

	if (pinfo->cont_splash_enabled) {
		pr_debug("%s: skip ULPS config with splash screen enabled\n",
			__func__);
		return 0;
	}

	
	active_lanes = BIT(4);
	clamp_reg = BIT(8) | BIT(9);
	if (mipi->data_lane0) {
		active_lanes |= BIT(0);
		clamp_reg |= (BIT(0) | BIT(1));
	}
	if (mipi->data_lane1) {
		active_lanes |= BIT(1);
		clamp_reg |= (BIT(2) | BIT(3));
	}
	if (mipi->data_lane2) {
		active_lanes |= BIT(2);
		clamp_reg |= (BIT(4) | BIT(5));
	}
	if (mipi->data_lane3) {
		active_lanes |= BIT(3);
		clamp_reg |= (BIT(6) | BIT(7));
	}

	pr_debug("%s: configuring ulps (%s) for ctrl%d, active lanes=0x%08x\n",
		__func__, (enable ? "on" : "off"), ctrl_pdata->ndx,
		active_lanes);

	if (enable && !ctrl_pdata->ulps) {
		MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, active_lanes);
		usleep(100);

		
		lane_status = MIPI_INP(ctrl_pdata->ctrl_base + 0xA8);
		if (lane_status & (active_lanes << 8)) {
			pr_err("%s: ULPS entry req failed for ctrl%d. Lane status=0x%08x\n",
				__func__, ctrl_pdata->ndx, lane_status);
			ret = -EINVAL;
			goto error;
		}

		
		if (ctrl_pdata->ndx == DSI_CTRL_0) {
			regval = MIPI_INP(ctrl_pdata->mmss_misc_io.base + 0x14);
			MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14,
				regval | clamp_reg);
			MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14,
				regval | (clamp_reg | BIT(15)));
		} else if (ctrl_pdata->ndx == DSI_CTRL_1) {
			regval = MIPI_INP(ctrl_pdata->mmss_misc_io.base + 0x14);
			MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14,
				regval | (clamp_reg << 16));
			MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14,
				regval | ((clamp_reg << 16) | BIT(31)));
		}

		wmb();

		MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x108, 0x1);
		ctrl_pdata->ulps = true;
	} else if (ctrl_pdata->ulps) {
		MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x108, 0x0);
		mdss_dsi_phy_init(pdata);

		__mdss_dsi_ctrl_setup(pdata);
		mdss_dsi_sw_reset(pdata);
		mdss_dsi_host_init(pdata);
		mdss_dsi_op_mode_config(pdata->panel_info.mipi.mode,
			pdata);

		MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, active_lanes);
		usleep(100);

		
		if (ctrl_pdata->ndx == DSI_CTRL_0) {
			regval = MIPI_INP(ctrl_pdata->mmss_misc_io.base + 0x14);
			MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14,
				regval & ~(clamp_reg | BIT(15)));
		} else if (ctrl_pdata->ndx == DSI_CTRL_1) {
			regval = MIPI_INP(ctrl_pdata->mmss_misc_io.base + 0x14);
			MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14,
				regval & ~((clamp_reg << 16) | BIT(31)));
		}


		MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, active_lanes << 8);
		usleep(1000);
		MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, 0x0);

		usleep(100);

		lane_status = MIPI_INP(ctrl_pdata->ctrl_base + 0xA8);
		ctrl_pdata->ulps = false;
	}

	pr_debug("%s: DSI lane status = 0x%08x. Ulps %s\n", __func__,
		lane_status, enable ? "enabled" : "disabled");

error:
	return ret;
}
static int mdss_dsi_ulps_config_sub(struct mdss_dsi_ctrl_pdata *ctrl_pdata,
				int enable, int partial)
{
	int ret = 0;
	struct mdss_panel_data *pdata = NULL;
	struct mipi_panel_info *pinfo = NULL;
	u32 lane_status = 0;
	u32 active_lanes = 0;

	if (!ctrl_pdata) {
		pr_err("%s: invalid input\n", __func__);
		return -EINVAL;
	}

	pdata = &ctrl_pdata->panel_data;
	if (!pdata) {
		pr_err("%s: Invalid panel data\n", __func__);
		return -EINVAL;
	}
	pinfo = &pdata->panel_info.mipi;

	if (!partial && !__mdss_dsi_ulps_feature_enabled(pdata)) {
		pr_debug("%s: ULPS feature not supported. enable=%d\n",
			__func__, enable);
		return -ENOTSUPP;
	}

	if (enable && !ctrl_pdata->ulps) {
		/* No need to configure ULPS mode when entering suspend state */
		if (!partial && !pdata->panel_info.panel_power_on) {
			pr_err("%s: panel off. returning\n", __func__);
			goto error;
		}

		if (!partial &&
			__mdss_dsi_clk_enabled(ctrl_pdata, DSI_LINK_CLKS)) {
			pr_err("%s: cannot enter ulps mode if dsi clocks are on\n",
				__func__);
			ret = -EPERM;
			goto error;
		}

		ret = mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
		if (ret) {
			pr_err("%s: Failed to enable clocks. rc=%d\n",
				__func__, ret);
			goto error;
		}

		/*
		 * ULPS Entry Request.
		 * Wait for a short duration to ensure that the lanes
		 * enter ULP state.
		 */
		MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, 0x01F);
		usleep(100);

		/* Check to make sure that all active data lanes are in ULPS */
		if (pinfo->data_lane3)
			active_lanes |= BIT(11);
		if (pinfo->data_lane2)
			active_lanes |= BIT(10);
		if (pinfo->data_lane1)
			active_lanes |= BIT(9);
		if (pinfo->data_lane0)
			active_lanes |= BIT(8);
		active_lanes |= BIT(12); /* clock lane */
		lane_status = MIPI_INP(ctrl_pdata->ctrl_base + 0xA8);
		if (lane_status & active_lanes) {
			pr_err("%s: ULPS entry req failed. Lane status=0x%08x\n",
				__func__, lane_status);
			ret = -EINVAL;
			mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0);
			goto error;
		}

		/* Enable MMSS DSI Clamps */
		MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, 0x3FF);
		MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, 0x83FF);

		wmb();

		MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x108, 0x1);
		/* disable DSI controller */
		mdss_dsi_controller_cfg(0, pdata);

		mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0);
		ctrl_pdata->ulps = true;
	} else if (ctrl_pdata->ulps) {
		ret = mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 1);
		if (ret) {
			pr_err("%s: Failed to enable bus clocks. rc=%d\n",
				__func__, ret);
			goto error;
		}

		MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x108, 0x0);
		mdss_dsi_phy_init(pdata);

		__mdss_dsi_ctrl_setup(pdata);
		mdss_dsi_sw_reset(pdata);
		mdss_dsi_host_init(pdata);
		mdss_dsi_op_mode_config(pdata->panel_info.mipi.mode,
			pdata);

		/*
		 * ULPS Entry Request. This is needed because, after power
		 * collapse and reset, the DSI controller resets back to
		 * idle state and not ULPS.
		 * Wait for a short duration to ensure that the lanes
		 * enter ULP state.
		 */
		MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, 0x01F);
		usleep(100);

		/* Disable MMSS DSI Clamps */
		MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, 0x3FF);
		MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, 0x0);

		ret = mdss_dsi_clk_ctrl(ctrl_pdata, DSI_LINK_CLKS, 1);
		if (ret) {
			pr_err("%s: Failed to enable link clocks. rc=%d\n",
				__func__, ret);
			mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 0);
			goto error;
		}

		/*
		 * ULPS Exit Request
		 * Hardware requirement is to wait for at least 1ms
		 */
		MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, 0x1F00);
		usleep(1000);
		MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, 0x0);

		/*
		 * Wait for a short duration before enabling
		 * data transmission
		 */
		usleep(100);

		lane_status = MIPI_INP(ctrl_pdata->ctrl_base + 0xA8);
		mdss_dsi_clk_ctrl(ctrl_pdata, DSI_LINK_CLKS, 0);
		mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 0);
		ctrl_pdata->ulps = false;
	}

	pr_debug("%s: DSI lane status = 0x%08x. Ulps %s\n", __func__,
		lane_status, enable ? "enabled" : "disabled");

error:
	return ret;
}
Exemple #30
0
/*
 * mdss_dsi_cmds_rx() - dcs read from panel
 * @ctrl: dsi controller
 * @cmds: read command descriptor
 * @len: number of bytes to read back
 *
 * controller have 4 registers can hold 16 bytes of rxed data
 * dcs packet: 4 bytes header + payload + 2 bytes crc
 * 2 padding bytes add to payload to have payload length is mutipled by 4
 * 1st read: 4 bytes header + 8 bytes payload + 2 padding + 2 crc
 * 2nd read: 12 bytes payload + 2 padding + 2 crc
 * 3rd read: 12 bytes payload + 2 padding + 2 crc
 *
 */
int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl,
			struct dsi_cmd_desc *cmds, int rlen)
{
	int data_byte, rx_byte, dlen, end;
	int short_response, len, diff, pkt_size, ret = 0;
	struct dsi_buf *tp, *rp;
	char cmd;
	u32 dsi_ctrl, data;
	int video_mode;
	u32 left_dsi_ctrl = 0;
	bool left_ctrl_restore = false;
	int no_max_pkt_size = ctrl->panel_data.panel_info.mipi.no_max_pkt_size;

	if (ctrl->shared_pdata.broadcast_enable) {
		if (ctrl->ndx == DSI_CTRL_0) {
			pr_debug("%s: Broadcast mode. 1st ctrl\n",
				 __func__);
			return 0;
		}
	}

	if (ctrl->shared_pdata.broadcast_enable) {
		if ((ctrl->ndx == DSI_CTRL_1)
		  && (left_ctrl_pdata != NULL)) {
			left_dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
								+ 0x0004);
			video_mode = left_dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
			if (video_mode) {
				data = left_dsi_ctrl | 0x04; /* CMD_MODE_EN */
				MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
						data);
				left_ctrl_restore = true;
			}
		}
	}

	/* turn on cmd mode
	* for video mode, do not send cmds more than
	* one pixel line, since it only transmit it
	* during BLLP.
	*/
	dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004);
	video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
	if (video_mode) {
		data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
		MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data);
	}

	if (no_max_pkt_size) {
		/* Only support rlen = 4*n */
		rlen = ALIGN(rlen, 4);
	}

	tp = &ctrl->tx_buf;
	rp = &ctrl->rx_buf;

	len = rlen;
	diff = 0;
	end = 0;
	data_byte = 0;

	if (len <= 2) {
		rx_byte = 4;	/* short read */
		short_response = 1;
	} else {
		if (len > MDSS_DSI_LEN) {
			data_byte = MDSS_DSI_LEN;
			pkt_size = data_byte + 2;/* 8 bytes +2 padding */
			rx_byte = data_byte + 8; /* 4 bytes header
						+ 2 bytes crc + 2 Padding */
		} else {
			len = ALIGN(len, 4);
			data_byte = len;
			pkt_size = data_byte;
			rx_byte = data_byte + 6; /* 4 bytes header
						+ 2 bytes crc*/
		}
		short_response = 0;
	}

	mdss_dsi_buf_init(rp);

	while (!end) {
		pr_debug("%s:  rlen=%d pkt_size=%d rx_byte=%d\n",
				__func__, len, pkt_size, rx_byte);
		 if (!short_response) {
			max_pktsize[0] = pkt_size;
			mdss_dsi_buf_init(tp);
			ret = mdss_dsi_cmd_dma_add(tp, &pkt_size_cmd);
			if (!ret) {
				pr_err("%s: failed to add max_pkt_size\n",
					__func__);
				rp->len = 0;
				goto end;
			}

			mdss_dsi_wait4video_eng_busy(ctrl);

			mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
			/* transmit read comamnd to client */
			ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
			if (IS_ERR_VALUE(ret)) {
				mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM);
				pr_err("%s: failed to tx max_pkt_size\n",
					__func__);
				rp->len = 0;
				goto end;
			}
			pr_debug("%s: max_pkt_size=%d sent\n",
						__func__, pkt_size);
		}

		mdss_dsi_buf_init(tp);
		ret = mdss_dsi_cmd_dma_add(tp, cmds);
		if (!ret) {
			pr_err("%s: failed to add cmd = 0x%x\n",
				__func__,  cmds->payload[0]);
			rp->len = 0;
			goto end;
		}

		mdss_dsi_wait4video_eng_busy(ctrl);	/* video mode only */
		mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
		/* transmit read comamnd to client */
		ret = mdss_dsi_cmd_dma_tx(ctrl, tp);
		if (IS_ERR_VALUE(ret)) {
			mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM);
			pr_err("%s: failed to tx cmd = 0x%x\n",
				__func__,  cmds->payload[0]);
			rp->len = 0;
			goto end;
		}
		/*
		 * once cmd_dma_done interrupt received,
		 * return data from client is ready and stored
		 * at RDBK_DATA register already
		 * since rx fifo is 16 bytes, dcs header is kept at first loop,
		 * after that dcs header lost during shift into registers
		 */
		dlen = mdss_dsi_cmd_dma_rx(ctrl, rp, rx_byte);

		if (short_response)
			break;
		if (len <= data_byte) {
			diff = data_byte - len;
			end = 1;
		} else {
			diff = 0;
			len -= data_byte;
		}

		dlen -= 2; /* 2 padding bytes */
		dlen -= 2; /* 2 crc */
		dlen -= diff;
		rp->data += dlen;	/* next start position */
		rp->len += dlen;
		data_byte = 12;	/* NOT first read */
		pkt_size += data_byte;
		pr_debug("%s: rp data=%x len=%d dlen=%d diff=%d\n",
			__func__, (int)rp->data, rp->len, dlen, diff);
	}

	rp->data = rp->start;
	if (rlen <= MDSS_DSI_LEN &&
			!no_max_pkt_size && !short_response) {
		/*
		 * remove extra 2 bytes from previous
		 * rx transaction at shift register
		 * which was inserted during copy
		 * shift registers to rx buffer
		 * rx payload start from long alignment addr
		 */
		rp->data += 2;
	}

	cmd = rp->data[0];
	pr_debug("%s: Read Response:0x%02X\n", __func__, cmd);
	switch (cmd) {
	case DTYPE_ACK_ERR_RESP:
		pr_info("%s: rx ACK_ERR_PACKAGE\n", __func__);
		rp->len = 0;
	case DTYPE_GEN_READ1_RESP:
	case DTYPE_DCS_READ1_RESP:
		mdss_dsi_short_read1_resp(rp);
		break;
	case DTYPE_GEN_READ2_RESP:
	case DTYPE_DCS_READ2_RESP:
		mdss_dsi_short_read2_resp(rp);
		break;
	case DTYPE_GEN_LREAD_RESP:
	case DTYPE_DCS_LREAD_RESP:
		mdss_dsi_long_read_resp(rp);
		break;
	default:
		pr_warning("%s:Invalid response cmd\n", __func__);
		rp->len = 0;
	}
end:
	if (left_ctrl_restore)
		MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
					left_dsi_ctrl); /*restore */
	if (video_mode)
		MIPI_OUTP((ctrl->ctrl_base) + 0x0004,
					dsi_ctrl); /* restore */

	return rp->len;
}