/*
 * mipi dsi short write with 0, 1 2 parameters
 * Write to GEN_HDR 24 bit register the value:
 * 1. 00h, MCS_command[15:8] ,VC[7:6],13h
 * 2. Data1[23:16], MCS_command[15:8] ,VC[7:6],23h
 */
int mipi_dsi_swrite(struct dsi_cmd_desc *cm)
{
    u32 hdr = 0;
    int len = 0;

    if (cm->dlen && cm->payload == 0) {
        k3fb_loge("NO payload error!\n");
        return 0;
    }

    len = (cm->dlen > 2) ? 2 : cm->dlen;

    hdr |= DSI_HDR_DTYPE(cm->dtype);
    hdr |= DSI_HDR_VC(cm->vc);
    if (len == 1) {
        hdr |= DSI_HDR_DATA1(cm->payload[0]);
        hdr |= DSI_HDR_DATA2(0);
    } else if (len == 2) {
        hdr |= DSI_HDR_DATA1(cm->payload[0]);
        hdr |= DSI_HDR_DATA2(cm->payload[1]);
    } else {
        hdr |= DSI_HDR_DATA1(0);
        hdr |= DSI_HDR_DATA2(0);
    }

    set_MIPIDSI_GEN_HDR(hdr);

    return len;  /* 4 bytes */
}
void mipi_dsi_max_return_packet_size(struct dsi_cmd_desc *cm)
{
    u32 hdr = 0;

    /* fill up header */
    hdr |= DSI_HDR_DTYPE(cm->dtype);
    hdr |= DSI_HDR_VC(cm->vc);
    hdr |= DSI_HDR_WC(cm->dlen);
    set_MIPIDSI_GEN_HDR(hdr);
}
void debug_lcd_read_lcd_reg(void)
{
	struct dsi_cmd_desc packet_size_cmd_set;
	volatile int cmd_reg;
	int		max_times;

	int i = 0;
	int reg_msb = g_mipi_lcd_debug_info.lcd_reg_msb;

	if (-1 == g_mipi_lcd_debug_info.lcd_reg_msb) {
		reg_msb = 0;
	}

	max_times = g_mipi_lcd_debug_info.para_num / 4 + 1;

	balongfb_logi("g_mipi_lcd_debug_info.para_num = %ld \n", g_mipi_lcd_debug_info.para_num);

	packet_size_cmd_set.dtype = DTYPE_MAX_PKTSIZE;
	packet_size_cmd_set.vc	  = 0;

	/* video LCD must set the DSI to Command Mode */
	if (g_panel_lcd_mode == 0) {
		set_dsi_mode(CMD_MODE);
		mdelay(100);
	}

	packet_size_cmd_set.dlen = g_mipi_lcd_debug_info.para_num;

	mipi_dsi_max_return_packet_size(&packet_size_cmd_set, NULL);

	mdelay(50);

	cmd_reg = (reg_msb << 8 | g_mipi_lcd_debug_info.lcd_reg_lsb) << 8 | g_mipi_lcd_debug_info.cmd_type;

	/* send cmd */
	set_MIPIDSI_GEN_HDR(NULL, cmd_reg);

	for (i = 0; i < max_times; i++) {
		mdelay(50);

		g_mipi_lcd_debug_info.para_array[i] = get_MIPIDSI_GEN_PLD_DATA();
		balongfb_logi("get_MIPIDSI_GEN_PLD_DATA cmd_reg = 0x%x, lcd_reg_val = %ld \n", cmd_reg, g_mipi_lcd_debug_info.para_array[i]);
	}

	if (g_panel_lcd_mode == 0) {
		set_dsi_mode(HSPD_MODE);
		mdelay(20);
	}

	return;
}
/******************************************************************************
** Read lcd reg interface
*/
int mipi_dsi_read_reg(struct balong_fb_data_type *balongfd, u32 reg, u32 *val, u32 rd_type)
{
    u32 tmp = 0;
    int ret = 0;

    balongfb_logi("check esd enter.\n");

    down(&balongfd->mipi_read_sem);
    down(&balong_fb_blank_sem);
    if (!balongfd->ade_ldi_on)
    {
        /*ldi off, discard this read operation*/
        balongfb_loge("ldi off, before send read cmd, discard this read operation.\n");
        up(&balong_fb_blank_sem);
        up(&balongfd->mipi_read_sem);
        return -1;
    }

    /*read status register*/
    tmp = inp32(balongfd->dsi_base + MIPIDSI_CMD_PKT_STATUS_ADDR);
    if ((tmp & 0x00000001) != 1)
    {
        /*dsi fifo is not empty*/
        balongfb_loge("dsi fifo is not empty!\n");
        ret = -1;
        up(&balong_fb_blank_sem);
        up(&balongfd->mipi_read_sem);
        return ret;
    }
    /*send read command*/
    set_MIPIDSI_GEN_HDR(NULL,((reg << 8) | rd_type));
    up(&balong_fb_blank_sem);

    /*wait and read data*/
    ret = mipi_dsi_wait_and_read(balongfd,val);
    if (ret != 0)
    {
        /*read error*/
        balongfb_loge("read error, discard this read operation.\n");
        ret = -1;
    }
    up(&balongfd->mipi_read_sem);
    return ret;
}
/*
 * mipi dsi long write
 * Write to GEN_PLD_DATA 32 bit register the value:
 * Data3[31:24], Data2[23:16], Data1[15:8], MCS_command[7:0]
 * If need write again to GEN_PLD_DATA 32 bit register the value:
 * Data7[31:24], Data6[23:16], Data5[15:8], Data4[7:0]
 *
 * Write to GEN_HDR 24 bit register the value: WC[23:8] ,VC[7:6],29h
 */
