/**
 * LCD ON.
 *
 * Set LCD On via MIPI interface or I2C-Slave interface.
 * Set Backlight on.
 *
 * @param pdev
 *
 * @return int
 */
static int mipi_d2l_lcd_on(struct platform_device *pdev)
{
	int ret = 0;
	u32 chip_id;
	struct msm_fb_data_type *mfd;

	pr_info("%s.\n", __func__);

	/* wait for valid clock before sending data over DSI or I2C. */
	msleep(30);

	mfd = platform_get_drvdata(pdev);
	d2l_mfd = mfd;

	if (!mfd)
		return -ENODEV;
	if (mfd->key != MFD_KEY)
		return -EINVAL;

	chip_id = mipi_d2l_read_reg(mfd, IDREG);


	if (chip_id != TC358764XBG_ID) {
		pr_err("%s: invalid chip_id=0x%x", __func__, chip_id);
		return -ENODEV;
	}

	ret = mipi_d2l_dsi_init_sequence(mfd);
	if (ret)
		return ret;

	mipi_d2l_write_reg(mfd, GPIOC, d2l_gpio_out_mask);
	/* Set GPIOs: gpio#4=U/D=0 , gpio#3=L/R=1 , gpio#2,1=CABC=0. */
	mipi_d2l_write_reg(mfd, GPIOO, d2l_gpio_out_val);

	if (bl_level == 0)
		bl_level = PWM_LEVEL * 2 / 3 ; /* Default ON value */

	/* Set backlight via PWM */
	if (bl_pwm) {
		ret = mipi_d2l_set_backlight_level(bl_pwm, bl_level);
		if (ret)
			pr_err("%s.mipi_d2l_set_backlight_level.ret=%d",
			       __func__, ret);
	}

	pr_info("%s.ret=%d.\n", __func__, ret);

	return ret;
}
/**
 * LCD ON.
 *
 * Set LCD On via MIPI interface or I2C-Slave interface.
 * Set Backlight on.
 *
 * @param pdev
 *
 * @return int
 */
static int mipi_d2l_lcd_on(struct platform_device *pdev)
{
	int ret = 0;
	u32 chip_id;
	struct msm_fb_data_type *mfd;

	pr_info("%s.\n", __func__);

	/* wait for valid clock before sending data over DSI or I2C. */
	msleep(30);

	mfd = platform_get_drvdata(pdev);
	d2l_mfd = mfd;

	if (!mfd)
		return -ENODEV;
	if (mfd->key != MFD_KEY)
		return -EINVAL;

	chip_id = mipi_d2l_read_reg(mfd, IDREG);


	if (chip_id != TC358764XBG_ID) {
		pr_err("%s: invalid chip_id=0x%x", __func__, chip_id);
		return -ENODEV;
	}

	ret = mipi_d2l_dsi_init_sequence(mfd);
	if (ret)
		return ret;

	mipi_d2l_write_reg(mfd, GPIOC, d2l_gpio_out_mask);
	/* Set GPIOs: gpio#4=U/D=0 , gpio#3=L/R=1 , gpio#2,1=CABC=0. */
	mipi_d2l_write_reg(mfd, GPIOO, d2l_gpio_out_val);

#if defined(CONFIG_FB_MSM_MIPI_BOEOT_TFT_VIDEO_WSVGA_PT_PANEL) \
	|| defined(CONFIG_FB_MSM_MIPI_SAMSUNG_TFT_VIDEO_WXGA_PT_PANEL)
	if ((bl_level == 0) && (!initial_powerseq)) {
		bl_level = BRIGHTNESS_DEFAULT ; /* Default ON value */
		INIT_DELAYED_WORK(&det_work, blenable_work_func);
		schedule_delayed_work(&det_work, msecs_to_jiffies(250));
	}

#else
	if ((bl_level == 0) && (!initial_powerseq))
		bl_level = PWM_LEVEL * 2 / 3 ; /* Default ON value */
	/* Set backlight via PWM */
	if (bl_pwm) {
		ret = mipi_d2l_set_backlight_level(bl_pwm, bl_level);
		if (ret)
			pr_err("%s.mipi_d2l_set_backlight_level.ret=%d",
			       __func__, ret);
	}
#endif

	pr_info("%s.ret=%d.\n", __func__, ret);
	/* Set power on flag */
	initial_powerseq = 1;

	return ret;
}
/*
 * Init the D2L bridge via the DSI interface for Video.
 *
 *	Register		Addr	Value
 *  ===================================================
 *  PPI_TX_RX_TA		0x013C	0x00040004
 *  PPI_LPTXTIMECNT	        0x0114	0x00000004
 *  PPI_D0S_CLRSIPOCOUNT	0x0164	0x00000003
 *  PPI_D1S_CLRSIPOCOUNT	0x0168	0x00000003
 *  PPI_D2S_CLRSIPOCOUNT	0x016C	0x00000003
 *  PPI_D3S_CLRSIPOCOUNT	0x0170	0x00000003
 *  PPI_LANEENABLE	        0x0134	0x0000001F
 *  DSI_LANEENABLE	        0x0210	0x0000001F
 *  PPI_STARTPPI	        0x0104	0x00000001
 *  DSI_STARTDSI	        0x0204	0x00000001
 *  VPCTRL			0x0450	0x01000120
 *  HTIM1			0x0454	0x002C0028
 *  VTIM1			0x045C	0x001E0008
 *  VFUEN			0x0464	0x00000001
 *  LVCFG			0x049C	0x00000001
 *
 * VPCTRL.EVTMODE (0x20) configuration bit is needed to determine whether
 * video timing information is delivered in pulse mode or event mode.
 * In pulse mode, both Sync Start and End packets are required.
 * In event mode, only Sync Start packets are required.
 *
 * @param mfd
 *
 * @return register data value
 */
