static int hisi_offlinecompser_panel_off(struct platform_device *pdev)
{
	int ret = 0;
	struct hisi_fb_data_type *hisifd = NULL;
	int i = 0;

	BUG_ON(pdev == NULL);
	hisifd = platform_get_drvdata(pdev);
	BUG_ON(hisifd == NULL);

	HISI_FB_DEBUG("index=%d, enter!\n", hisifd->index);

	for (i = 0; i < HISI_DSS_OFFLINE_MAX_NUM; i++) {
		char __iomem *ctl_base = hisifd->dss_base + DSS_GLB_WBE1_CH0_CTL +
				i * (DSS_GLB_WBE1_CH1_CTL - DSS_GLB_WBE1_CH0_CTL);

		cmdlist_config_stop(hisifd, i);
		hisifd->offline_wb_status[i] = e_status_idle;
		set_reg(ctl_base, 0x1, 1, 8);
		set_reg(ctl_base, 0x0, 1, 8);
	}

	HISI_FB_DEBUG("index=%d, exit!\n", hisifd->index);

	return ret;
}
static int hisi_offlinecompser_panel_remove(struct platform_device *pdev)
{
	int ret = 0;
	int i = 0;
	struct hisi_fb_data_type *hisifd = NULL;

	BUG_ON(pdev == NULL);
	hisifd = platform_get_drvdata(pdev);
	/*BUG_ON(hisifd == NULL);*/

	if (!hisifd) {
		return 0;
	}

	HISI_FB_DEBUG("index=%d, enter!\n", hisifd->index);

	for (i = 0; i < HISI_DSS_OFFLINE_MAX_BLOCK; i++) {
		kfree(hisifd->block_rects[i]);
		hisifd->block_rects[i] = NULL;
	}

	if (hisifd->block_overlay) {
		kfree(hisifd->block_overlay);
		hisifd->block_overlay = NULL;
	}

	for(i = 0; i < HISI_DSS_OFFLINE_MAX_LIST; i++){
		cmdlist_free_one_list(hisifd->cmdlist_node[i], hisifd->ion_client);
	}

	HISI_FB_DEBUG("index=%d, exit!\n", hisifd->index);

	return ret;
}
static int mipi_dsi_on(struct platform_device *pdev)
{
	int ret = 0;
	struct hisi_fb_data_type *hisifd = NULL;

	BUG_ON(pdev == NULL);
	hisifd = platform_get_drvdata(pdev);
	BUG_ON(hisifd == NULL);

	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);

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

	mipi_dsi_clk_enable(hisifd);

	mipi_dsi_on_sub1(hisifd, hisifd->mipi_dsi0_base);
	if (is_dual_mipi_panel(hisifd))
		mipi_dsi_on_sub1(hisifd, hisifd->mipi_dsi1_base);

	ret = panel_next_on(pdev);

	mipi_dsi_on_sub2(hisifd, hisifd->mipi_dsi0_base);
	if (is_dual_mipi_panel(hisifd))
		mipi_dsi_on_sub2(hisifd, hisifd->mipi_dsi1_base);

	/* mipi hs video/command mode */
	ret = panel_next_on(pdev);

	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);

	return ret;
}
static int rgb2mipi_on(struct platform_device *pdev)
{
    int ret = 0;
    struct hisi_fb_data_type *hisifd = NULL;

    BUG_ON(pdev == NULL);
    hisifd = platform_get_drvdata(pdev);
    BUG_ON(hisifd == NULL);

    HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);

    hisifd->panel_info.lcd_init_step = LCD_INIT_POWER_ON;

    ret = panel_next_on(pdev);

    /* rgb2mipi bridge init */
    ret = rgb2mipi_init(hisifd);

    /* LCDD (Peripheral) Setting */
    ret = panel_next_on(pdev);

    /* rgb2mipi bridge prepare for receiving  */
    ret = rgb2mipi_prep4Rec(hisifd);

    ret = panel_next_on(pdev);

    msleep(50);

    HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);

    return ret;
}
static void hisifb_vsync_ctrl_workqueue_handler(struct work_struct *work)
{
	struct hisi_fb_data_type *hisifd = NULL;
	struct hisifb_vsync *vsync_ctrl = NULL;
	struct hisi_fb_panel_data *pdata = NULL;
	unsigned long flags = 0;

	vsync_ctrl = container_of(work, typeof(*vsync_ctrl), vsync_ctrl_work);
	BUG_ON(vsync_ctrl == NULL);
	hisifd = vsync_ctrl->hisifd;
	BUG_ON(hisifd == NULL);
	pdata = dev_get_platdata(&hisifd->pdev->dev);
	BUG_ON(pdata == NULL);

	down(&(hisifd->blank_sem));

	if (!hisifd->panel_power_on) {
		HISI_FB_DEBUG("fb%d, panel is power off!", hisifd->index);
		up(&(hisifd->blank_sem));
		return;
	}

	mutex_lock(&(vsync_ctrl->vsync_lock));
	if (vsync_ctrl->vsync_ctrl_disabled_set &&
		(vsync_ctrl->vsync_ctrl_expire_count == 0) &&
		vsync_ctrl->vsync_ctrl_enabled &&
		!vsync_ctrl->vsync_enabled) {
		HISI_FB_DEBUG("fb%d, dss clk off!\n", hisifd->index);

		spin_lock_irqsave(&(vsync_ctrl->spin_lock), flags);
		if (pdata->vsync_ctrl) {
			pdata->vsync_ctrl(hisifd->pdev, 0);
		} else {
			HISI_FB_ERR("fb%d, vsync_ctrl not supported!\n", hisifd->index);
		}
		vsync_ctrl->vsync_ctrl_enabled = 0;
		vsync_ctrl->vsync_ctrl_disabled_set = 0;
		spin_unlock_irqrestore(&(vsync_ctrl->spin_lock), flags);

		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_MIPI_ULPS) {
			mipi_dsi_ulps_cfg(hisifd, 0);
		}

		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_CLK_OFF) {
			dpe_clk_disable(hisifd);
			mipi_dsi_clk_disable(hisifd);
		}

		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_VCC_OFF) {
			dpe_regulator_disable(hisifd);
		}
	}
	mutex_unlock(&(vsync_ctrl->vsync_lock));

	if (vsync_ctrl->vsync_report_fnc) {
		vsync_ctrl->vsync_report_fnc(1);
	}

	up(&(hisifd->blank_sem));
}
static int mipi_dsi_remove(struct platform_device *pdev)
{
	int ret = 0;
	struct hisi_fb_data_type *hisifd = NULL;

	BUG_ON(pdev == NULL);
	hisifd = platform_get_drvdata(pdev);
	BUG_ON(hisifd == NULL);

	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);

	ret = panel_next_remove(pdev);

	if (hisifd->dss_dphy0_clk) {
		clk_put(hisifd->dss_dphy0_clk);
		hisifd->dss_dphy0_clk = NULL;
	}

	if (hisifd->dss_dphy1_clk) {
		clk_put(hisifd->dss_dphy1_clk);
		hisifd->dss_dphy1_clk = NULL;
	}

	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);

	return ret;
}
static int hisi_pwm_probe(struct platform_device *pdev)
{
	struct device_node *np = NULL;
	int ret = 0;

	HISI_FB_DEBUG("+.\n");

	BUG_ON(pdev == NULL);

	np = of_find_compatible_node(NULL, NULL, DTS_COMP_PWM_NAME);
	if (!np) {
		HISI_FB_ERR("NOT FOUND device node %s!\n", DTS_COMP_PWM_NAME);
		ret = -ENXIO;
		goto err_return;
	}

	/* get pwm reg base */
	hisifd_pwm_base = of_iomap(np, 0);

#if !defined(CONFIG_ARCH_HI3630FPGA) && !defined(CONFIG_HISI_3635_FPGA) \
	&& !defined(CONFIG_HISI_3650_FPGA)
	/* pwm pinctrl init */
	ret = pinctrl_cmds_tx(pdev, pwm_pinctrl_init_cmds,
		ARRAY_SIZE(pwm_pinctrl_init_cmds));
	if (ret != 0) {
		HISI_FB_ERR("Init pwm pinctrl failed! ret=%d.\n", ret);
		goto err_return;
	}

	/* get blpwm clk resource */
	g_dss_pwm_clk = of_clk_get(np, 0);
	if (IS_ERR(g_dss_pwm_clk)) {
		HISI_FB_ERR("%s clock not found: %d!\n",
			np->name, (int)PTR_ERR(g_dss_pwm_clk));
		ret = -ENXIO;
		goto err_return;
	}

	ret = clk_set_rate(g_dss_pwm_clk, DEFAULT_PWM_CLK_RATE);
	if (ret != 0) {
		HISI_FB_ERR("dss_pwm_clk clk_set_rate(%lu) failed, error=%d!\n",
			DEFAULT_PWM_CLK_RATE, ret);
		ret = -EINVAL;
		goto err_return;
	}

	HISI_FB_INFO("dss_pwm_clk:[%lu]->[%lu].\n",
		DEFAULT_PWM_CLK_RATE, clk_get_rate(g_dss_pwm_clk));
#endif

	hisi_fb_device_set_status0(DTS_PWM_READY);

	HISI_FB_DEBUG("-.\n");

	return 0;

err_return:
	return ret;
}
static int mipi_dsi_frc_handle(struct platform_device *pdev, int fps)
{
	int ret = 0;

#if 0
	struct hisi_fb_data_type *hisifd = NULL;
	struct hisi_panel_info *pinfo = NULL;
	uint32_t hline_time = 0;
	uint32_t pixel_clk = 0;
	uint32_t vertical_timing = 0;
	uint32_t horizontal_timing = 0;
	uint32_t h_front_porch = 0;

	BUG_ON(pdev == NULL);
	hisifd = platform_get_drvdata(pdev);
	BUG_ON(hisifd == NULL);

	if (hisifd->index != PRIMARY_PANEL_IDX) {
		HISI_FB_ERR("fb%d, not support!", hisifd->index);
		return 0;
	}

	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);

	pinfo = &(hisifd->panel_info);

	/* calculate new HFP based on target_fps */
	vertical_timing = pinfo->yres + pinfo->ldi.v_back_porch
		+ pinfo->ldi.v_front_porch + pinfo->ldi.v_pulse_width;
	horizontal_timing = pinfo->pxl_clk_rate / (vertical_timing * fps);

	/* new HFP*/
	/*
	pinfo->ldi.h_front_porch = horizontal_timing - pinfo->xres
		-pinfo->ldi.h_back_porch - pinfo->ldi.h_pulse_width;
	*/
	h_front_porch = horizontal_timing - pinfo->xres
		-pinfo->ldi.h_back_porch - pinfo->ldi.h_pulse_width;

	pixel_clk = pinfo->pxl_clk_rate / 1000000;
	/* update hline_time */
	hline_time = (pinfo->ldi.h_pulse_width + pinfo->ldi.h_back_porch +
		pinfo->xres + h_front_porch) *
		(pinfo->mipi.dsi_bit_clk / 4) / pixel_clk;

	/* reset dsi core */
	set_reg(hisifd->mipi_dsi0_base + MIPIDSI_PWR_UP_OFFSET, 0x0, 1, 0);
	set_reg(hisifd->mipi_dsi0_base + MIPIDSI_VID_HLINE_TIME_OFFSET, hline_time, 15, 0);
	outp32(hisifd->dss_base + PDP_LDI_DPI0_HRZ_CTRL0,
		h_front_porch | (pinfo->ldi.h_back_porch << 16));

	/* power on dsi core */
	set_reg(hisifd->mipi_dsi0_base + MIPIDSI_PWR_UP_OFFSET, 0x1, 1, 0);

	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);