int mipi_dsi_lwrite(struct dsi_cmd_desc *cm)
{
    u32 hdr = 0;
    int i = 0;

    if (cm->dlen && cm->payload == 0) {
        k3fb_loge("NO payload error!\n");
        return 0;
    }

    /* fill up payload */
    for (i = 0;  i < cm->dlen; i += 4) {
        set_MIPIDSI_GEN_PLD_DATA(*((u32 *)(cm->payload + i)));
    }

    /* fill up header */
    hdr |= DSI_HDR_DTYPE(cm->dtype);
    hdr |= DSI_HDR_VC(cm->vc);
    hdr |= DSI_HDR_WC(cm->dlen);
    set_MIPIDSI_GEN_HDR(hdr);

    return cm->dlen;
}
int mipi_dsi_on(struct platform_device *pdev)
{
	int ret = 0;
	struct balong_fb_data_type *balongfd = NULL;
	unsigned long timeout = jiffies;
	if (NULL == pdev) {
		balongfb_loge("NULL Pointer\n");
		return -EINVAL;
	}

	balongfd = (struct balong_fb_data_type *)platform_get_drvdata(pdev);
	if (NULL == balongfd) {
		balongfb_loge("NULL Pointer\n");
		return -EINVAL;
	}

	/* set LCD init step before LCD on*/
	balongfd->panel_info.lcd_init_step = LCD_INIT_POWER_ON;
	ret = panel_next_on(pdev);

	/* mipi dphy clock enable */
	ret = clk_prepare_enable(balongfd->dsi_cfg_clk);
	if (ret != 0) {
		balongfb_loge("failed to enable dsi_cfg_clk, error=%d!\n", ret);
		return ret;
	}

	/* dsi pixel on */
	set_reg(balongfd->ade_base + LDI_HDMI_DSI_GT_REG, 0x0, 1, 0);
	/* mipi init */
	mipi_init(balongfd);

	/* modified for b052 bbit begin */
	/* switch to command mode */
	set_MIPIDSI_MODE_CFG(MIPIDSI_COMMAND_MODE);
	set_MIPIDSI_CMD_MODE_CFG_all_en_flag(1);

	/* 禁止向Clock Lane发起HS时钟传输请求 */
	set_MIPIDSI_LPCLK_CTRL_phy_txrequestclkhs(0);
	/* add for timeout print log */
	balongfb_loge("%s: dsi_on_time = %u,curfreq = %d\n",
			__func__,jiffies_to_msecs(jiffies-timeout),cpufreq_get_fb(0));
	timeout = jiffies;
	ret = panel_next_on(pdev);
	/* modified for b052 bbit begin */
	/* add for timeout print log */
	balongfb_loge("%s: panel_on_time = %u,curfreq = %d\n",
			__func__,jiffies_to_msecs(jiffies-timeout),cpufreq_get_fb(0));
	/* reset Core */
	set_MIPIDSI_PWR_UP_shutdownz(0);

	if (balongfd->panel_info.type == PANEL_MIPI_VIDEO) {
		/* switch to video mode */
	set_MIPIDSI_MODE_CFG(MIPIDSI_VIDEO_MODE);

#if ADE_DEBUG_LOG_ENABLE
	/* set to video lcd mode */
	g_panel_lcd_mode = 0;
#endif
	}

	if (balongfd->panel_info.type == PANEL_MIPI_CMD) {
		/* switch to cmd mode */
		set_MIPIDSI_CMD_MODE_CFG_all_en_flag(0);

#if ADE_DEBUG_LOG_ENABLE
		/* set to command lcd mode */
		g_panel_lcd_mode = 1;
#endif
	}

	/* enable generate High Speed clock */
	set_MIPIDSI_LPCLK_CTRL_phy_txrequestclkhs(1);
	/* Waking up Core */
	set_MIPIDSI_PWR_UP_shutdownz(1);
	/*set max packet size, 0x1 << 8 |0x37*/
	set_MIPIDSI_GEN_HDR(NULL, 0x137);
	lcd_pwr_status.lcd_dcm_pwr_status |= BIT(1);
	do_gettimeofday(&lcd_pwr_status.tvl_lcd_on);
	time_to_tm(lcd_pwr_status.tvl_lcd_on.tv_sec, 0, &lcd_pwr_status.tm_lcd_on);
	return ret;
}