static int mipi_d2l_dsi_init_sequence(struct msm_fb_data_type *mfd)
{
	struct mipi_panel_info *mipi = &mfd->panel_info.mipi;
	u32 lanes_enable;
	u32 vpctrl;
	u32 htime1 = 0x002C0028;
	u32 vtime1 = 0x001E0008;

	lanes_enable = 0x01; /* clock-lane enable */
	lanes_enable |= (mipi->data_lane0 << 1);
	lanes_enable |= (mipi->data_lane1 << 2);
	lanes_enable |= (mipi->data_lane2 << 3);
	lanes_enable |= (mipi->data_lane3 << 4);

	if (mipi->traffic_mode == DSI_NON_BURST_SYNCH_EVENT)
		vpctrl = 0x01000120;
	else if (mipi->traffic_mode == DSI_NON_BURST_SYNCH_PULSE)
		vpctrl = 0x01000100;
	else {
		pr_err("%s.unsupported traffic_mode %d.\n",
		       __func__, mipi->traffic_mode);
		return -EINVAL;
	}

	pr_debug("%s.htime1=0x%x.\n", __func__, htime1);
	pr_debug("%s.vtime1=0x%x.\n", __func__, vtime1);
	pr_debug("%s.vpctrl=0x%x.\n", __func__, vpctrl);
	pr_debug("%s.lanes_enable=0x%x.\n", __func__, lanes_enable);


	mipi_d2l_write_reg(mfd, SYSRST, 0xFF);
	msleep(30);

	/* VESA format instead of JEIDA format for RGB888 */
	mipi_d2l_write_reg(mfd, LVMX0003, 0x03020100);
	mipi_d2l_write_reg(mfd, LVMX0407, 0x08050704);
	mipi_d2l_write_reg(mfd, LVMX0811, 0x0F0E0A09);
	mipi_d2l_write_reg(mfd, LVMX1215, 0x100D0C0B);
	mipi_d2l_write_reg(mfd, LVMX1619, 0x12111716);
	mipi_d2l_write_reg(mfd, LVMX2023, 0x1B151413);
	mipi_d2l_write_reg(mfd, LVMX2427, 0x061A1918);

	mipi_d2l_write_reg(mfd, PPI_TX_RX_TA, 0x00040004); /* BTA */
	mipi_d2l_write_reg(mfd, PPI_LPTXTIMECNT, 0x00000004);
	mipi_d2l_write_reg(mfd, PPI_D0S_CLRSIPOCOUNT, 0x00000003);
	mipi_d2l_write_reg(mfd, PPI_D1S_CLRSIPOCOUNT, 0x00000003);
	mipi_d2l_write_reg(mfd, PPI_D2S_CLRSIPOCOUNT, 0x00000003);
	mipi_d2l_write_reg(mfd, PPI_D3S_CLRSIPOCOUNT, 0x00000003);
	mipi_d2l_write_reg(mfd, PPI_LANEENABLE, lanes_enable);
	mipi_d2l_write_reg(mfd, DSI_LANEENABLE, lanes_enable);
	mipi_d2l_write_reg(mfd, PPI_STARTPPI, 0x00000001);
	mipi_d2l_write_reg(mfd, DSI_STARTDSI, 0x00000001);

	mipi_d2l_write_reg(mfd, VPCTRL, vpctrl); /* RGB888 + Event mode */
	mipi_d2l_write_reg(mfd, HTIM1, htime1);
	mipi_d2l_write_reg(mfd, VTIM1, vtime1);
	mipi_d2l_write_reg(mfd, VFUEN, 0x00000001);
	mipi_d2l_write_reg(mfd, LVCFG, 0x00000001); /* Enables LVDS tx */

	return 0;
}
/*
 * Init the D2L bridge via the DSI interface for Video.
 *
 *	Register		Addr	Value
 *  ===================================================
 *  PPI_TX_RX_TA		0x013C	0x00040004
 *  PPI_LPTXTIMECNT	        0x0114	0x00000004
 *  PPI_D0S_CLRSIPOCOUNT	0x0164	0x00000003
 *  PPI_D1S_CLRSIPOCOUNT	0x0168	0x00000003
 *  PPI_D2S_CLRSIPOCOUNT	0x016C	0x00000003
 *  PPI_D3S_CLRSIPOCOUNT	0x0170	0x00000003
 *  PPI_LANEENABLE	        0x0134	0x0000001F
 *  DSI_LANEENABLE	        0x0210	0x0000001F
 *  PPI_STARTPPI	        0x0104	0x00000001
 *  DSI_STARTDSI	        0x0204	0x00000001
 *  VPCTRL			0x0450	0x01000120
 *  HTIM1			0x0454	0x002C0028
 *  VTIM1			0x045C	0x001E0008
 *  VFUEN			0x0464	0x00000001
 *  LVCFG			0x049C	0x00000001
 *
 * VPCTRL.EVTMODE (0x20) configuration bit is needed to determine whether
 * video timing information is delivered in pulse mode or event mode.
 * In pulse mode, both Sync Start and End packets are required.
 * In event mode, only Sync Start packets are required.
 *
 * @param mfd
 *
 * @return register data value
 */