#endif

	return ret;
}
static int hisi_spi_remove(struct spi_device *spi_dev)
{
	HISI_FB_DEBUG("+.\n");
	/*spi_unregister_driver(&spi_driver);*/
	HISI_FB_DEBUG("-.\n");

	return 0;
}
static int hisi_spi_probe (struct spi_device *spi_dev)
{
	HISI_FB_DEBUG("+.\n");

	g_spi_dev = spi_dev;

	spi_dev->bits_per_word = 8;
	spi_dev->mode = SPI_MODE_3;
	spi_setup(spi_dev);

	hisi_fb_device_set_status0(DTS_SPI_READY);

	HISI_FB_DEBUG("-.\n");

	return 0;
}
static int rgb2mipi_esd_handle(struct platform_device *pdev)
{
    int ret = 0;
    struct hisi_fb_data_type *hisifd = NULL;

    BUG_ON(pdev == NULL);
    hisifd = platform_get_drvdata(pdev);
    BUG_ON(hisifd == NULL);

    HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);

    ret = panel_next_esd_handle(pdev);

    HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);

    return ret;
}
static int rgb2mipi_vsync_ctrl(struct platform_device *pdev, int enable)
{
    int ret = 0;
    struct hisi_fb_data_type *hisifd = NULL;

    BUG_ON(pdev == NULL);
    hisifd = platform_get_drvdata(pdev);
    BUG_ON(hisifd == NULL);

    HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);

    ret = panel_next_vsync_ctrl(pdev, enable);

    HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);

    return ret;
}
static int mipi_dsi_set_display_region(struct platform_device *pdev, struct dss_rect *dirty)
{
	int ret = 0;
	struct hisi_fb_data_type *hisifd = NULL;

	BUG_ON(pdev == NULL || dirty == NULL);
	hisifd = platform_get_drvdata(pdev);
	BUG_ON(hisifd == NULL);

	HISI_FB_DEBUG("index=%d, enter!\n", hisifd->index);

	ret = panel_next_set_display_region(pdev, dirty);

	HISI_FB_DEBUG("index=%d, exit!\n", hisifd->index);

	return ret;
}
int hisifb_vsync_ctrl(struct fb_info *info, void __user *argp)
{
	int ret = 0;
	struct hisi_fb_data_type *hisifd = NULL;
	struct hisi_fb_panel_data *pdata = NULL;
	struct hisifb_vsync *vsync_ctrl = NULL;
	int enable = 0;

	BUG_ON(info == NULL);
	hisifd = (struct hisi_fb_data_type *)info->par;
	BUG_ON(hisifd == NULL);
	pdata = dev_get_platdata(&hisifd->pdev->dev);
	BUG_ON(pdata == NULL);
	vsync_ctrl = &(hisifd->vsync_ctrl);
	BUG_ON(vsync_ctrl == NULL);

	ret = copy_from_user(&enable, argp, sizeof(enable));
	if (ret) {
		HISI_FB_ERR("hisifb_vsync_ctrl ioctl failed!\n");
		return ret;
	}

	enable = (enable) ? 1 : 0;

	mutex_lock(&(vsync_ctrl->vsync_lock));

	if (vsync_ctrl->vsync_enabled == enable) {
		mutex_unlock(&(vsync_ctrl->vsync_lock));
		return 0;
	}

	if (g_debug_online_vsync)
		HISI_FB_INFO("fb%d, enable=%d!\n", hisifd->index, enable);

	vsync_ctrl->vsync_enabled = enable;

	mutex_unlock(&(vsync_ctrl->vsync_lock));

	down(&hisifd->blank_sem);

	if (!hisifd->panel_power_on) {
		HISI_FB_DEBUG("fb%d, panel is power off!", hisifd->index);
		up(&hisifd->blank_sem);
		return 0;
	}

	if (enable) {
		hisifb_activate_vsync(hisifd);
	} else {
		hisifb_deactivate_vsync(hisifd);
	}

	up(&hisifd->blank_sem);

	return 0;
}
void hisifb_activate_vsync(struct hisi_fb_data_type *hisifd)
{
	struct hisi_fb_panel_data *pdata = NULL;
	struct hisifb_vsync *vsync_ctrl = NULL;
	unsigned long flags = 0;
	int clk_enabled = 0;

	BUG_ON(hisifd == NULL);
	pdata = dev_get_platdata(&hisifd->pdev->dev);
	BUG_ON(pdata == NULL);
	vsync_ctrl = &(hisifd->vsync_ctrl);
	BUG_ON(vsync_ctrl == NULL);

	if (hisifd->panel_info.vsync_ctrl_type == VSYNC_CTRL_NONE)
		return;

	mutex_lock(&(vsync_ctrl->vsync_lock));

	if (vsync_ctrl->vsync_ctrl_enabled == 0) {
		HISI_FB_DEBUG("fb%d, dss clk on!\n", hisifd->index);
		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_VCC_OFF) {
			dpe_regulator_enable(hisifd);
		}

		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_CLK_OFF) {
			mipi_dsi_clk_enable(hisifd);
			dpe_clk_enable(hisifd);
		}

		if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_MIPI_ULPS) {
			mipi_dsi_ulps_cfg(hisifd, 1);
		}

		vsync_ctrl->vsync_ctrl_enabled = 1;
		clk_enabled = 1;
	}

	spin_lock_irqsave(&(vsync_ctrl->spin_lock), flags);
	vsync_ctrl->vsync_ctrl_disabled_set = 0;
	vsync_ctrl->vsync_ctrl_expire_count = 0;

	if (clk_enabled) {
		if (pdata->vsync_ctrl) {
			pdata->vsync_ctrl(hisifd->pdev, 1);
		} else {
			HISI_FB_ERR("fb%d, vsync_ctrl not supported!\n", hisifd->index);
		}
	}
	spin_unlock_irqrestore(&(vsync_ctrl->spin_lock), flags);

	mutex_unlock(&(vsync_ctrl->vsync_lock));
}
int mipi_dsi_ulps_cfg(struct hisi_fb_data_type *hisifd, int enable)
{
	int ret = 0;

	BUG_ON(hisifd == NULL);

	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);

	if (enable) {
		mipi_dsi_ulps_exit(hisifd, hisifd->mipi_dsi0_base);
		if (is_dual_mipi_panel(hisifd))
			mipi_dsi_ulps_exit(hisifd, hisifd->mipi_dsi1_base);
	} else {
		mipi_dsi_ulps_enter(hisifd, hisifd->mipi_dsi0_base);
		if (is_dual_mipi_panel(hisifd))
			mipi_dsi_ulps_enter(hisifd, hisifd->mipi_dsi1_base);
	}

	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);

	return ret;
}
static int mipi_dsi_off(struct platform_device *pdev)
{
	int ret = 0;
	struct hisi_fb_data_type *hisifd = NULL;

	BUG_ON(pdev == NULL);
	hisifd = platform_get_drvdata(pdev);
	BUG_ON(hisifd == NULL);

	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);

	ret = panel_next_off(pdev);

	mipi_dsi_off_sub(hisifd, hisifd->mipi_dsi0_base);
	if (is_dual_mipi_panel(hisifd))
		mipi_dsi_off_sub(hisifd, hisifd->mipi_dsi1_base);

	mipi_dsi_clk_disable(hisifd);

	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);

	return ret;
}
static ssize_t mipi_dsi_bit_clk_upt_store(struct platform_device *pdev,
	const char *buf, size_t count)
{
	struct hisi_fb_data_type *hisifd = NULL;
	struct hisi_panel_info *pinfo = NULL;

	BUG_ON(pdev == NULL);
	hisifd = platform_get_drvdata(pdev);
	BUG_ON(hisifd == NULL);
	pinfo = &(hisifd->panel_info);

	if (!hisifd->panel_info.dsi_bit_clk_upt_support) {
		HISI_FB_ERR("fb%d, not support!", hisifd->index);
		return count;
	}

	HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);

	if (!strncmp(buf, MIPI_DSI_BIT_CLK_STR1, count)) {
		pinfo->mipi.dsi_bit_clk_upt = pinfo->mipi.dsi_bit_clk_val1;
	} else if (!strncmp(buf, MIPI_DSI_BIT_CLK_STR2, count)) {
		pinfo->mipi.dsi_bit_clk_upt = pinfo->mipi.dsi_bit_clk_val2;
	} else if (!strncmp(buf, MIPI_DSI_BIT_CLK_STR3, count)) {
		pinfo->mipi.dsi_bit_clk_upt = pinfo->mipi.dsi_bit_clk_val3;
	} else if (!strncmp(buf, MIPI_DSI_BIT_CLK_STR4, count)) {
		pinfo->mipi.dsi_bit_clk_upt = pinfo->mipi.dsi_bit_clk_val4;
	} else if (!strncmp(buf, MIPI_DSI_BIT_CLK_STR5, count)) {
		pinfo->mipi.dsi_bit_clk_upt = pinfo->mipi.dsi_bit_clk_val5;
	} else {
		HISI_FB_ERR("fb%d, unknown dsi_bit_clk_index!\n", hisifd->index);
	}

	HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);

	return count;
}
static int rgb2mipi_probe(struct platform_device *pdev)
{
    struct hisi_fb_data_type *hisifd = NULL;
    struct platform_device *dpe_dev = NULL;
    struct hisi_fb_panel_data *pdata = NULL;
    int ret = 0;

    BUG_ON(pdev == NULL);
    hisifd = platform_get_drvdata(pdev);
    BUG_ON(hisifd == NULL);
    BUG_ON(hisifd->panel_info.spi_dev == NULL);

    HISI_FB_DEBUG("fb%d, +.\n", hisifd->index);

    /* alloc device */
    dpe_dev = platform_device_alloc(DEV_NAME_DSS_DPE, pdev->id);
    if (!dpe_dev) {
        HISI_FB_ERR("fb%d platform_device_alloc failed, error=%d!\n", hisifd->index, ret);
        ret = -ENOMEM;
        goto err_device_alloc;
    }

    /* link to the latest pdev */
    hisifd->pdev = dpe_dev;

    /* alloc panel device data */
    ret = platform_device_add_data(dpe_dev, dev_get_platdata(&pdev->dev),
                                   sizeof(struct hisi_fb_panel_data));
    if (ret) {
        HISI_FB_ERR("fb%d platform_device_add_data failed error=%d!\n", hisifd->index, ret);
        goto err_device_put;
    }

    /* data chain */
    pdata = dev_get_platdata(&dpe_dev->dev);
    pdata->set_fastboot = rgb2mipi_set_fastboot;
    pdata->on = rgb2mipi_on;
    pdata->off = rgb2mipi_off;
    pdata->remove = rgb2mipi_remove;
    pdata->set_backlight = rgb2mipi_set_backlight;
    pdata->vsync_ctrl = rgb2mipi_vsync_ctrl;
    pdata->frc_handle = rgb2mipi_frc_handle;
    pdata->esd_handle = rgb2mipi_esd_handle;
    pdata->next = pdev;

    /* get/set panel info */
    memcpy(&hisifd->panel_info, pdata->panel_info, sizeof(struct hisi_panel_info));

    /* set driver data */
    platform_set_drvdata(dpe_dev, hisifd);
    /* device add */
    ret = platform_device_add(dpe_dev);
    if (ret) {
        HISI_FB_ERR("fb%d platform_device_add failed, error=%d!\n", hisifd->index, ret);
        goto err_device_put;
    }

    HISI_FB_DEBUG("fb%d, -.\n", hisifd->index);

    return 0;

err_device_put:
    platform_device_put(dpe_dev);
err_device_alloc:
    return ret;
}
int mipi_dsi_bit_clk_upt_isr_handler(struct hisi_fb_data_type *hisifd)
{
	char __iomem *mipi_dsi0_base = NULL;
	struct mipi_dsi_phy_ctrl phy_ctrl = {0};
	struct hisi_panel_info *pinfo = NULL;
	uint32_t dsi_bit_clk_upt = 0;
	uint32_t hline_time = 0;
	uint32_t hsa_time = 0;
	uint32_t hbp_time = 0;
	uint32_t pixel_clk = 0;

	uint32_t tmp = 0;
	bool is_ready = false;
	int i = 0;

	BUG_ON(hisifd == NULL);
	pinfo = &(hisifd->panel_info);
	dsi_bit_clk_upt = pinfo->mipi.dsi_bit_clk_upt;
	mipi_dsi0_base = hisifd->mipi_dsi0_base;

	if (hisifd->index != PRIMARY_PANEL_IDX) {
		HISI_FB_ERR("fb%d, not support!", hisifd->index);
		return 0;
	}

	if (dsi_bit_clk_upt == pinfo->mipi.dsi_bit_clk) {
		return 0;
	}

	HISI_FB_DEBUG("fb%d +.\n", hisifd->index);

	/* get new phy_ctrl value according to dsi_bit_clk_next */
	get_dsi_phy_ctrl(pinfo->mipi.dsi_bit_clk_upt, &phy_ctrl);

	/*
	** Configure the DPHY PLL clock frequency through the TEST Interface to
	** operate at XX Hz,
	*/

	/* Write M Pll part 1 */
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010018);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, phy_ctrl.m_pll_1);

	/*wait until dphy data lane enter into stop state*/
	for (i = 0; i < 40; i++) {
		tmp = inp32(mipi_dsi0_base + MIPIDSI_PHY_STATUS_OFFSET);
		if ((tmp & 0x00000a90) == 0x00000a90) {
			is_ready = true;
			break;
		}
		udelay(1);
	}

	if (!is_ready) {
		HISI_FB_ERR("fb%d, phystopstatedatalane is not ready! MIPIDSI_PHY_STATUS_OFFSET=0x%x.\n",
			hisifd->index, tmp);
		return 0;
	}

	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);

	pinfo->mipi.dsi_bit_clk = dsi_bit_clk_upt;

	/* Write M Pll part 2 */
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010018);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, phy_ctrl.m_pll_2);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);

	/* Set hsfreqrange */
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010044);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, phy_ctrl.hsfreqrange);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);

	/* Write CP current */
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010011);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, phy_ctrl.cp_current);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);

	/* Write LPF Control */
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010012);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, phy_ctrl.lpf_ctrl);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);

	if (!is_mipi_cmd_panel(hisifd)) {
		/*
		** Define the DPI Horizontal timing configuration:
		**
		** Hsa_time = HSA*(PCLK period/Clk Lane Byte Period);
		** Hbp_time = HBP*(PCLK period/Clk Lane Byte Period);
		** Hline_time = (HSA+HBP+HACT+HFP)*(PCLK period/Clk Lane Byte Period);
		*/
		pixel_clk = pinfo->pxl_clk_rate / 1000000;
		hsa_time = pinfo->ldi.h_pulse_width * phy_ctrl.lane_byte_clk / pixel_clk;
		hbp_time = pinfo->ldi.h_back_porch * phy_ctrl.lane_byte_clk / pixel_clk;
		hline_time = (pinfo->ldi.h_pulse_width + pinfo->ldi.h_back_porch +
		pinfo->xres + pinfo->ldi.h_front_porch) *
		phy_ctrl.lane_byte_clk / pixel_clk;

		outp32(mipi_dsi0_base + MIPIDSI_VID_HSA_TIME_OFFSET, hsa_time);
		outp32(mipi_dsi0_base + MIPIDSI_VID_HBP_TIME_OFFSET, hbp_time);
		outp32(mipi_dsi0_base + MIPIDSI_VID_HLINE_TIME_OFFSET, hline_time);
	}

	/* Configure core's phy parameters */
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TMR_LPCLK_CFG_OFFSET,
		(phy_ctrl.clk_lane_lp2hs_time + (phy_ctrl.clk_lane_hs2lp_time << 16)));
	outp32(mipi_dsi0_base + MIPIDSI_PHY_TMR_CFG_OFFSET,
		(4095 + (phy_ctrl.data_lane_lp2hs_time << 16) + (phy_ctrl.data_lane_hs2lp_time << 24)));

	/*
	** Configure the TX_ESC clock frequency to a frequency lower than 20 MHz
	** that is the maximum allowed frequency for D-PHY ESCAPE mode.
	*/
	outp32(mipi_dsi0_base + MIPIDSI_CLKMGR_CFG_OFFSET, (phy_ctrl.clk_division + (phy_ctrl.clk_division<<8)));

	HISI_FB_DEBUG("fb%d -.\n", hisifd->index);

	return 0;
}
static int mipi_dsi_ulps_exit(struct hisi_fb_data_type *hisifd,
	char __iomem *mipi_dsi_base)
{
	uint32_t tmp = 0;
	uint32_t cmp_val = 0;
	uint32_t try_times = 0;

	BUG_ON(hisifd == NULL);
	BUG_ON(mipi_dsi_base == NULL);

	HISI_FB_DEBUG("fb%d, +!\n", hisifd->index);

	if (hisifd->panel_info.mipi.lane_nums >= DSI_4_LANES) {
		cmp_val = (BIT(3) | BIT(5) | BIT(8) | BIT(10) | BIT(12));
	} else if (hisifd->panel_info.mipi.lane_nums >= DSI_3_LANES) {
		cmp_val = (BIT(3) | BIT(5) | BIT(8) | BIT(10));
	} else if (hisifd->panel_info.mipi.lane_nums >= DSI_2_LANES) {
		cmp_val = (BIT(3) | BIT(5) | BIT(8));
	} else {
		cmp_val = (BIT(3) | BIT(5));
	}

	/* enable refclk and cfgclk */
	if (is_dual_mipi_panel(hisifd))
		outp32(hisifd->crgperi_base + PEREN3_OFFSET, 0x500000);
	else
		outp32(hisifd->crgperi_base + PEREN3_OFFSET, 0x100000);

	/* Test Code @ 0x20 = 0x45 */
	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010020);
	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);
	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00000045);
	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002);
	outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000);

	/* enable DPHY PLL, force_pll = 1 */
	outp32(mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET, 0xF);

	/* wait DPHY PLL Lock */
	try_times = 0;
	tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
	while ((tmp & BIT(0)) != 0X1) {
		udelay(10);
		if (++try_times > 100) {
			HISI_FB_ERR("fb%d, failed to wait DPHY PLL Lock!MIPIDSI_PHY_STATUS=0x%x.\n",
				hisifd->index, tmp);
			break;
		}

		tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
	}

	/* request that data lane and clock lane exit ULPS */
	outp32(mipi_dsi_base + MIPIDSI_PHY_ULPS_CTRL_OFFSET, 0xF);
	try_times= 0;
	tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
	while ((tmp & cmp_val) != cmp_val) {
		udelay(10);
		if (++try_times > 100) {
			HISI_FB_ERR("fb%d, failed to request that data lane and clock lane exit ULPS!MIPIDSI_PHY_STATUS=0x%x.\n",
				hisifd->index, tmp);
			break;
		}

		tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET);
	}

	/* mipi spec */
	mdelay(1);

	/* clear PHY_ULPS_CTRL */
	outp32(mipi_dsi_base + MIPIDSI_PHY_ULPS_CTRL_OFFSET, 0x0);

	/* enable DPHY clock lane's Hight Speed Clock */
	set_reg(mipi_dsi_base + MIPIDSI_LPCLK_CTRL_OFFSET, 0x1, 1, 0);

	HISI_FB_DEBUG("fb%d, -!\n", hisifd->index);

	return 0;
}
uint32_t hisi_dss_mif_get_invalid_sel(dss_img_t *img, uint32_t transform, int v_scaling_factor,
	uint8_t is_tile, bool rdma_stretch_enable)
{
	uint32_t invalid_sel_val = 0;
	uint32_t tlb_tag_org = 0;

	if (img == NULL) {
		HISI_FB_ERR("img is null");
		return 0;
	}

	if ((transform == (HISI_FB_TRANSFORM_ROT_90 | HISI_FB_TRANSFORM_FLIP_H))
		|| (transform == (HISI_FB_TRANSFORM_ROT_90 | HISI_FB_TRANSFORM_FLIP_V))) {
		transform = HISI_FB_TRANSFORM_ROT_90;
	}

	if (isYUVSemiPlanar(img->format) || isYUVPlanar(img->format)) {
		if (v_scaling_factor > (2048 / (img->stride/16) - 4)) {
			HISI_FB_DEBUG(" v_scaling_factor out of limit !!!! \n");
			return 0;
		}
	}

	tlb_tag_org =  (transform & 0x7) |
		((is_tile ? 1 : 0) << 3) | ((rdma_stretch_enable ? 1 : 0) << 4);

	switch (tlb_tag_org) {
	case MMU_TLB_TAG_ORG_0x0:
		invalid_sel_val = 1;
		break;
	case MMU_TLB_TAG_ORG_0x1:
		invalid_sel_val = 1;
		break;
	case MMU_TLB_TAG_ORG_0x2:
		invalid_sel_val = 2;
		break;
	case MMU_TLB_TAG_ORG_0x3:
		invalid_sel_val = 2;
		break;
	case MMU_TLB_TAG_ORG_0x4:
		invalid_sel_val = 0;
		break;
	case MMU_TLB_TAG_ORG_0x7:
		invalid_sel_val = 0;
		break;

	case MMU_TLB_TAG_ORG_0x8:
		invalid_sel_val = 3;
		break;
	case MMU_TLB_TAG_ORG_0x9:
		invalid_sel_val = 3;
		break;
	case MMU_TLB_TAG_ORG_0xA:
		invalid_sel_val = 3;
		break;
	case MMU_TLB_TAG_ORG_0xB:
		invalid_sel_val = 3;
		break;
	case MMU_TLB_TAG_ORG_0xC:
		invalid_sel_val = 0;
		break;
	case MMU_TLB_TAG_ORG_0xF:
		invalid_sel_val = 0;
		break;

	case MMU_TLB_TAG_ORG_0x10:
		invalid_sel_val = 1;
		break;
	case MMU_TLB_TAG_ORG_0x11:
		invalid_sel_val = 1;
		break;
	case MMU_TLB_TAG_ORG_0x12:
		invalid_sel_val = 2;
		break;
	case MMU_TLB_TAG_ORG_0x13:
		invalid_sel_val = 2;
		break;
	case MMU_TLB_TAG_ORG_0x14:
		invalid_sel_val = 0;
		break;
	case MMU_TLB_TAG_ORG_0x17:
		invalid_sel_val = 0;
		break;

	case MMU_TLB_TAG_ORG_0x18:
		invalid_sel_val = 3;
		break;
	case MMU_TLB_TAG_ORG_0x19:
		invalid_sel_val = 3;
		break;
	case MMU_TLB_TAG_ORG_0x1A:
		invalid_sel_val = 3;
		break;
	case MMU_TLB_TAG_ORG_0x1B:
		invalid_sel_val = 3;
		break;
	case MMU_TLB_TAG_ORG_0x1C:
		invalid_sel_val = 0;
		break;
	case MMU_TLB_TAG_ORG_0x1F:
		invalid_sel_val = 0;
		break;

	default:
		invalid_sel_val = 0;
		HISI_FB_ERR("not support this tlb_tag_org(0x%x)!\n", tlb_tag_org);
		break;
	}

	return invalid_sel_val;
}
static int lcdc_fake_panel_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct hisi_panel_info *pinfo = NULL;
	struct device_node *np = NULL;

	if (hisi_fb_device_probe_defer(PANEL_NO)) {
		goto err_probe_defer;
	}

	HISI_FB_DEBUG("+.\n");

	np = of_find_compatible_node(NULL, NULL, DTS_COMP_LCDC_FAKE_PANEL);
	if (!np) {
		HISI_FB_ERR("NOT FOUND device node %s!\n", DTS_COMP_LCDC_FAKE_PANEL);
		goto err_return;
	}

	pdev->id = 1;
	/* init lcd info */
	pinfo = fake_panel_data.panel_info;
	memset(pinfo, 0, sizeof(struct hisi_panel_info));
	pinfo->xres = 1080;
	pinfo->yres = 1920;
	pinfo->width  = 61;
	pinfo->height = 109;
	pinfo->type = PANEL_NO;
	pinfo->orientation = LCD_PORTRAIT;
	pinfo->bpp = LCD_RGB888;
	pinfo->bgr_fmt = LCD_RGB;
	pinfo->bl_min = 1;
	pinfo->bl_max = 255;
	pinfo->bl_set_type = BL_SET_BY_PWM;
	pinfo->ifbc_type = IFBC_TYPE_NON;

	pinfo->vsync_ctrl_type = 0;
	pinfo->frc_enable = 0;
	pinfo->esd_enable = 0;
	pinfo->dirty_region_updt_support = 0;

	pinfo->sbl_support = 0;
	pinfo->smart_bl.strength_limit = 128;
	pinfo->smart_bl.calibration_a = 60;
	pinfo->smart_bl.calibration_b = 95;
	pinfo->smart_bl.calibration_c = 5;
	pinfo->smart_bl.calibration_d = 1;
	pinfo->smart_bl.t_filter_control = 5;
	pinfo->smart_bl.backlight_min = 480;
	pinfo->smart_bl.backlight_max = 4096;
	pinfo->smart_bl.backlight_scale = 0xff;
	pinfo->smart_bl.ambient_light_min = 14;
	pinfo->smart_bl.filter_a = 1738;
	pinfo->smart_bl.filter_b = 6;
	pinfo->smart_bl.logo_left = 0;
	pinfo->smart_bl.logo_top = 0;

	pinfo->ldi.h_back_porch = 11;
	pinfo->ldi.h_front_porch = 4;
	pinfo->ldi.h_pulse_width = 4;
	pinfo->ldi.v_back_porch = 10;
	pinfo->ldi.v_front_porch = 4;
	pinfo->ldi.v_pulse_width = 4;

	pinfo->mipi.lane_nums = DSI_4_LANES;
	pinfo->mipi.color_mode = DSI_24BITS_1;
	pinfo->mipi.vc = 0;
	pinfo->mipi.dsi_bit_clk = 480;

	pinfo->pxl_clk_rate = 150*1000000;

	/* alloc panel device data */
	ret = platform_device_add_data(pdev, &fake_panel_data,
		sizeof(struct hisi_fb_panel_data));
	if (ret) {
		HISI_FB_ERR("platform_device_add_data failed!\n");
		goto err_device_put;
	}

	hisi_fb_add_device(pdev);

	HISI_FB_DEBUG("-.\n");

	return 0;