static int mipi_d2l_dsi_init_sequence(struct msm_fb_data_type *mfd)
{
	struct mipi_panel_info *mipi = &mfd->panel_info.mipi;
	u32 lanes_enable;
	u32 vpctrl;
	u32 htime1 = 0x002C0028;
	u32 vtime1 = 0x001E0008;

	lanes_enable = 0x01; /* clock-lane enable */
	lanes_enable |= (mipi->data_lane0 << 1);
	lanes_enable |= (mipi->data_lane1 << 2);
	lanes_enable |= (mipi->data_lane2 << 3);
	lanes_enable |= (mipi->data_lane3 << 4);

	if (mipi->traffic_mode == DSI_NON_BURST_SYNCH_EVENT)
		vpctrl = 0x01000120;
	else if (mipi->traffic_mode == DSI_NON_BURST_SYNCH_PULSE)
		vpctrl = 0x01000100;
	else {
		pr_err("%s.unsupported traffic_mode %d.\n",
		       __func__, mipi->traffic_mode);
		return -EINVAL;
	}

	pr_debug("%s.htime1=0x%x.\n", __func__, htime1);
	pr_debug("%s.vtime1=0x%x.\n", __func__, vtime1);
	pr_debug("%s.vpctrl=0x%x.\n", __func__, vpctrl);
	pr_debug("%s.lanes_enable=0x%x.\n", __func__, lanes_enable);



#if defined(CONFIG_FB_MSM_MIPI_BOEOT_TFT_VIDEO_WSVGA_PT) \
	|| defined(CONFIG_FB_MSM_MIPI_SAMSUNG_TFT_VIDEO_WXGA_PT)
	/* VESA format instead of JEIDA format for RGB888 */
	mipi_d2l_write_reg(mfd, LVMX0003, 0x03020100);
	mipi_d2l_write_reg(mfd, LVMX0407, 0x08050704);
	mipi_d2l_write_reg(mfd, LVMX0811, 0x0F0E0A09);
	mipi_d2l_write_reg(mfd, LVMX1215, 0x100D0C0B);
	mipi_d2l_write_reg(mfd, LVMX1619, 0x12111716);
	mipi_d2l_write_reg(mfd, LVMX2023, 0x1B151413);
	mipi_d2l_write_reg(mfd, LVMX2427, 0x061A1918);

	mipi_d2l_write_reg(mfd, PPI_TX_RX_TA, 0x00030005); /* BTA */
	mipi_d2l_write_reg(mfd, PPI_LPTXTIMECNT, 0x00000003);
	mipi_d2l_write_reg(mfd, PPI_D0S_CLRSIPOCOUNT, 0x00000002);
	mipi_d2l_write_reg(mfd, PPI_D1S_CLRSIPOCOUNT, 0x00000002);
	mipi_d2l_write_reg(mfd, PPI_D2S_CLRSIPOCOUNT, 0x00000002);
	mipi_d2l_write_reg(mfd, PPI_D3S_CLRSIPOCOUNT, 0x00000002);
	mipi_d2l_write_reg(mfd, PPI_LANEENABLE, 0x0000001F);
	mipi_d2l_write_reg(mfd, DSI_LANEENABLE, 0x0000001F);
	mipi_d2l_write_reg(mfd, PPI_STARTPPI, 0x00000001);
	mipi_d2l_write_reg(mfd, DSI_STARTDSI, 0x00000001);

	mipi_d2l_write_reg(mfd, VPCTRL, 0x03F00120); /* RGB888 + Event mode */
	mipi_d2l_write_reg(mfd, HTIM1, 0x00140114);
	mipi_d2l_write_reg(mfd, HTIM2, 0x00340400);
	mipi_d2l_write_reg(mfd, VTIM1, 0x0022000A);
	mipi_d2l_write_reg(mfd, VTIM1, 0x00150258);
	mipi_d2l_write_reg(mfd, VFUEN, 0x00000001);
#if defined(CONFIG_MACH_ESPRESSO10_ATT)
	mipi_d2l_write_reg(mfd, LVPHY0, 0x0044842D);
	udelay(20);
	mipi_d2l_write_reg(mfd, LVPHY0, 0x0004842D);
	mipi_d2l_write_reg(mfd, LVCFG, 0x00000001);
#else
	mipi_d2l_write_reg(mfd, LVPHY0, 0x0044802D);
	udelay(20);
	mipi_d2l_write_reg(mfd, LVPHY0, 0x0004802D);
	mipi_d2l_write_reg(mfd, LVCFG, 0x00000101);
#endif
#else
	mipi_d2l_write_reg(mfd, SYSRST, 0xFF);
	msleep(30);
	/* VESA format instead of JEIDA format for RGB888 */
	mipi_d2l_write_reg(mfd, LVMX0003, 0x03020100);
	mipi_d2l_write_reg(mfd, LVMX0407, 0x08050704);
	mipi_d2l_write_reg(mfd, LVMX0811, 0x0F0E0A09);
	mipi_d2l_write_reg(mfd, LVMX1215, 0x100D0C0B);
	mipi_d2l_write_reg(mfd, LVMX1619, 0x12111716);
	mipi_d2l_write_reg(mfd, LVMX2023, 0x1B151413);
	mipi_d2l_write_reg(mfd, LVMX2427, 0x061A1918);

	mipi_d2l_write_reg(mfd, PPI_TX_RX_TA, 0x00040004); /* BTA */
	mipi_d2l_write_reg(mfd, PPI_LPTXTIMECNT, 0x00000004);
	mipi_d2l_write_reg(mfd, PPI_D0S_CLRSIPOCOUNT, 0x00000003);
	mipi_d2l_write_reg(mfd, PPI_D1S_CLRSIPOCOUNT, 0x00000003);
	mipi_d2l_write_reg(mfd, PPI_D2S_CLRSIPOCOUNT, 0x00000003);
	mipi_d2l_write_reg(mfd, PPI_D3S_CLRSIPOCOUNT, 0x00000003);
	mipi_d2l_write_reg(mfd, PPI_LANEENABLE, lanes_enable);
	mipi_d2l_write_reg(mfd, DSI_LANEENABLE, lanes_enable);
	mipi_d2l_write_reg(mfd, PPI_STARTPPI, 0x00000001);
	mipi_d2l_write_reg(mfd, DSI_STARTDSI, 0x00000001);

	mipi_d2l_write_reg(mfd, VPCTRL, vpctrl); /* RGB888 + Event mode */
	mipi_d2l_write_reg(mfd, HTIM1, htime1);
	mipi_d2l_write_reg(mfd, VTIM1, vtime1);
	mipi_d2l_write_reg(mfd, VFUEN, 0x00000001);
	mipi_d2l_write_reg(mfd, LVCFG, 0x00000001); /* Enables LVDS tx */
#endif /* CONFIG_FB_MSM_MIPI_BOEOT_TFT_VIDEO_WSVGA_PT */


	return 0;
}