err_device_put:
	platform_device_put(pdev);
err_return:
	return ret;
err_probe_defer:
	return -EPROBE_DEFER;
}
static int hisi_offlinecompser_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct hisi_panel_info *pinfo = NULL;
	struct hisi_fb_data_type *hisifd = NULL;
	struct platform_device *reg_dev = NULL;
	int i = 0;

	if (hisi_fb_device_probe_defer(PANEL_OFFLINECOMPOSER)) {
		goto err_probe_defer;
	}

	HISI_FB_DEBUG("+.\n");

	BUG_ON(pdev == NULL);

	pdev->id = 1;
	pinfo = hisi_offlinecomposer_panel_data.panel_info;
	memset(pinfo, 0, sizeof(struct hisi_panel_info));
	pinfo->xres = g_primary_lcd_xres;
	pinfo->yres = g_primary_lcd_yres;
	pinfo->type = PANEL_OFFLINECOMPOSER;

	/* alloc panel device data */
	ret = platform_device_add_data(pdev, &hisi_offlinecomposer_panel_data,
		sizeof(struct hisi_fb_panel_data));
	if (ret) {
		HISI_FB_ERR("platform_device_add_data failed!\n");
		goto err_device_put;
	}

	reg_dev = hisi_fb_add_device(pdev);
	if (!reg_dev) {
		HISI_FB_ERR("hisi_fb_add_device failed!\n");
		goto err_device_put;
	}

	hisifd = platform_get_drvdata(reg_dev);
	BUG_ON(hisifd == NULL);

	for (i = 0; i < HISI_DSS_OFFLINE_MAX_NUM; i++) {
		INIT_LIST_HEAD(&hisifd->offline_cmdlist_head[i]);
		hisifd->offline_wb_status[i] = e_status_idle;
		init_waitqueue_head(&hisifd->offline_writeback_wq[i]);
	}

	for (i = 0; i < HISI_DSS_OFFLINE_MAX_BLOCK; i++) {
		hisifd->block_rects[i] = (dss_rect_t *)kmalloc(sizeof(dss_rect_t), GFP_ATOMIC);
		if (!hisifd->block_rects[i]) {
			HISI_FB_ERR("block_rects[%d] failed to alloc!", i);
			goto err_device_put;
		}
	}

	hisifd->block_overlay = (dss_overlay_t *)kmalloc(sizeof(dss_overlay_t), GFP_ATOMIC);
	if (!hisifd->block_overlay) {
		HISI_FB_ERR("hisifd->block_overlay no mem.\n");
		goto err_device_put;
	}
	memset(hisifd->block_overlay, 0, sizeof(dss_overlay_t));

	for(i = 0; i < HISI_DSS_OFFLINE_MAX_LIST; i++){
		ret = cmdlist_alloc_one_list(&hisifd->cmdlist_node[i], hisifd->ion_client);
		if(ret < 0){
			HISI_FB_ERR("cmdlist_alloc_one_list no mem.\n");
			goto err_device_put;
		}
	}

	hisi_dss_offline_module_default(hisifd);
	hisifd->dss_module_resource_initialized = true;

	HISI_FB_DEBUG("-.\n");

	return 0;

err_device_put:
	platform_device_put(pdev);
	return ret;
err_probe_defer:
	return -EPROBE_DEFER;
}