君正T40添加lcd驱动

最近需要调试一个lcd驱动,在原先的驱动上面适配好了,为了分离出来好给后续单个适配,从新添加多一个驱动

君正T40添加一个lcd驱动
步骤:
1.添加驱动源文件
os/kernel/drivers/video/fbdev/ingenic/fb_v12/displays/panel-st7102-xiaomi.c

/*
 * Copyright (c) 2012 Ingenic Semiconductor Co., Ltd.
 *              http://www.ingenic.com/
 *
 *  dorado board lcd setup routines.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mm.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/pwm_backlight.h>
#include <linux/lcd.h>
#include <linux/of_gpio.h>
#include <soc/gpio.h>
#include <linux/fb.h>
#include <linux/backlight.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/ide.h>
#include <linux/irq.h>
#include <linux/errno.h>
#include <linux/ioctl.h>

#include "../ingenicfb.h"
#include "../jz_dsim.h"
#include "../jz_mipi_dsi/jz_mipi_dsih_hal.h"

#define ST7102_SUPPORT_LANE_2_FPS_60 0
#define ST7102_SUPPORT_LANE_2_FPS_30 1
#if defined(CONFIG_FB_ESD_CHECK_MODE)
#define ST7102_TE_IRQ_USE	1
#else
#define ST7102_TE_IRQ_USE	0
#endif
#define JZ_LCD_FPS_MAX  ST7102_SUPPORT_LANE_2_FPS_60

static struct dsi_cmd_packet st7102_xiaomi_cmd_list[] = {

#if 0
{0x39, 0x06, 0x00, {0xFF,0x77,0x01,0x00,0x00,0x13}},
{0x39, 0x02, 0x00, {0xEF,0x08}},
{0x39, 0x06, 0x00, {0xFF,0x77,0x01,0x00,0x00,0x10}},
{0x39, 0x03, 0x00, {0xC0,0x63,0x00}},
{0x39, 0x03, 0x00, {0xC1,0x09,0x02}},
{0x39, 0x03, 0x00, {0xC2,0x20,0x02}},
{0x39, 0x02, 0x00, {0xCC,0x18}},
{0x39, 0x11, 0x00, {0xB0,0x40,0x0E,0x51,0x0F,0x11,0x07,0x00,0x09,0x06,0x1E,0x04,0x12,0x11,0x64,0x29,0xDF}},
{0x39, 0x11, 0x00, {0xB1,0x40,0x07,0x4C,0x0A,0x0E,0x04,0x00,0x08,0x09,0x1D,0x01,0x0E,0x0C,0x6A,0x34,0xDF}},
{0x39, 0x06, 0x00, {0xFF,0x77,0x01,0x00,0x00,0x11}},
{0x39, 0x02, 0x00, {0xB0,0x30}},
{0x39, 0x02, 0x00, {0xB1,0x48}},
{0x39, 0x02, 0x00, {0xB2,0x80}},
{0x39, 0x02, 0x00, {0xB3,0x80}},
{0x39, 0x02, 0x00, {0xB5,0x4F}},
{0x39, 0x02, 0x00, {0xB7,0x85}},
{0x39, 0x02, 0x00, {0xB8,0x23}},
{0x39, 0x03, 0x00, {0xB9,0x22,0x13}},
{0x39, 0x02, 0x00, {0xBB,0x03}},
{0x39, 0x02, 0x00, {0xBC,0x10}},
{0x39, 0x02, 0x00, {0xC0,0x89}},
{0x39, 0x02, 0x00, {0xC1,0x78}},
{0x39, 0x02, 0x00, {0xC2,0x78}},
{0x39, 0x02, 0x00, {0xD0,0x88}},
{0x39, 0x04, 0x00, {0xE0,0x00,0x00,0x02}},
{0x39, 0x0C, 0x00, {0xE1,0x04,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x10,0x10}},
{0x39, 0x0E, 0x00, {0xE2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
{0x39, 0x05, 0x00, {0xE3,0x00,0x00,0x33,0x00}},
{0x39, 0x03, 0x00, {0xE4,0x22,0x00}},
{0x39, 0x11, 0x00, {0xE5,0x03,0x34,0xAF,0xB3,0x05,0x34,0xAF,0xB3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
{0x39, 0x05, 0x00, {0xE6,0x00,0x00,0x33,0x00}},
{0x39, 0x03, 0x00, {0xE7,0x22,0x00}},
{0x39, 0x11, 0x00, {0xE8,0x04,0x34,0xAF,0xB3,0x06,0x34,0xAF,0xB3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}},
{0x39, 0x08, 0x00, {0xEB,0x02,0x00,0x40,0x40,0x00,0x00,0x00}},
{0x39, 0x03, 0x00, {0xEC,0x00,0x00}},
{0x39, 0x11, 0x00, {0xED,0xFA,0x45,0x0B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB0,0x54,0xAF}},
{0x39, 0x07, 0x00, {0xEF,0x08,0x08,0x08,0x45,0x3F,0x54}},
{0x39, 0x06, 0x00, {0xFF,0x77,0x01,0x00,0x00,0x13}},
{0x39, 0x03, 0x00, {0xE6,0x16,0x7c}},
{0x39, 0x03, 0x00, {0xe8,0x00,0x0E}},
{0x39, 0x06, 0x00, {0xFF,0x77,0x01,0x00,0x00,0x00}},
{0x15, 0x11, 0x00, { 0x00 }}, 	//Sleep out
{0x99, 120, 0x00, {0x00}},
{0x39, 0x06, 0x00, {0xFF,0x77,0x01,0x00,0x00,0x13}},
{0x39, 0x03, 0x00, {0xe8,0x00,0x0C}},
{0x99, 10, 0x00, {0x00}},
{0x39, 0x03, 0x00, {0xe8,0x00,0x00}},
{0x39, 0x06, 0x00, {0xFF,0x77,0x01,0x00,0x00,0x00}},
{0x39, 0x02, 0x00, {0x35,0x00}},
{0x39, 0x06, 0x00, {0xFF,0x77,0x01,0x00,0x00,0x00}},
{0x15, 0x29, 0x00, { 0x00}},  	// Display On
{0x99, 20, 0x00, {0x00}},		//delay 50ms
{0x39, 0x06, 0x00, {0xFF,0x77,0x01,0x00,0x00,0x10}},
{0x39, 0x02, 0x00, {0xE5,0x00}},
#else


//{0x99, 50, 0x00, {0x00}},  //sleep 5ms

{0x05, 0x10, 0x00 },
{0x05, 0x28, 0x00 },

{0x29, 0x04, 0x00, { 0x99, 0x71, 0x02, 0xa2, } },
{0x29, 0x04, 0x00, { 0x99, 0x71, 0x02, 0xa3, } },
{0x29, 0x04, 0x00, { 0x99, 0x71, 0x02, 0xa4, } },

{0x39, 0x02, 0x00, { 0x78, 0x21, } },
{0x39, 0x02, 0x00, { 0x79, 0xCF, } },
//2lane
//{0x39, 0x02, 0x00, { 0xA4, 0x31, } },

{0x39, 0x08, 0x00, { 0xB0, 0x22, 0x57, 0x1E, 0x61, 0x2F, 0x57, 0x61, } },

{0x39, 0x03, 0x00, { 0xB7, 0x64, 0x64, } },

{0x39, 0x03, 0x00, { 0xBF, 0x6e, 0x6e, } },
{0x29, 0x26, 0x00, { 0xC8, 0x00, 0x00, 0x13, 0x23, 0x3E, 0x00, 0x6A, 0x03, 0xB0, 0x06, 0x11, 0x0F, 0x07, 0x85, 0x03, 0x21, 0xD5, 0x01, 0x18, 0x00, 0x22, 0x56, 0x0F, 0x98, 0x0A, 0x32, 0xF8, 0x0D, 0x48, 0x0F, 0xF3, 0x80, 0x0F, 0xAC, 0xC1, 0x03, 0xC4, } },

{0x29, 0x26, 0x00, { 0xC9, 0x00, 0x00, 0x13, 0x23, 0x3E, 0x00, 0x6A, 0x03, 0xB0, 0x06, 0x11, 0x0F, 0x07, 0x85, 0x03, 0x21, 0xD5, 0x01, 0x18, 0x00, 0x22, 0x56, 0x0F, 0x98, 0x0A, 0x32, 0xF8, 0x0D, 0x48, 0x0F, 0xF3, 0x80, 0x0F, 0xAC, 0xC1, 0x03, 0xC4, } },

{0x39, 0x07, 0x00, { 0xD7, 0x10, 0x0C, 0x77, 0x19, 0xE0, 0xE0, } },
{0x39, 0x21, 0x00, { 0xA3, 0x40, 0x03, 0x80, 0xCF, 0x44, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x6F, 0x00, 0x1A, 0x00, 0x45, 0x05, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x02, 0x20, 0x52, 0x00, 0x05, 0x00, 0x00, 0xFF, } },
{0x39, 0x2D, 0x00, { 0xA6, 0x02, 0x00, 0x24, 0x55, 0x35, 0x00, 0x38, 0x00, 0x5E, 0x5E, 0x00, 0x24, 0x55,0x36, 0x00, 0x37, 0x00, 0x5E, 0x5E, 0x02, 0xAC, 0x51, 0x3A, 0x00, 0x00, 0x00, 0x5E, 0x5E, 0x00, 0xAC, 0x11, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x5E, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, } },

{0x39, 0x31, 0x00, { 0xA7, 0x19, 0x19, 0x00, 0x64, 0x40, 0x07, 0x16, 0x40, 0x00, 0x04, 0x03, 0x5E, 0x5E, 0x00, 0x64, 0x40, 0x25, 0x34, 0x00, 0x00, 0x02, 0x01, 0x5E, 0x5E, 0x00, 0x64, 0x40, 0x4B, 0x5A, 0x00, 0x00, 0x02, 0x01, 0x5E, 0x5E, 0x00, 0x24, 0x40, 0x69, 0x78, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x5E, 0x00, 0x44, } },

{0x39, 0x26, 0x00, { 0xAC, 0x08, 0x0A, 0x11, 0x00, 0x13, 0x03, 0x1B,0x18, 0x06, 0x1A, 0x19, 0x1B, 0x1B,0x1B, 0x18, 0x1B, 0x09,0x0B, 0x10, 0x02, 0x12, 0x01, 0x1B, 0x18, 0x06, 0x1A, 0x19, 0x1B, 0x1B, 0x1B, 0x18, 0x1B, 0xFF, 0x67, 0xFF, 0x67, 0x00, } },
{0x39, 0x08, 0x00, { 0xAD, 0xCC, 0x40, 0x46, 0x11, 0x04, 0x6F, 0x6F, } },
{0x39, 0x0F, 0x00, { 0xE8, 0x30, 0x07, 0x00, 0x7A, 0x7A, 0x9C, 0x00, 0xE2, 0x04, 0x00, 0x00, 0x00, 0x00, 0xEF, } },
{0x29, 0x03, 0x00, { 0x75, 0x03, 0x04, } },
{0x39, 0x22, 0x00, { 0xE7, 0x8B, 0x3C, 0x00, 0x0C, 0xF0, 0x5D, 0x00, 0x5D, 0x00, 0x5D, 0x00, 0x5D, 0x00, 0xFF, 0x00, 0x08, 0x7B, 0x00, 0x00, 0xC8, 0x6A, 0x5A, 0x08, 0x1A, 0x3C, 0x00, 0x91, 0x01, 0xCC, 0x01, 0x7F, 0xF0, 0x22, } },
{0x39, 0x0A, 0x00, { 0xE9, 0x4C, 0x7F, 0x08, 0x07, 0x1A, 0x7A, 0x22, 0x1A, 0x33, } },

{0x05, 0x11, 0x00 }, 	//Sleep out
{0x99, 120, 0x00, {0x00}},		//delay 250ms

{0x05, 0x29, 0x00 },  	// Display On

{0x29, 0x02, 0x00, { 0x35, 0x00, } },
//{0x39, 0x02, 0x00, { 0xB5, 0x85, } },
#endif
};

struct board_gpio {
	short gpio;
	short active_level;
};

struct panel_dev {
	/* ingenic frame buffer */
	struct device *dev;
	struct lcd_panel *panel;

	/* common lcd framework */
	struct lcd_device *lcd;
	struct backlight_device *backlight;
	int power;

	struct regulator *vcc;
	struct board_gpio vdd_en;
	struct board_gpio bl;
	struct board_gpio rst;
	struct board_gpio oled;
	struct board_gpio lcd_pwm;

	struct mipi_dsim_lcd_device *dsim_dev;
};

struct panel_dev *panel;

#define lcd_to_master(a)     (a->dsim_dev->master)
#define lcd_to_master_ops(a) ((lcd_to_master(a))->master_ops)

#define DEV_NAME "gpio_irq"
#define GPIO_LCD_TE GPIO_PC(24)
struct gpio_irq_st
{
    int gpio;
    unsigned int irq_num; //中断号
    unsigned char value;  //键值
};
// static int te_reset_flag = 0;
static int sg_suspend_flag = 1;
static int sg_init_ignore_cnt = 0;
static volatile unsigned long long lcd_te_irq_ts = 0;
static struct gpio_irq_st gpio_data = {GPIO_LCD_TE, 0, 0};

struct st7102_xiaomi {
	struct device *dev;
	unsigned int power;
	unsigned int id;

	struct lcd_device *ld;
	struct backlight_device *bd;

	struct mipi_dsim_lcd_device *dsim_dev;
};

struct fb_videomode jzfb_st7102_xiaomi_videomode[] = {
	//[0] 4lane 60fps
	{
		.name = "st7102_xiaomi",
		.refresh = 30,//现在不支持60fps
		.xres = 480,
		.yres = 960,
		.pixclock = KHZ2PICOS(56000),  //60

		.left_margin = 40,
		.right_margin = 80,
		.hsync_len = 2,//2

		.upper_margin = 10,
		.lower_margin = 215,//215
		.vsync_len = 2,

		.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
		.vmode = FB_VMODE_NONINTERLACED,
		.flag = 0
	},

	{
		.name = "st7102_xiaomi",
		.refresh = 30,
		.xres = 480,
		.yres = 960,
		.pixclock = KHZ2PICOS(56000),  //60//56000
		.left_margin = 40,
		.right_margin = 80,
		.hsync_len = 2,//2

		.upper_margin = 10,
		.lower_margin = 215,
		.vsync_len = 2,

		.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
		.vmode = FB_VMODE_NONINTERLACED,
		.flag = 0
	},

};

struct jzdsi_data jzdsi_pdata = {
	.modes = &jzfb_st7102_xiaomi_videomode[JZ_LCD_FPS_MAX],
#ifdef CONFIG_MIPI_2LANE
	.video_config.no_of_lanes = 2,
#endif
#ifdef CONFIG_MIPI_4LANE
	.video_config.no_of_lanes = 4,
#endif
	.video_config.virtual_channel = 0,
	.video_config.color_coding = COLOR_CODE_24BIT,
#if 0
	.video_config.video_mode = VIDEO_NON_BURST_WITH_SYNC_PULSES,
	// .video_config.video_mode = VIDEO_NON_BURST_WITH_SYNC_EVENTS,
#else
	.video_config.video_mode = VIDEO_BURST_WITH_SYNC_PULSES,
#endif
	.video_config.receive_ack_packets = 0,	/* enable receiving of ack packets */
	/*loosely: R0R1R2R3R4R5__G0G1G2G3G4G5G6__B0B1B2B3B4B5B6,
	 * not loosely: R0R1R2R3R4R5G0G1G2G3G4G5B0B1B2B3B4B5*/
	.video_config.is_18_loosely = 0,
	.video_config.data_en_polarity = 1,

	.dsi_config.max_lanes = 4,//4
	.dsi_config.max_hs_to_lp_cycles = 100,
	.dsi_config.max_lp_to_hs_cycles = 40,
	.dsi_config.max_bta_cycles = 4095,
	.dsi_config.color_mode_polarity = 1,
	.dsi_config.shut_down_polarity = 1,
	.dsi_config.max_bps = 460,//460
	//	.max_bps = 650,  // 650 Mbps
	.bpp_info = 24,

};

struct tft_config st7102_xiaomi_cfg = {
	.pix_clk_inv = 0,
	.de_dl = 0,
	.sync_dl = 0,
	.color_even = TFT_LCD_COLOR_EVEN_RGB,
	.color_odd = TFT_LCD_COLOR_ODD_RGB,
	.mode = TFT_LCD_MODE_PARALLEL_888,
};

struct lcd_panel lcd_panel = {
	.num_modes = 1,
	.modes = &jzfb_st7102_xiaomi_videomode[JZ_LCD_FPS_MAX],
	.dsi_pdata = &jzdsi_pdata,
	//.smart_config = &smart_cfg,
	.tft_config = &st7102_xiaomi_cfg,

	.lcd_type = LCD_TYPE_TFT ,
	.width = 480,
	.height = 960,
	//.bpp = 24,

	//.pixclk_falling_edge = 0,
	//.data_enable_active_low = 0,

};

/**************************************************************************************************/
#ifdef CONFIG_BACKLIGHT_PWM

static struct platform_pwm_backlight_data backlight_data = {
	.pwm_id		= 0,
	.max_brightness	= 255,
	.dft_brightness	= 100,
	.pwm_period_ns	= 30000,
};

struct platform_device backlight_device = {
	.name		= "pwm-backlight",
	.dev		= {
		.platform_data	= &backlight_data,
	},
};

#endif

#define POWER_IS_ON(pwr)    ((pwr) <= FB_BLANK_NORMAL)
static int panel_set_power(struct lcd_device *lcd, int power)
{
	return 0;
}

static int panel_get_power(struct lcd_device *lcd)
{
	struct panel_dev *panel = lcd_get_data(lcd);

	return panel->power;
}

static struct lcd_ops panel_lcd_ops = {
	.early_set_power = panel_set_power,
	.set_power = panel_set_power,
	.get_power = panel_get_power,
};

static unsigned long long get_ms_time(void) {
    struct timeval ts;
    do_gettimeofday(&ts);
    return ((unsigned long long)ts.tv_sec * 1000) + (ts.tv_usec / 1000);
}

//中断回调函数
static irqreturn_t key_handler(int irq, void *dev_id)
{
	lcd_te_irq_ts = get_ms_time();
    struct gpio_irq_st *dev = (struct gpio_irq_st *)dev_id;
    // printk("key%d irq\n",dev->gpio);
    return IRQ_RETVAL(IRQ_HANDLED);
}

int lcd_te_irq_init(void)
{
    int ret;
    ret = gpio_request(gpio_data.gpio, DEV_NAME);
    if (ret < 0)
        printk("gpio_request %d error!\n", gpio_data.gpio);
    gpio_direction_input(gpio_data.gpio);

    gpio_data.irq_num = gpio_to_irq(gpio_data.gpio);
    if (gpio_data.irq_num < 0)
        printk("gpio_to_irq error!\n");
    ret = request_irq(gpio_data.irq_num, key_handler, IRQF_TRIGGER_FALLING, DEV_NAME, &gpio_data);
    if (ret < 0)
    {
        printk("irq %d request failed!\r\n", gpio_data.irq_num);
    }
	printk("lcd_te_irq_init\n");
    return 0;
}

static int esd_check(void)
{
	static int loop = 0;
    unsigned char buf[150];
	memset(buf, 0, sizeof(buf));
	struct dsi_master_ops *ops = lcd_to_master_ops(panel);
	struct dsi_device *dsi = lcd_to_master(panel);

	if(sg_suspend_flag) {
		return 0;
	}
	if(sg_init_ignore_cnt) {
		sg_init_ignore_cnt--;
		return 0;
	}
#if ST7102_TE_IRQ_USE
	if(get_ms_time() - lcd_te_irq_ts > 1000) {
		printk("LEC TE reset\n");
		return -1;
	}
#endif

	msleep(20);
	mipi_dsih_gen_rd_packet(dsi, 0, 0x14, 0, 0x0a, 4, buf);
	printk("read buffer: \ncmd: 0x%x, parameter:0x%x,0x%x,0x%x,0x%x\n", 0x0a, buf[0], buf[1], buf[2], buf[3]);
    //复位
	if(0x9c != buf[0])  {
		printk("0A reset\n");
       return -1;
	}

	// mipi_dsih_gen_rd_packet(dsi, 0, 0x14, 0, 0xE5, 4, buf);
	// printk("read buffer: \ncmd: 0x%x, parameter:0x%x,0x%x,0x%x,0x%x\n", 0xE5, buf[0], buf[1], buf[2], buf[3]);
    // //复位
	// if(0x00 != buf[0])
	// {
	// 	printk("E5 reset\n");
    //    return -1;
	// }

	unsigned int value = 0;
	unsigned int addr = 0xb00030b0;
	value = *(volatile unsigned int*)(addr);
	printk("dsi phy address 0x100030b0 = 0x%x\n", value);

	addr = 0xb00030bc;
	value = *(volatile unsigned int*)(addr);
	printk("dsi phy address 0x100030bc = 0x%x\n", value);
	if(value != 0) {
		printk("dsi phy 0x100030bc reset\n");
		return -1;
	}

	addr = 0xb00030c0;
	value = *(volatile unsigned int*)(addr);
	printk("dsi phy address 0x100030c0 = 0x%x\n", value);
	if(value != 0) {
		printk("dsi phy 0xb00030c0 reset\n");
		return -1;
	}
	// loop++;
	// if(loop >= 10) {
	// 	loop = 0;
	// 	printk("timeout reset\n");
	// 	return -1;
	// }
	return 0;

}

static int of_panel_parse(struct device *dev)
{
	struct panel_dev *panel = dev_get_drvdata(dev);
	struct device_node *np = dev->of_node;
	enum of_gpio_flags flags;
	int ret = 0;

	panel->bl.gpio = of_get_named_gpio_flags(np, "ingenic,bl-gpio", 0, &flags);
	if (gpio_is_valid(panel->bl.gpio)) {
		panel->bl.active_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1;
		ret = devm_gpio_request(dev, panel->bl.gpio, "backlight");
		if (ret < 0) {
			dev_err(dev, "Failed to request backlight pin!\n");
			return ret;
		}
	} else
		dev_warn(dev, "invalid gpio backlight.gpio: %d\n", panel->bl.gpio);

	panel->rst.gpio = of_get_named_gpio_flags(np, "ingenic,rst-gpio", 0, &flags);
	if (gpio_is_valid(panel->rst.gpio)) {
		panel->rst.active_level = (flags & OF_GPIO_ACTIVE_LOW) ? 0 : 1;
		ret = devm_gpio_request(dev, panel->rst.gpio, "reset");
		if (ret < 0) {
			dev_err(dev, "Failed to request rst pin!\n");
			return ret;
		}
	} else {
		dev_warn(dev, "invalid gpio rst.gpio: %d\n", panel->rst.gpio);
	}

	return 0;
}

static void panel_dev_panel_init(struct panel_dev *lcd)
{
	static int boot_flag = 0;
	int i, j;
	struct dsi_master_ops *ops = lcd_to_master_ops(lcd);
	struct dsi_device *dsi = lcd_to_master(lcd);
	unsigned char buf[MAX_WORD_COUNT];
	unsigned char dsi_command_param[MAX_WORD_COUNT] = {0};

	memset(buf, 0, sizeof(buf));
#if 0
	//set maximum transfer datasize
	dsi_command_param[0] = 4;  //lsb
	dsi_command_param[1] = 0;  //msb
	mipi_dsih_gen_wr_packet(dsi, 0, 0x37, dsi_command_param, 2);
	printk("set maximum return packet size ok now...\n");

	//read display ID
	mipi_dsih_gen_rd_packet(dsi, 0, 0x14, 0, 0x04, 4, buf);
	printk("read buffer: \ncmd: 0x04, parameter:0x%x,0x%x,0x%x,0x%x\n", buf[0], buf[1], buf[2], buf[3]);

#endif


#if 0
    struct dsi_cmd_packet list[] =
	{
		{0x05, 0x10, 0x00},//{0x05, 0x01, 0x00},
	};
	if(boot_flag) { //ESD复位时做一个软复位,首次上电不需要
		msleep(120);
		ops->cmd_write(dsi, list[0]);
		msleep(120);
	}
#endif

	for (i = 0; i < ARRAY_SIZE(st7102_xiaomi_cmd_list); i++) {
		if (st7102_xiaomi_cmd_list[i].packet_type == 0x99) {
			/* printk("\nsleep now. time: %dms\n", st7102_xiaomi_cmd_list[i].cmd0_or_wc_lsb+st7102_xiaomi_cmd_list[i].cmd1_or_wc_msb); */
			if (st7102_xiaomi_cmd_list[i].cmd0_or_wc_lsb+st7102_xiaomi_cmd_list[i].cmd1_or_wc_msb == 510)
				msleep(600);
			else
				msleep(st7102_xiaomi_cmd_list[i].cmd0_or_wc_lsb+st7102_xiaomi_cmd_list[i].cmd1_or_wc_msb);
			continue;
		}

		ops->cmd_write(dsi, st7102_xiaomi_cmd_list[i]);

#if 0
		//short packet read here
		if (st7102_xiaomi_cmd_list[i].packet_type == 0x15) {
			//we read command here, see whether we send command configure ok.
			mipi_dsih_gen_rd_packet(dsi, 0, 0x14, 0, st7102_xiaomi_cmd_list[i].cmd0_or_wc_lsb, 4, buf);
			printk("read buffer: \ncmd: 0x%x, parameter:0x%x,0x%x,0x%x,0x%x\n", st7102_xiaomi_cmd_list[i].cmd0_or_wc_lsb, buf[0], buf[1], buf[2], buf[3]);
		}
		//long packet read here
		if (st7102_xiaomi_cmd_list[i].packet_type == 0x39 || st7102_xiaomi_cmd_list[i].packet_type == 0x29) {
			//we read command here, see whether we send command configure ok.
			printk("return value : %d\t", mipi_dsih_gen_rd_packet(dsi, 0, 0x14, 0, st7102_xiaomi_cmd_list[i].cmd_data[0], 110, buf));
			printk("read buffer(data_type: 0x%x, cmd: 0x%x)\n", st7102_xiaomi_cmd_list[i].packet_type, st7102_xiaomi_cmd_list[i].cmd_data[0]);
			for (j = 0 ; j < 110; j++)
				printk("paramter list[%d]:0x%x\t", j, buf[j]);
			printk("\n");
		}
#endif
		memset(buf, 0, sizeof(buf));
	}
	boot_flag = 1;
}

static int panel_dev_ioctl(struct mipi_dsim_lcd_device *dsim_dev, int cmd)
{
	return esd_check();
}

static void panel_dev_set_sequence(struct mipi_dsim_lcd_device *dsim_dev)
{
	struct st7102_xiaomi *lcd = dev_get_drvdata(&dsim_dev->dev);

	dev_info(panel->dev, "panel_dev_panel_init\n");
	panel_dev_panel_init(panel);
    msleep(120);
	sg_suspend_flag = 0;
	dev_info(panel->dev, "panel_dev_panel_init done!\n");
	lcd->power = FB_BLANK_UNBLANK;
}

static void panel_dev_power_on(struct mipi_dsim_lcd_device *dsim_dev, int power)
{
	static int boot_flag  = 0;
	struct panel_dev *panel_st7102_xiaomi = dev_get_drvdata(panel->dev);


    if( 0 <= panel_st7102_xiaomi->bl.gpio <= 22)
	{
		// 1: 1.8V
		// 0: 3.3v
		jzgpio_set_work_voltage(GPIO_PORT_A,1);
	}

	if (power == 1) {
		//reset
		dev_info(panel->dev, "Panel power on reset\n");
		if (gpio_is_valid(panel_st7102_xiaomi->rst.gpio)) {

			gpio_direction_output(panel_st7102_xiaomi->rst.gpio, !panel_st7102_xiaomi->rst.active_level);
			msleep(120);
			gpio_direction_output(panel_st7102_xiaomi->rst.gpio, panel_st7102_xiaomi->rst.active_level);
			msleep(50);
			gpio_direction_output(panel_st7102_xiaomi->rst.gpio, !panel_st7102_xiaomi->rst.active_level);
			msleep(120);
			// msleep(20);
			boot_flag = 1;
		}
		//open backlight
		if (gpio_is_valid(panel_st7102_xiaomi->bl.gpio)) {
			gpio_direction_output(panel_st7102_xiaomi->bl.gpio, panel_st7102_xiaomi->bl.active_level);
		}
	} else {
		dev_info(panel->dev, "Panel power on open backlight\n");
		if (gpio_is_valid(panel_st7102_xiaomi->bl.gpio)) {
			gpio_direction_output(panel_st7102_xiaomi->bl.gpio, panel_st7102_xiaomi->bl.active_level);
		}
	}

}

static int panel_dev_probe(struct mipi_dsim_lcd_device *dsim_dev)
{
	struct st7102_xiaomi *lcd;

	lcd = devm_kzalloc(&dsim_dev->dev, sizeof(struct st7102_xiaomi), GFP_KERNEL);
	if (IS_ERR_OR_NULL(lcd)) {
		dev_err(&dsim_dev->dev, "Failed to allocate st7102_xiaomi structure!\n");
		return -ENOMEM;
	}

	lcd->dsim_dev = dsim_dev;
	lcd->dev = &dsim_dev->dev;

	lcd->ld = lcd_device_register("st7102_xiaomi", lcd->dev, lcd,
								  &panel_lcd_ops);
	if (IS_ERR(lcd->ld)) {
		dev_err(lcd->dev, "Failed to register lcd ops.");
		return PTR_ERR(lcd->ld);
	}

	dev_set_drvdata(&dsim_dev->dev, lcd);

	dev_dbg(lcd->dev, "Now probed st7102_xiaomi panel.\n");
#if ST7102_TE_IRQ_USE
	lcd_te_irq_init();
#endif
	panel->dsim_dev = dsim_dev;

	return 0;
}

static int panel_dev_suspend(struct mipi_dsim_lcd_device *dsim_dev)
{
	struct board_gpio *vdd_en = &panel->bl;
	dev_info(panel->dev, "panel_dev_suspend\n");
	sg_suspend_flag = 1;
	sg_init_ignore_cnt = 3;

	if (gpio_is_valid(vdd_en->gpio)) {
		gpio_direction_output(vdd_en->gpio, !vdd_en->active_level);
	}
	return 0;
}

static int panel_dev_resume(struct mipi_dsim_lcd_device *dsim_dev)
{
	struct board_gpio *vdd_en = &panel->bl;
	dev_info(panel->dev, "panel_dev_resume\n");
	if (gpio_is_valid(vdd_en->gpio)) {
		gpio_direction_output(vdd_en->gpio, vdd_en->active_level);
	}
	return 0;
}

static struct mipi_dsim_lcd_driver panel_dev_dsim_ddi_driver = {
	.name = "st7102_xiaomi",
	.id = -1,

	.power_on = panel_dev_power_on,
	.set_sequence = panel_dev_set_sequence,
	.probe = panel_dev_probe,
	.suspend = panel_dev_suspend,
	.resume = panel_dev_resume,
	.ioctl = panel_dev_ioctl,
};

static struct mipi_dsim_lcd_device panel_dev_device = {
	.name = "st7102_xiaomi",
	.id = 0,
};

/**
 * @panel_probe
 *
 *   1. register to ingenicfb
 *   2. register to lcd
 *   3. register to backlight if possible
 *
 * @pdev
 *
 * @return -
 */
static int panel_probe(struct platform_device *pdev)
{
	int ret = 0;
    
	panel = kzalloc(sizeof(struct panel_dev), GFP_KERNEL);
	if (IS_ERR_OR_NULL(panel)) {
		dev_err(&pdev->dev, "Failed to alloc memory!\n");
		return -ENOMEM;
	}
	panel->dev = &pdev->dev;
	dev_set_drvdata(&pdev->dev, panel);

	ret = of_panel_parse(&pdev->dev);
	if (ret < 0)
		goto err_of_parse;

	/* register to mipi-dsi devicelist*/
	mipi_dsi_register_lcd_device(&panel_dev_device);
	mipi_dsi_register_lcd_driver(&panel_dev_dsim_ddi_driver);

	ret = ingenicfb_register_panel(&lcd_panel);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to register lcd panel!\n");
		goto err_of_parse;
	}

	return 0;
err_of_parse:
	kfree(panel);
	return ret;
}

static int panel_remove(struct platform_device *dev)
{
	if (NULL != panel)
		kfree(panel);

	return 0;
}

#ifdef CONFIG_PM
static int panel_suspend(struct device *dev)
{
	struct panel_dev *panel = dev_get_drvdata(dev);

	panel_set_power(panel->lcd, FB_BLANK_POWERDOWN);
	return 0;
}

static int panel_resume(struct device *dev)
{
	struct panel_dev *panel = dev_get_drvdata(dev);

	panel_set_power(panel->lcd, FB_BLANK_UNBLANK);
	return 0;
}

static const struct dev_pm_ops panel_pm_ops = {
	.suspend = panel_suspend,
	.resume = panel_resume,
};
#endif
static const struct of_device_id panel_of_match[] = {
	{ .compatible = "ingenic,st7102_xiaomi", },
	{ .compatible = "st7102_xiaomi", },
	{},
};

static struct platform_driver panel_driver = {
	.probe = panel_probe,
	.remove = panel_remove,
	.driver = {
		.name = "st7102_xiaomi",
		.of_match_table = panel_of_match,
#ifdef CONFIG_PM
		.pm = &panel_pm_ops,
#endif
	},
};

// module_platform_driver(panel_driver);
static int __init panel_driver_init(void)
{
	platform_driver_register(&panel_driver);
	return 0;
}

static void __exit panel_driver_exit(void)
{
	platform_driver_unregister(&panel_driver);
}

module_init(panel_driver_init);
module_exit(panel_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kevin");
MODULE_DESCRIPTION("Kernel panel driver");

2.Kconfig加进来该模块,路径:os/kernel/drivers/video/fbdev/ingenic/fb_v12/displays/Kconfig

menuconfig FB_INGENIC_DISPLAYS_V12
	tristate "Supported lcd panels"
	depends on FB_INGENIC_V12
	select BACKLIGHT_LCD_SUPPORT
	select LCD_CLASS_DEVICE
	select BACKLIGHT_CLASS_DEVICE


config PANEL_V12_Y88249
	tristate "lcd panel y88249"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel y88249, for ingenicfb drivers.

config PANEL_V12_KD050HDFIA019
	tristate "lcd panel kd050hdfia019"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel kd050hdfia019, for ingenicfb drivers.

config PANEL_V12_MA0060
	tristate "lcd panel MA0060"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel MA0060, for ingenicfb drivers.

config PANEL_V12_TL040WVS03CT
	tristate "lcd panel tl040wvs03ct"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel tl040wvs03ct, for ingenicfb drivers.

config PANEL_V12_TL040HDS01CT
	tristate "lcd panel tl040hds01ct"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel tl040hds01ct, for ingenicfb drivers.

config PANEL_V12_JD9161Z
	tristate "lcd panel JD9161Z"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel JD9161Z, for ingenicfb drivers.

config PANEL_V12_ST7701S
	tristate "lcd panel ST7701S"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel ST7701S, for ingenicfb drivers.

config PANEL_V12_YTS500XLAI
	tristate "lcd panel YTS500XLAI"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel YTS500XLAI, for ingenicfb drivers.

config PANEL_V12_YLYM286A
	tristate "lcd panel ylym286a"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel ylym286a with bridge lt9211, for ingenicfb drivers.

config PANEL_X2000_KD035HVFBD037
	tristate "SLCD KD035HVFBD037 with control IC otm4802a (320x480)"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel KD035HVFBD037, for ingenicfb drivers.

config PANEL_BM8766
	tristate "TFT BM8766 (800x480)"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel BM8766, for ingenicfb drivers.

config PANEL_TRULY240240
	tristate "SLCD TRULY240240 (240x240)"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel TRULY240240, for ingenicfb drivers.

config PANEL_ST7789V240320
	tristate "SLCD ST7789V240320 (240x320)"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel TRULY240240, for ingenicfb drivers.

config PANEL_EK79007
	tristate "TFT EK79007 (1024x600)"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel EK79007, for ingenicfb drivers.

config PANEL_ST7703
	tristate "TFT ST7703 (1280*720)"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel ST7703, for ingenicfb drivers.

config PANEL_ST7701SN
        tristate "TFT ST7701SN (480*800)"
        depends on FB_INGENIC_DISPLAYS_V12
        help
                lcd panel ST7701SN, for ingenicfb drivers.

config PANEL_OTA7290B
	tristate "TFT OTA7290B (1024*600 )"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel OTA7290B, for ingenicfb drivers.

config PANEL_ST7701S
	tristate "TFT ST7701S"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel ST7701S, for ingenicfb drivers.

config PANEL_VX071FHP
	tristate "TFT VX071FHP"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel VX071FHP, for ingenicfb drivers.

config PANEL_JD9852
	tristate "TFT JD9852"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel VX071FHP, for ingenicfb drivers.

config PANEL_GC9503V
	tristate "TFT GC9503V (480*800)"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel GC9503V, for ingenicfb drivers.

config PANEL_ST7701S_XIAOMI
	tristate "TFT ST7701S XIAOMI"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel ST7701S, for ingenicfb drivers.

config PANEL_ST7102_XIAOMI
	tristate "TFT ST7102 XIAOMI"
	depends on FB_INGENIC_DISPLAYS_V12
	help
		lcd panel ST7102, for ingenicfb drivers.

3.Makefile添加该新驱动,路径:os/kernel/drivers/video/fbdev/ingenic/fb_v12/displays/Makefile

obj-$(CONFIG_PANEL_V12_Y88249) += panel-y88249.o
obj-$(CONFIG_PANEL_V12_KD050HDFIA019) += panel-kd050hdfia019.o
obj-$(CONFIG_PANEL_V12_MA0060) += panel-ma0060.o
obj-$(CONFIG_PANEL_V12_TL040WVS03CT) += panel-tl040wvs03ct.o
obj-$(CONFIG_PANEL_V12_TL040HDS01CT) += panel-tl040hds01ct.o
obj-$(CONFIG_PANEL_V12_JD9161Z) += panel-jd9161z.o
obj-$(CONFIG_PANEL_V12_ST7701S) += panel-st7701s.o
obj-$(CONFIG_PANEL_V12_YTS500XLAI) += panel-yts500xlai.o
obj-$(CONFIG_PANEL_V12_YLYM286A) += panel-ylym286a.o
obj-$(CONFIG_PANEL_X2000_KD035HVFBD037)	+= panel-kd035hvfbd037.o
obj-$(CONFIG_PANEL_BM8766)	+= panel-bm8766.o
obj-$(CONFIG_PANEL_TRULY240240)	+= panel-truly_240_240.o
obj-$(CONFIG_PANEL_ST7789V240320)	+= panel-st7789v_240_320.o
obj-$(CONFIG_PANEL_EK79007)	+= panel-ek79007.o
obj-$(CONFIG_PANEL_ST7703)	+= panel-st7703.o
obj-$(CONFIG_PANEL_ST7701SN)     += panel-st7701sn.o
obj-$(CONFIG_PANEL_OTA7290B)	+= panel-ota7290b.o
obj-$(CONFIG_PANEL_ST7701S)	+= panel-st7701s.o
obj-$(CONFIG_PANEL_VX071FHP)	+= panel-vx071fhp.o
obj-$(CONFIG_PANEL_JD9852)	+= panel-jd9852.o
obj-$(CONFIG_PANEL_GC9503V)	+= panel-gc9503v.o
obj-$(CONFIG_PANEL_ST7701S_XIAOMI)	+= panel-st7701s-xiaomi.o
obj-$(CONFIG_PANEL_ST7102_XIAOMI) += panel-st7102-xiaomi.o


4.dts添加该驱动名字用于匹配,路径:os/kernel/arch/mips/boot/dts/ingenic/shark.dts

/dts-v1/;

#include <dt-bindings/input/input.h>
#include "t40.dtsi"
#include <dt-bindings/interrupt-controller/irq.h>

/ {
	compatible = "ingenic,shark", "ingenic,t40";

	mmc0_pwrseq: mmc0_pwrseq {
		compatible = "mmc-pwrseq-simple";
		reset-gpios = <&gpd 27 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
	};
};

&uart0 {
	status = "disable";
};

&uart1 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&uart1_pb>;
};

&uart2 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&uart2_pb>;
};

&uart3 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&uart3_pc>;
};

&i2c0 {
	pinctrl-0 = <&i2c0_pa>;
	pinctrl-names = "default";
	status = "okay";
};

&i2c1 {
	pinctrl-0 = <&i2c1_pa>;
	pinctrl-names = "default";
	status = "okay";
};

&i2c2 {
	pinctrl-0 = <&i2c2_pb>;
	pinctrl-names = "default";
	status = "disable";
};

&i2c3 {
	pinctrl-0 = <&i2c3_pa>;
	pinctrl-names = "default";
	status = "okay";
};

&cpufreq {
	status = "okay";
	operating-points = <
		/*KHZ uV */
		1200000	900000
		750000	900000
		600000	900000
		500000	900000
		400000	900000
		375000	900000
		300000	900000
		200000	900000
			>;

};

//&pwm {
//	ingenic,pwm-outputs = <0>; /* <0 - 15> select which pwms are really used */
//}

&pdma {
	status = "okay";
};

&msc0 {
	status = "disable";
	pinctrl-names = "default";
	/*mmc-hs200-1_8v;*/
	cap-mmc-highspeed;
	max-frequency = <50000000>;
	bus-width = <4>;
	voltage-ranges = <1800 3300>;
	cd-inverted;

	/* special property */
	ingenic,wp-gpios = <0>;
	ingenic,cd-gpios = <&gpd 25 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
	ingenic,rst-gpios = <0>;
	pinctrl-0 = <&msc0_pb>;
	mmc-pwrseq = <&mmc0_pwrseq>;
};

&msc1 {
	status = "okay";
	pinctrl-names = "default";
	/*mmc-hs200-1_8v;*/
	cap-mmc-highspeed;
	max-frequency = <50000000>;
	bus-width = <4>;
	voltage-ranges = <1800 3300>;
	non-removable;

	/* special property */
	ingenic,wp-gpios = <0>;
	ingenic,rst-gpios = <&gpc 22 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
	pinctrl-0 = <&msc1_pc>;
};

&mac0 {
	pinctrl-names = "default", "reset";
	pinctrl-0 = <&mac0_rmii_p0_normal>, <&mac0_rmii_p1_normal>;
	pinctrl-1 = <&mac0_rmii_p0_rst>, <&mac0_rmii_p1_normal>;
	status = "okay";
	ingenic,rst-gpio = <&gpb 12 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
	ingenic,mac-rst-gpio = <&gpb 30 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
	ingenic,rst-ms = <10>;
	ingenic,mac-mode = <RMII>;
	ingenic,mode-reg = <0xb00000e4>;
	ingenic,phy-clk-freq = <50000000>;
};

&sfc {
	status = "okay";
    pinctrl-names = "default";
	ingenic,sfc-max-frequency = <400000000>;
	ingenic,use_board_info      = /bits/ 8 <0>;
	ingenic,spiflash_param_offset = <0>;
	pinctrl-0 = <&sfc_pa>;
};

&spi0 {
	status = "disable";
	pinctrl-names = "default";
	pinctrl-0 = <&spi0_pc>;

	spi-max-frequency = <60000000>;
	num-cs = <2>;
	cs-gpios = <0>, <0>;
	ingenic,chnl = <0>;
	ingenic,allow_cs_same = <1>;
	ingenic,bus_num = <0>;
	ingenic,has_dma_support = <1>;
};

&spi1 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&spi1_pc>;

	spi-max-frequency = <50000000>;
	num-cs = <2>;
	cs-gpios = <0>, <0>;
//	cs-gpios = <&gpc 9 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>, <&gpc 9 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
	ingenic,chnl = <0>;
	ingenic,allow_cs_same = <1>;
	ingenic,bus_num = <1>;
	ingenic,has_dma_support = <1>;
//	ingenic,spi-src-clk = <1>;
	z7682inf: z7682inf@0 {
			compatible = "z7682inf";
			reg = <0>;
			spi-max-frequency = <25000000>;
	};
};

&dtrng {
	status = "okay";
};

&otg {
	g-use-dma;
	dr_mode = "otg";
	status = "okay";
};

&otg_phy {
	dr_mode = "otg";
	compatible = "ingenic,innophy", "syscon";
	ingenic,drvvbus-gpio = <&gpb 27 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
	status = "okay";
};

/ {

	extclk: extclk {
		clock-frequency = <24000000>;
	};

	gpio_keys: gpio_keys {
		   compatible = "gpio-keys";

		   power {
			   label = "Power";
			   linux,code = <KEY_POWER>;
			   gpios = <&gpa 31 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
			   gpio-key,wakeup;
		   };
            bootsel0 {
                label = "bootsel0";
                linux,code = <KEY_HOME>;
                gpios = <&gpc 0 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
            };

            bootsel1 {
                label = "bootsel1";
                linux,code = <KEY_BACK>;
                gpios = <&gpc 1 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
            };

	   };
};

&el150 {
	status = "disable";
};

&dpu {
	status = "okay";
};

/ {
	display-dpi {
		compatible = "simple-bus";
		#interrupt-cells = <1>;
		#address-cells = <1>;
		#size-cells = <1>;
		ranges = <>;
		panel_bm8766@0 {
			compatible = "ingenic,bm8766";
			status = "okay";
			pinctrl-names = "default";
			pinctrl-0 = <&tft_lcd_pd>;
			ingenic,bl-gpio = <&gpa 15 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
			ingenic,rst-gpio = <&gpa 16 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
		};
	};


};
/ {
	display-dbi {
		compatible = "simple-bus";
		#interrupt-cells = <1>;
		#address-cells = <1>;
		#size-cells = <1>;
		ranges = <>;
		panel_truly240240@0 {
			compatible = "ingenic,truly240240";
			status = "disable";
			pinctrl-names = "default";
			pinctrl-0 = <&smart_lcd_pd>;
			/*ingenic,rst-gpio = <&gpc 7 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;*/
			ingenic,rst-gpio = <&gpd 9 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
			ingenic,rd-gpio = <&gpd 12 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
			ingenic,cs-gpio = <&gpd 10 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
		};
	};


};
/ {
	display-dbi {
		compatible = "simple-bus";
		#interrupt-cells = <1>;
		#address-cells = <1>;
		#size-cells = <1>;
		ranges = <>;
		panel_st7789v240320@0 {
			compatible = "ingenic,st7789v240320";
			status = "disable";
			pinctrl-names = "default";
			pinctrl-0 = <&smart_lcd_pd>;
			/*ingenic,rst-gpio = <&gpc 7 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;*/
			ingenic,rst-gpio = <&gpd 9 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
			ingenic,rd-gpio = <&gpd 12 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
			ingenic,cs-gpio = <&gpd 10 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
			ingenic,bl-gpio = <&gpd 27 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
		};
	};


};
/ {
	display-dsi {
		compatible = "simple-bus";
		#interrupt-cells = <1>;
		#address-cells = <1>;
		#size-cells = <1>;
		ranges = <>;
		panel_EK79007@0 {
			compatible = "ingenic,ek79007";
			status = "disable";
			#pinctrl-names = "default";
			#pinctrl-0 = <&tft_lcd_pd>;
			ingenic,bl-gpio = <&gpd 26 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
			//ingenic,rst-gpio = <&gpd 17 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
		};
	};

};


/ {
	display-dsi {
		compatible = "simple-bus";
		#interrupt-cells = <1>;
		#address-cells = <1>;
		#size-cells = <1>;
		ranges = <>;
		panel_ST7701S@0 {
			compatible = "ingenic,st7701s";
			ingenic,vdd-en-gpio = <&gpc 26 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
			ingenic,lcd-pwd-gpio = <&gpc 28 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
			ingenic,lcd-te-gpio = <&gpc 23 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
			ingenic,rst-gpio = <&gpc 22 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
			status = "okay";
		};
	};

};


/ {
	display-dsi {
		compatible = "simple-bus";
		#interrupt-cells = <1>;
		#address-cells = <1>;
		#size-cells = <1>;
		ranges = <>;
		panel_OTA7290B@0 {
			compatible = "ingenic,ota7290b";
			ingenic,bl-gpio = <&gpc 03 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
			ingenic,rst-gpio = <&gpd 15 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
			status = "okay";
		};
	};

};


/ {
	display-dsi {
		compatible = "simple-bus";
		#interrupt-cells = <1>;
		#address-cells = <1>;
		#size-cells = <1>;
		ranges = <>;
		panel_ST7703@0 {
			compatible = "ingenic,vx071fhp";
			status = "okay";
			#pinctrl-names = "default";
			#pinctrl-0 = <&tft_lcd_pd>;
			ingenic,bl-gpio = <&gpa 15 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
			ingenic,rst-gpio = <&gpa 16 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
		};
	};

};


/ {
	display-dsi {
		compatible = "simple-bus";
		#interrupt-cells = <1>;
		#address-cells = <1>;
		#size-cells = <1>;
		ranges = <>;
		panel_JD9852@0 {
			compatible = "ingenic,jd9852";
			status = "okay";
			#pinctrl-names = "default";
			#pinctrl-0 = <&tft_lcd_pd>;
			ingenic,bl-gpio = <&gpc 28 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
			ingenic,rst-gpio = <&gpa 16 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
		};
	};

};


/ {
        display-dsi {
                compatible = "simple-bus";
                #interrupt-cells = <1>;
                #address-cells = <1>;
                #size-cells = <1>;
                ranges = <>;
                panel_ST7703@0 {
                        compatible = "ingenic,st7703";
                        status = "okay";
                        #pinctrl-names = "default";
                        #pinctrl-0 = <&tft_lcd_pd>;
                        ingenic,bl-gpio = <&gpa 15 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
                        ingenic,rst-gpio = <&gpa 16 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
                };
        };

};


/ {
        display-dsi {
                compatible = "simple-bus";
                #interrupt-cells = <1>;
                #address-cells = <1>;
                #size-cells = <1>;
                ranges = <>;
                panel_ST7701SN@0 {
                        compatible = "ingenic,st7701sn";
                        status = "okay";
                        #pinctrl-names = "default";
                        #pinctrl-0 = <&tft_lcd_pd>;
                        ingenic,bl-gpio = <&gpc 6 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
                        ingenic,rst-gpio = <&gpa 16 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
                };
        };

};

/ {
        display-dsi {
                compatible = "simple-bus";
                #interrupt-cells = <1>;
                #address-cells = <1>;
                #size-cells = <1>;
                ranges = <>;
                panel_GC9503V@0 {
                        compatible = "ingenic,gc9503v";
                        status = "okay";
                        #pinctrl-names = "default";
                        #pinctrl-0 = <&tft_lcd_pd>;
                        #ingenic,bl-gpio = <&gpd 26 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
                        ingenic,rst-gpio = <&gpb 8 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
                };
        };

};

/ {
        display-dsi {
                compatible = "simple-bus";
                #interrupt-cells = <1>;
                #address-cells = <1>;
                #size-cells = <1>;
                ranges = <>;
                panel_ST7701SG2@0 {
                        compatible = "ingenic,st7701s_xiaomi";
                        status = "okay";
                        #pinctrl-names = "default";
                        #pinctrl-0 = <&tft_lcd_pd>;
                        #ingenic,bl-gpio = <&gpd 26 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
                        ingenic,rst-gpio = <&gpb 8 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
                };
        };

};

/ {
        display-dsi {
                compatible = "simple-bus";
                #interrupt-cells = <1>;
                #address-cells = <1>;
                #size-cells = <1>;
                ranges = <>;
                panel_ST7102@0 {
                        compatible = "ingenic,st7102_xiaomi";
                        status = "okay";
                        #pinctrl-names = "default";
                        #pinctrl-0 = <&tft_lcd_pd>;
                        #ingenic,bl-gpio = <&gpd 26 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
                        ingenic,rst-gpio = <&gpb 8 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
                };
        };

};




5.mipi_dsi加入该时钟选择(jz_mipi_dsi.c)就在displays下面的jz_mipi_dsi目录下
路径:os/kernel/drivers/video/fbdev/ingenic/fb_v12/jz_mipi_dsi/jz_mipi_dsi.c
参照st7701s写

/*
 * Ingenic SoC MIPI-DSI dsim driver.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/mutex.h>
#include <linux/wait.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/fb.h>
#include <linux/ctype.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/memory.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/notifier.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/gpio.h>

#include "../ingenicfb.h"
#include "../jz_dsim.h"
#include "jz_mipi_dsi_lowlevel.h"
#include "jz_mipi_dsih_hal.h"
#include "jz_mipi_dsi_regs.h"
extern struct jzfb_platform_data jzfb_platform_data;
#define jzfb_pdata jzfb_platform_data

#define DSI_IOBASE	0xb0003000

#define DSI_PHY_IOBASE	0xb0004000

/*64*/

struct mipi_dsim_ddi {
	int				bus_id;
	struct list_head		list;
	struct mipi_dsim_lcd_device	*dsim_lcd_dev;
	struct mipi_dsim_lcd_driver	*dsim_lcd_drv;
};

static LIST_HEAD(dsim_ddi_list);

static DEFINE_MUTEX(mipi_dsim_lock);

void dump_dsi_reg(struct dsi_device *dsi);
static DEFINE_MUTEX(dsi_lock);

int jz_dsi_video_cfg(struct dsi_device *dsi)
{
	dsih_error_t err_code = OK;
	unsigned short bytes_per_pixel_x100 = 0;	/* bpp x 100 because it can be 2.25 */
	unsigned short video_size = 0;
	unsigned int ratio_clock_xPF = 0;	/* holds dpi clock/byte clock times precision factor */
	unsigned short null_packet_size = 0;
	unsigned char video_size_step = 1;
	unsigned int total_bytes = 0;
	unsigned int bytes_per_chunk = 0;
	unsigned int no_of_chunks = 0;
	unsigned int bytes_left = 0;
	unsigned int chunk_overhead = 0;

	struct video_config *video_config;
	video_config = dsi->video_config;

	/* check DSI controller dsi */
	if ((dsi == NULL) || (video_config == NULL)) {
		return ERR_DSI_INVALID_INSTANCE;
	}
#if 1
	if(dsi->state == UBOOT_INITIALIZED) {
		/*no need to reconfig, just return*/
		printk("dsi has already been initialized by uboot!!\n");
		return OK;
	}
#endif
	if (dsi->state != INITIALIZED) {
		return ERR_DSI_INVALID_INSTANCE;
	}

	ratio_clock_xPF = video_config->byte_clock * PRECISION_FACTOR;

	if(video_config->refresh <= 10)
		ratio_clock_xPF *= 15;
	else if(video_config->refresh <= 15)
		ratio_clock_xPF *= 11;
	else if(video_config->refresh <= 20)
		ratio_clock_xPF *= 8;
	else if(video_config->refresh <= 25)
		ratio_clock_xPF *= 6;
	else if(video_config->refresh <= 30)
		ratio_clock_xPF *= 5;
	else if(video_config->refresh <= 50)
		ratio_clock_xPF *= 4;
	else if(video_config->refresh <= 60)
		ratio_clock_xPF *= 3;
	else if(video_config->refresh <= 120)
		ratio_clock_xPF *= 2;

	ratio_clock_xPF /= video_config->pixel_clock;
#ifdef CONFIG_PANEL_JD9852
	ratio_clock_xPF = 14000;
#endif
#ifdef CONFIG_PANEL_VX071FHP
	ratio_clock_xPF = 900;
#endif
#if (defined(CONFIG_PANEL_ST7701S_XIAOMI_MODULE)||defined(CONFIG_PANEL_ST7701S_XIAOMI)||defined(CONFIG_PANEL_ST7102_XIAOMI_MODULE)||defined(CONFIG_PANEL_ST7102_XIAOMI))
	ratio_clock_xPF = 2400;
#endif
	printk("####################### ratio_clock_xPF=%d\n",ratio_clock_xPF);

	video_size = video_config->h_active_pixels;
	/*  disable set up ACKs and error reporting */
	mipi_dsih_hal_dpi_frame_ack_en(dsi, video_config->receive_ack_packets);
	if (video_config->receive_ack_packets) {	/* if ACK is requested, enable BTA, otherwise leave as is */
		mipi_dsih_hal_bta_en(dsi, 1);
	}
	/*0:switch to high speed transfer, 1 low power mode */
	mipi_dsih_write_word(dsi, R_DSI_HOST_CMD_MODE_CFG, 0);
	/*0:enable video mode, 1:enable cmd mode */
	mipi_dsih_hal_gen_set_mode(dsi, 0);

	err_code =
	    jz_dsi_video_coding(dsi, &bytes_per_pixel_x100, &video_size_step,
				&video_size);
	if (err_code) {
		return err_code;
	}

	jz_dsi_dpi_cfg(dsi, &ratio_clock_xPF, &bytes_per_pixel_x100);

	/* TX_ESC_CLOCK_DIV must be less than 20000KHz */
	jz_dsih_hal_tx_escape_division(dsi, TX_ESC_CLK_DIV);

	/* video packetisation   */
	if (video_config->video_mode == VIDEO_BURST_WITH_SYNC_PULSES) {	/* BURST */
		//mipi_dsih_hal_dpi_null_packet_en(dsi, 0);
		mipi_dsih_hal_dpi_null_packet_size(dsi, 0);
		//mipi_dsih_hal_dpi_multi_packet_en(dsi, 0);
		err_code =
		    err_code ? err_code : mipi_dsih_hal_dpi_chunks_no(dsi, 1);
		err_code =
		    err_code ? err_code :
		    mipi_dsih_hal_dpi_video_packet_size(dsi, video_size);
		if (err_code != OK) {
			return err_code;
		}
		/* BURST by default, returns to LP during ALL empty periods - energy saving */
		mipi_dsih_hal_dpi_lp_during_hfp(dsi, 1);
		mipi_dsih_hal_dpi_lp_during_hbp(dsi, 1);
		mipi_dsih_hal_dpi_lp_during_vactive(dsi, 1);
		mipi_dsih_hal_dpi_lp_during_vfp(dsi, 1);
		mipi_dsih_hal_dpi_lp_during_vbp(dsi, 1);
		mipi_dsih_hal_dpi_lp_during_vsync(dsi, 1);
#ifdef CONFIG_DSI_DPI_DEBUG
		/*      D E B U G               */
		{
			pr_info("burst video");
			pr_info("h line time %d ,",
			       (unsigned
				short)((video_config->h_total_pixels *
					ratio_clock_xPF) / PRECISION_FACTOR));
			pr_info("video_size %d ,", video_size);
		}
#endif
	} else {		/* non burst transmission */
		null_packet_size = 0;
		/* bytes to be sent - first as one chunk */
		bytes_per_chunk =
		    (bytes_per_pixel_x100 * video_config->h_active_pixels) /
		    100 + VIDEO_PACKET_OVERHEAD;
		/* bytes being received through the DPI interface per byte clock cycle */
		total_bytes =
		    (ratio_clock_xPF * video_config->no_of_lanes *
		     (video_config->h_total_pixels -
		      video_config->h_back_porch_pixels -
		      video_config->h_sync_pixels)) / PRECISION_FACTOR;
		pr_debug("---->total_bytes:%d, bytes_per_chunk:%d\n", total_bytes,
		       bytes_per_chunk);
		/* check if the in pixels actually fit on the DSI link */
		if (total_bytes >= bytes_per_chunk) {
			chunk_overhead = total_bytes - bytes_per_chunk;
			/* overhead higher than 1 -> enable multi packets */
			if (chunk_overhead > 1) {
				for (video_size = video_size_step; video_size < video_config->h_active_pixels; video_size += video_size_step) {	/* determine no of chunks */
					if ((((video_config->h_active_pixels *
					       PRECISION_FACTOR) / video_size) %
					     PRECISION_FACTOR) == 0) {
						no_of_chunks =
						    video_config->
						    h_active_pixels /
						    video_size;
						bytes_per_chunk =
						    (bytes_per_pixel_x100 *
						     video_size) / 100 +
						    VIDEO_PACKET_OVERHEAD;
						if (total_bytes >=
						    (bytes_per_chunk *
						     no_of_chunks)) {
							bytes_left =
							    total_bytes -
							    (bytes_per_chunk *
							     no_of_chunks);
							break;
						}
					}
				}
				/* prevent overflow (unsigned - unsigned) */
				if (bytes_left >
				    (NULL_PACKET_OVERHEAD * no_of_chunks)) {
					null_packet_size =
					    (bytes_left -
					     (NULL_PACKET_OVERHEAD *
					      no_of_chunks)) / no_of_chunks;
					if (null_packet_size > MAX_NULL_SIZE) {	/* avoid register overflow */
						null_packet_size =
						    MAX_NULL_SIZE;
					}
				}
			} else {	/* no multi packets */
				no_of_chunks = 1;
#ifdef CONFIG_DSI_DPI_DEBUG
				/*      D E B U G               */
				{
					pr_info("no multi no null video");
					pr_info("h line time %d",
					       (unsigned
						short)((video_config->
							h_total_pixels *
							ratio_clock_xPF) /
						       PRECISION_FACTOR));
					pr_info("video_size %d", video_size);
				}
#endif
				/* video size must be a multiple of 4 when not 18 loosely */
				for (video_size = video_config->h_active_pixels;
				     (video_size % video_size_step) != 0;
				     video_size++) {
					;
				}
			}
		} else {
			pr_err
			    ("resolution cannot be sent to display through current settings");
			err_code = ERR_DSI_OVERFLOW;

		}
	}
	err_code =
	    err_code ? err_code : mipi_dsih_hal_dpi_chunks_no(dsi,
							      no_of_chunks);
	err_code =
	    err_code ? err_code : mipi_dsih_hal_dpi_video_packet_size(dsi,
								      video_size);
	err_code =
	    err_code ? err_code : mipi_dsih_hal_dpi_null_packet_size(dsi,
								     null_packet_size);

	// mipi_dsih_hal_dpi_null_packet_en(dsi, null_packet_size > 0? 1: 0);
	// mipi_dsih_hal_dpi_multi_packet_en(dsi, (no_of_chunks > 1)? 1: 0);
#ifdef  CONFIG_DSI_DPI_DEBUG
	/*      D E B U G               */
	{
		pr_info("total_bytes %d ,", total_bytes);
		pr_info("bytes_per_chunk %d ,", bytes_per_chunk);
		pr_info("bytes left %d ,", bytes_left);
		pr_info("null packets %d ,", null_packet_size);
		pr_info("chunks %d ,", no_of_chunks);
		pr_info("video_size %d ", video_size);
	}
#endif
	mipi_dsih_hal_dpi_video_vc(dsi, video_config->virtual_channel);
	jz_dsih_dphy_no_of_lanes(dsi, video_config->no_of_lanes);
	/* enable high speed clock */
	mipi_dsih_dphy_enable_hs_clk(dsi, 1);
	pr_debug("video configure is ok!\n");
	return err_code;

}

/* set all register settings to MIPI DSI controller. */
dsih_error_t jz_dsi_phy_cfg(struct dsi_device * dsi)
{
	dsih_error_t err = OK;
	err = jz_dsi_set_clock(dsi);
	if (err) {
		return err;
	}
	err = jz_init_dsi(dsi);
	if (err) {
		return err;
	}
	return OK;
}

int jz_dsi_phy_open(struct dsi_device *dsi)
{
	struct video_config *video_config;
	video_config = dsi->video_config;

	pr_debug("entry %s()\n", __func__);

	jz_dsih_dphy_reset(dsi, 0);
	jz_dsih_dphy_stop_wait_time(dsi, 0x1c);	/* 0x1c: */

	if (video_config->no_of_lanes > 4 || video_config->no_of_lanes < 1)
		return ERR_DSI_OUT_OF_BOUND;
	jz_dsih_dphy_no_of_lanes(dsi, video_config->no_of_lanes);

	jz_dsih_dphy_clock_en(dsi, 1);
	jz_dsih_dphy_shutdown(dsi, 1);
	jz_dsih_dphy_reset(dsi, 1);

	dsi->dsi_phy->status = INITIALIZED;
	return OK;
}

void dump_dsi_reg(struct dsi_device *dsi)
{
	pr_info("dsi->dev: ===========>dump dsi reg\n");
	pr_info("dsi->dev: VERSION------------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VERSION));
	pr_info("dsi->dev: PWR_UP:------------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_PWR_UP));
	pr_info("dsi->dev: CLKMGR_CFG---------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_CLKMGR_CFG));
	pr_info("dsi->dev: DPI_VCID-----------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_DPI_VCID));
	pr_info("dsi->dev: DPI_COLOR_CODING---:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_DPI_COLOR_CODING));
	pr_info("dsi->dev: DPI_CFG_POL--------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_DPI_CFG_POL));
	pr_info("dsi->dev: DPI_LP_CMD_TIM-----:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_DPI_LP_CMD_TIM));
	pr_info("dsi->dev: DBI_VCID-----------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_DBI_VCID));
	pr_info("dsi->dev: DBI_CFG------------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_DBI_CFG));
	pr_info("dsi->dev: DBI_PARTITIONING_EN:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_DBI_PARTITIONING_EN));
	pr_info("dsi->dev: DBI_CMDSIZE--------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_DBI_CMDSIZE));
	pr_info("dsi->dev: PCKHDL_CFG---------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_PCKHDL_CFG));
	pr_info("dsi->dev: GEN_VCID-----------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_GEN_VCID));
	pr_info("dsi->dev: MODE_CFG-----------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_MODE_CFG));
	pr_info("dsi->dev: VID_MODE_CFG-------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_MODE_CFG));
	pr_info("dsi->dev: VID_PKT_SIZE-------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_PKT_SIZE));
	pr_info("dsi->dev: VID_NUM_CHUNKS-----:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_NUM_CHUNKS));
	pr_info("dsi->dev: VID_NULL_SIZE------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_NULL_SIZE));
	pr_info("dsi->dev: VID_HSA_TIME-------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_HSA_TIME));
	pr_info("dsi->dev: VID_HBP_TIME-------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_HBP_TIME));
	pr_info("dsi->dev: VID_HLINE_TIME-----:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_HLINE_TIME));
	pr_info("dsi->dev: VID_VSA_LINES------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_VSA_LINES));
	pr_info("dsi->dev: VID_VBP_LINES------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_VBP_LINES));
	pr_info("dsi->dev: VID_VFP_LINES------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_VFP_LINES));
	pr_info("dsi->dev: VID_VACTIVE_LINES--:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_VACTIVE_LINES));
	pr_info("dsi->dev: EDPI_CMD_SIZE------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_EDPI_CMD_SIZE));
	pr_info("dsi->dev: CMD_MODE_CFG-------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_CMD_MODE_CFG));
	pr_info("dsi->dev: GEN_HDR------------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_GEN_HDR));
	pr_info("dsi->dev: GEN_PLD_DATA-------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_GEN_PLD_DATA));
	pr_info("dsi->dev: CMD_PKT_STATUS-----:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_CMD_PKT_STATUS));
	pr_info("dsi->dev: TO_CNT_CFG---------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_TO_CNT_CFG));
	pr_info("dsi->dev: HS_RD_TO_CNT-------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_HS_RD_TO_CNT));
	pr_info("dsi->dev: LP_RD_TO_CNT-------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_LP_RD_TO_CNT));
	pr_info("dsi->dev: HS_WR_TO_CNT-------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_HS_WR_TO_CNT));
	pr_info("dsi->dev: LP_WR_TO_CNT_CFG---:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_LP_WR_TO_CNT));
	pr_info("dsi->dev: BTA_TO_CNT---------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_BTA_TO_CNT));
	pr_info("dsi->dev: SDF_3D-------------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_SDF_3D));
	pr_info("dsi->dev: LPCLK_CTRL---------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_LPCLK_CTRL));
	pr_info("dsi->dev: PHY_TMR_LPCLK_CFG--:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_PHY_TMR_LPCLK_CFG));
	pr_info("dsi->dev: PHY_TMR_CFG--------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_PHY_TMR_CFG));
	pr_info("dsi->dev: PHY_RSTZ-----------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_PHY_RSTZ));
	pr_info("dsi->dev: PHY_IF_CFG---------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_PHY_IF_CFG));
	pr_info("dsi->dev: PHY_ULPS_CTRL------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_PHY_ULPS_CTRL));
	pr_info("dsi->dev: PHY_TX_TRIGGERS----:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_PHY_TX_TRIGGERS));
	pr_info("dsi->dev: PHY_STATUS---------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_PHY_STATUS));
	pr_info("dsi->dev: PHY_TST_CTRL0------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_PHY_TST_CTRL0));
	pr_info("dsi->dev: PHY_TST_CTRL1------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_PHY_TST_CTRL1));
	pr_info("dsi->dev: INT_ST0------------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_INT_ST0));
	pr_info("dsi->dev: INT_ST1------------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_INT_ST1));
	pr_info("dsi->dev: INT_MSK0-----------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_INT_MSK0));
	pr_info("dsi->dev: INT_MSK1-----------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_INT_MSK1));
	pr_info("dsi->dev: INT_FORCE0---------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_INT_FORCE0));
	pr_info("dsi->dev: INT_FORCE1---------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_INT_FORCE1));
	pr_info("dsi->dev: VID_SHADOW_CTRL----:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_SHADOW_CTRL));
	pr_info("dsi->dev: DPI_VCID_ACT-------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_DPI_VCID_ACT));
	pr_info("dsi->dev: DPI_COLOR_CODING_AC:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_DPI_COLOR_CODING_ACT));
	pr_info("dsi->dev: DPI_LP_CMD_TIM_ACT-:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_DPI_LP_CMD_TIM_ACT));
	pr_info("dsi->dev: VID_MODE_CFG_ACT---:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_MODE_CFG_ACT));
	pr_info("dsi->dev: VID_PKT_SIZE_ACT---:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_PKT_SIZE_ACT));
	pr_info("dsi->dev: VID_NUM_CHUNKS_ACT-:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_NUM_CHUNKS_ACT));
	pr_info("dsi->dev: VID_HSA_TIME_ACT---:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_HSA_TIME_ACT));
	pr_info("dsi->dev: VID_HBP_TIME_ACT---:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_HBP_TIME_ACT));
	pr_info("dsi->dev: VID_HLINE_TIME_ACT-:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_HLINE_TIME_ACT));
	pr_info("dsi->dev: VID_VSA_LINES_ACT--:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_VSA_LINES_ACT));
	pr_info("dsi->dev: VID_VBP_LINES_ACT--:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_VBP_LINES_ACT));
	pr_info("dsi->dev: VID_VFP_LINES_ACT--:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_VFP_LINES_ACT));
	pr_info("dsi->dev: VID_VACTIVE_LINES_ACT:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_VID_VACTIVE_LINES_ACT));
	pr_info("dsi->dev: SDF_3D_ACT---------:%08x\n",
		 mipi_dsih_read_word(dsi, R_DSI_HOST_SDF_3D_ACT));

}

void set_base_dir_tx(struct dsi_device *dsi, void *param)
{
	int i = 0;
	register_config_t phy_direction[] = {
		{0xb4, 0x02},
		{0xb8, 0xb0},
		{0xb8, 0x100b0},
		{0xb4, 0x00},
		{0xb8, 0x000b0},
		{0xb8, 0x0000},
		{0xb4, 0x02},
		{0xb4, 0x00}
	};
	i = mipi_dsih_write_register_configuration(dsi, phy_direction,
						   (sizeof(phy_direction) /
						    sizeof(register_config_t)));
	if (i != (sizeof(phy_direction) / sizeof(register_config_t))) {
		pr_err("ERROR setting up testchip %d", i);
	}
}

static void init_dsi_phy(struct dsi_device *dsi)
{
	unsigned int temp = 0xffffffff;

	printk("dsi phy address = 0x%x\n", dsi->phy_address);
	//power on ,reset, set pin_enable_ck/0/1/* of lanes to be used to high level and others to low
	printk("%s,%d  step0 do nothing now.\n", __func__, __LINE__);

	//step1
	temp = *(volatile unsigned int*)(dsi->phy_address+0x0C);
	temp &= ~0xff;
#ifdef CONFIG_PANEL_VX071FHP 
	temp |= 0x01;
#else
	temp |= 0x02;
#endif
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x0C));
	if ((*(volatile unsigned int*)(dsi->phy_address+0x0C) & 0xff) != 0x02) {
		printk("%s,%d reg write error. Step1\n", __func__, __LINE__);
	}
	printk("reg:0x03, value:0x%x\n", *(volatile unsigned int*)(dsi->phy_address+0x0C));
	//step2
	temp = *(volatile unsigned int*)(dsi->phy_address+0x10);
	temp &= ~0xff;

#if defined(CONFIG_PANEL_VX071FHP)
	temp |= 0x8c;
#elif (defined(CONFIG_PANEL_ST7701S_XIAOMI_MODULE) || defined(CONFIG_PANEL_ST7701S_XIAOMI)||defined(CONFIG_PANEL_ST7102_XIAOMI_MODULE)||defined(CONFIG_PANEL_ST7102_XIAOMI))
#if 1 // 60fps
	temp |= 0x96;
#else // 30fps
	temp |= 0x50;
#endif
#else
	temp |= 0xff;
#endif

	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x10));
	if ((*(volatile unsigned int*)(dsi->phy_address+0x10) & 0xff) != 0x53) {
		printk("%s,%d reg write error. Step2\n", __func__, __LINE__);
	}
	printk("reg:0x04, value:0x%x\n", *(volatile unsigned int*)(dsi->phy_address+0x10));
	//step3
	temp = *(volatile unsigned int*)(dsi->phy_address+0x04);
	temp &= ~0xff;
	temp |= 0xe4;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x04));
	if ((*(volatile unsigned int*)(dsi->phy_address+0x04) & 0xff) != 0xe4) {
		printk("%s,%d reg write error. Step3\n", __func__, __LINE__);
	}
	printk("reg:0x01, value:0x%x\n", *(volatile unsigned int*)(dsi->phy_address+0x04));
	//step4
	if (dsi->video_config->no_of_lanes == 4) {
		temp = *(volatile unsigned int*)(dsi->phy_address+0x00);
		temp &= ~0xff;
		temp |= 0x7d;     //4lane
		writel(temp, (volatile unsigned int*)(dsi->phy_address+0x00));
		if ((*(volatile unsigned int*)(dsi->phy_address+0x00) & 0xff) != 0x7d) {
			printk("%s,%d reg write error. Step4\n", __func__, __LINE__);
		}
	}
	else if (dsi->video_config->no_of_lanes == 2){
		temp = *(volatile unsigned int*)(dsi->phy_address+0x00);
		temp &= ~0xff;
		temp |= 0x4d;     //2lane
		writel(temp, (volatile unsigned int*)(dsi->phy_address+0x00));
		if ((*(volatile unsigned int*)(dsi->phy_address+0x00) & 0xff) != 0x4d) {
			printk("%s,%d reg write error. Step4\n", __func__, __LINE__);
		}
	}
	else if (dsi->video_config->no_of_lanes == 1){
		temp = *(volatile unsigned int*)(dsi->phy_address+0x00);
		temp &= ~0xff;
		temp |= 0x45;     //1lane
		writel(temp, (volatile unsigned int*)(dsi->phy_address+0x00));
		if ((*(volatile unsigned int*)(dsi->phy_address+0x00) & 0xff) != 0x45) {
			printk("%s,%d reg write error. Step4\n", __func__, __LINE__);
		}
	}
	printk("reg:0x00, value:0x%x\n", *(volatile unsigned int*)(dsi->phy_address+0x00));
	//step5
	temp = *(volatile unsigned int*)(dsi->phy_address+0x04);
	temp &= ~0xff;
	temp |= 0xe0;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x04));
	if ((*(volatile unsigned int*)(dsi->phy_address+0x04) & 0xff) != 0xe0) {
		printk("%s,%d reg write error. Step5\n", __func__, __LINE__);
	}
	printk("reg:0x01, value:0x%x\n", *(volatile unsigned int*)(dsi->phy_address+0x04));

	//step6
	msleep(20);   //at lease 20ms, shortening need validation

	//step7
	// temp = *(volatile unsigned int*)(dsi->phy_address+0x80);
	// temp &= ~0xff;
	// temp |= 0x1e;
	// writel(temp, (volatile unsigned int*)(dsi->phy_address+0x80));
	// if ((*(volatile unsigned int*)(dsi->phy_address+0x80) & 0xff) != 0x1e) {
	// 	printk("%s,%d reg write error. Step7\n", __func__, __LINE__);
	// }
	// printk("reg:0x20, value:0x%x\n", *(volatile unsigned int*)(dsi->phy_address+0x80));
	//step8
	temp = *(volatile unsigned int*)(dsi->phy_address+0x80);
	temp &= ~0xff;
	temp |= 0x1f;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x80));
	if ((*(volatile unsigned int*)(dsi->phy_address+0x80) & 0xff) != 0x1f) {
		printk("%s,%d reg write error. Step8\n", __func__, __LINE__);
	}
	printk("reg:0x20, value:0x%x\n", *(volatile unsigned int*)(dsi->phy_address+0x80));
	//step9
	msleep(10);
#if (defined(CONFIG_PANEL_ST7701S_XIAOMI) || defined(CONFIG_PANEL_ST7701S_XIAOMI_MODULE)||defined(CONFIG_PANEL_ST7102_XIAOMI_MODULE)||defined(CONFIG_PANEL_ST7102_XIAOMI))
#if 1 // 60fps
	temp = *(volatile unsigned int*)(dsi->phy_address+0x018);
	temp &= 0xfffffff0;
	temp |= 0x8;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x018));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x020);
	temp &= 0xfffffff0;
	temp |= 0x8;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x020));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x02c);
	temp &= 0xfffffff0;
	temp |= 0x8;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x02c));

  //LPX
	temp = *(volatile unsigned int*)(dsi->phy_address+0x114);
	temp &= ~0xff;
	temp |= 0x3;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x114));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x194);
	temp &= ~0xff;
	temp |= 0x3;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x194));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x214);
	temp &= ~0xff;
	temp |= 0x3;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x214));


    //THS-PREPARE
	temp = *(volatile unsigned int*)(dsi->phy_address+0x118);
	temp &= ~0xff;
	temp |= 0x7c;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x118));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x198);
	temp &= ~0xff;
	temp |= 0x7c;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x198));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x218);
	temp &= ~0xff;
	temp |= 0x7c;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x218));

    
    //THS-ZERO
	temp = *(volatile unsigned int*)(dsi->phy_address+0x11c);
	temp &= ~0xff;
	temp |= 0x1b;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x11c));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x19c);
	temp &= ~0xff;
	temp |= 0x7;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x19c));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x21c);
	temp &= ~0xff;
	temp |= 0x7;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x21c));


    //THS-TRAIL 
	temp = *(volatile unsigned int*)(dsi->phy_address+0x120);
	temp &= ~0xff;
	temp |= 0x8;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x120));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x1a0);
	temp &= ~0xff;
	temp |= 0x8;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x1a0));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x220);
	temp &= ~0xff;
	temp |= 0x8;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x220));

    //THS-EXIT reg09
	temp = *(volatile unsigned int*)(dsi->phy_address+0x124);
	temp &= ~0xff;
	temp |= 0x0;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x124));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x1a4);
	temp &= ~0xff;
	temp |= 0x0;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x1a4));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x224);
	temp &= ~0xff;
	temp |= 0x0;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x224));

    //THS-EXIT reg11
	temp = *(volatile unsigned int*)(dsi->phy_address+0x144);
	temp &= ~0xff;
	temp |= 0x0;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x144));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x1c4);
	temp &= ~0xff;
	temp |= 0x0;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x1c4));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x244);
	temp &= ~0xff;
	temp |= 0x0;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x244));
#else //30fps

  //LPX
	temp = *(volatile unsigned int*)(dsi->phy_address+0x114);
	temp &= ~0xff;
	temp |= 0x2;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x114));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x194);
	temp &= ~0xff;
	temp |= 0x2;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x194));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x214);
	temp &= ~0xff;
	temp |= 0x2;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x214));


    //THS-PREPARE
	temp = *(volatile unsigned int*)(dsi->phy_address+0x118);
	temp &= ~0xff;
	temp |= 0x7f;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x118));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x198);
	temp &= ~0xff;
	temp |= 0x7f;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x198));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x218);
	temp &= ~0xff;
	temp |= 0x7f;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x218));

    
    //THS-ZERO
	temp = *(volatile unsigned int*)(dsi->phy_address+0x11c);
	temp &= ~0xff;
	temp |= 0x17;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x11c));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x19c);
	temp &= ~0xff;
	temp |= 0x5;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x19c));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x21c);
	temp &= ~0xff;
	temp |= 0x5;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x21c));


    //THS-TRAIL 
	temp = *(volatile unsigned int*)(dsi->phy_address+0x120);
	temp &= ~0xff;
	temp |= 0x4;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x120));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x1a0);
	temp &= ~0xff;
	temp |= 0x4;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x1a0));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x220);
	temp &= ~0xff;
	temp |= 0x4;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x220));

    //THS-EXIT reg09
	temp = *(volatile unsigned int*)(dsi->phy_address+0x124);
	temp &= ~0xff;
	temp |= 0x0;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x124));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x1a4);
	temp &= ~0xff;
	temp |= 0x0;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x1a4));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x224);
	temp &= ~0xff;
	temp |= 0x0;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x224));

    //THS-EXIT reg11
	temp = *(volatile unsigned int*)(dsi->phy_address+0x144);
	temp &= ~0xff;
	temp |= 0x0;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x144));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x1c4);
	temp &= ~0xff;
	temp |= 0x0;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x1c4));

	temp = *(volatile unsigned int*)(dsi->phy_address+0x244);
	temp &= ~0xff;
	temp |= 0x0;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x244));

#endif
#endif
#ifdef CONFIG_PANEL_OTA7290B /*Add this to adjust HS prepare time*/
	//step10
	temp = *(volatile unsigned int*)(dsi->phy_address+0x118);
	temp &= ~0xff;
	temp |= 0x40;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x118));
	if ((*(volatile unsigned int*)(dsi->phy_address+0x118) & 0xff) != 0x40) {
		printk("%s,%d reg write error. Step10\n", __func__, __LINE__);
	}
	//step11
	temp = *(volatile unsigned int*)(dsi->phy_address+0x198);
	temp &= ~0xff;
	temp |= 0x40;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x198));
	if ((*(volatile unsigned int*)(dsi->phy_address+0x198) & 0xff) != 0x40) {
		pr_err("%s,%d reg write error. Step11\n", __func__, __LINE__);
	}
	//step12
	temp = *(volatile unsigned int*)(dsi->phy_address+0x218);
	temp &= ~0xff;
	temp |= 0x40;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x218));
	if ((*(volatile unsigned int*)(dsi->phy_address+0x218) & 0xff) != 0x40) {
		pr_err("%s,%d reg write error. Step12\n", __func__, __LINE__);
	}
	//step13
	temp = *(volatile unsigned int*)(dsi->phy_address+0x298);
	temp &= ~0xff;
	temp |= 0x40;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x298));
	if ((*(volatile unsigned int*)(dsi->phy_address+0x298) & 0xff) != 0x40) {
		pr_err("%s,%d reg write error. Step13\n", __func__, __LINE__);
	}
	//step14
	temp = *(volatile unsigned int*)(dsi->phy_address+0x1318);
	temp &= ~0xff;
	temp |= 0x40;
	writel(temp, (volatile unsigned int*)(dsi->phy_address+0x318));
	if ((*(volatile unsigned int*)(dsi->phy_address+0x318) & 0xff) != 0x40) {
		pr_err("%s,%d reg write error. Step14\n", __func__, __LINE__);
	}
#endif
	printk("%s,%d  dsi phy init over now...\n", __func__, __LINE__);
}

static int jz_mipi_update_cfg(struct dsi_device *dsi)
{
	int ret;
	int st_mask = 0;
	int retry = 5;
	ret = jz_dsi_phy_open(dsi);
	if (ret) {
		pr_err("open the phy failed!\n");
		return ret;
	}

	mipi_dsih_write_word(dsi, R_DSI_HOST_CMD_MODE_CFG,
				     0xffffff0);

	/*set command mode */
	mipi_dsih_write_word(dsi, R_DSI_HOST_MODE_CFG, 0x1);
	/*set this register for cmd size, default 0x6 */
	mipi_dsih_write_word(dsi, R_DSI_HOST_EDPI_CMD_SIZE, 0x6);

	/*
	 * jz_dsi_phy_cfg:
	 * PLL programming, config the output freq to DEFAULT_DATALANE_BPS.
	 * */
	init_dsi_phy(dsi);
	ret = jz_dsi_phy_cfg(dsi);
	if (ret) {
		pr_err("phy configigure failed!\n");
		return ret;
	}

	pr_debug("wait for phy config ready\n");
	if (dsi->video_config->no_of_lanes == 2)
		st_mask = 0x95;
	else
		st_mask = 0x15;

	/*checkout phy clk lock and  clklane, datalane stopstate  */
	udelay(10);
	while ((mipi_dsih_read_word(dsi, R_DSI_HOST_PHY_STATUS) & st_mask) !=
			st_mask && retry--) {
		pr_info("phy status = %08x\n", mipi_dsih_read_word(dsi, R_DSI_HOST_PHY_STATUS));
	}

	if (!retry){
		pr_err("wait for phy config failed!\n");
		return ret;
	}

	dsi->state = INITIALIZED;
	return 0;
}

/* for debug lcd power on/off */
int jz_mipi_dsi_set_client(struct dsi_device *dsi, int power)
{
	struct mipi_dsim_lcd_driver *client_drv = dsi->dsim_lcd_drv;
	struct mipi_dsim_lcd_device *client_dev = dsi->dsim_lcd_dev;

	switch (power) {
	case FB_BLANK_POWERDOWN:
		if (client_drv && client_drv->suspend)
			client_drv->suspend(client_dev);

		break;
	case FB_BLANK_UNBLANK:
		/* lcd panel power on. */
		if (client_drv && client_drv->power_on)
			client_drv->power_on(client_dev, POWER_ON_LCD);

		/* set lcd panel sequence commands. */
		if (client_drv && client_drv->set_sequence)
			client_drv->set_sequence(client_dev);

		break;
	case FB_BLANK_NORMAL:
		/* TODO. */
		break;

	default:
		break;
	}
	return 0;
}

static int jz_mipi_dsi_blank_mode(struct dsi_device *dsi, int power)
{
	struct mipi_dsim_lcd_driver *client_drv = dsi->dsim_lcd_drv;
	struct mipi_dsim_lcd_device *client_dev = dsi->dsim_lcd_dev;

    switch (power) {
	case FB_BLANK_POWERDOWN:
        if (dsi->suspended)
            return 0;

        if (client_drv && client_drv->suspend)
            client_drv->suspend(client_dev);

        jz_dsih_dphy_clock_en(dsi, 0);
        jz_dsih_dphy_shutdown(dsi, 0);
        clk_disable_unprepare(dsi->clk);
        mipi_dsih_hal_power(dsi, 0);

        dsi->state = NOT_INITIALIZED;
        dsi->suspended = true;

        break;
    case FB_BLANK_UNBLANK:
        if (!dsi->suspended)
            return 0;

        clk_prepare_enable(dsi->clk);
        jz_mipi_update_cfg(dsi);

        /* lcd panel power on. */
        if (client_drv && client_drv->power_on)
            client_drv->power_on(client_dev, POWER_ON_LCD);

        /* set lcd panel sequence commands. */
        if (client_drv && client_drv->set_sequence)
            client_drv->set_sequence(client_dev);

        dsi->suspended = false;

        break;
    case FB_BLANK_NORMAL:
        /* TODO. */
        break;


    default:
        break;
    }

    return 0;
}

static int jz_mipi_dsi_ioctl(struct dsi_device *dsi, int cmd)
{
    struct mipi_dsim_lcd_driver *client_drv = dsi->dsim_lcd_drv;
    struct mipi_dsim_lcd_device *client_dev = dsi->dsim_lcd_dev;

    if (client_drv && client_drv->ioctl)
        client_drv->ioctl(client_dev, cmd);

    return 0;
}

int jz_dsi_mode_cfg(struct dsi_device *dsi, int mode)
{
	struct video_config *video_config;
	struct dsi_config *dsi_config;
	video_config = dsi->video_config;
	dsi_config = dsi->dsi_config;

	if(mode == 1) {
		/* video mode */
		jz_dsih_hal_power(dsi, 0);
		jz_dsi_video_cfg(dsi);
		jz_dsih_hal_power(dsi, 1);
	} else {
		mipi_dsih_write_word(dsi, R_DSI_HOST_EDPI_CMD_SIZE, 1024); /* 当设置太小时, 对于M31传输数据会有卡死的现象??, 这里设置成1024。*/
		mipi_dsih_dphy_enable_hs_clk(dsi, 1);
		mipi_dsih_dphy_auto_clklane_ctrl(dsi, 1);
		mipi_dsih_write_word(dsi, R_DSI_HOST_CMD_MODE_CFG, 1);

		/* cmd mode */
		/* color coding fix to 24bit ???? */
		mipi_dsih_hal_dpi_frame_ack_en(dsi, video_config->receive_ack_packets);
		if (video_config->receive_ack_packets) {	/* if ACK is requested, enable BTA, otherwise leave as is */
			mipi_dsih_hal_bta_en(dsi, 1);
		}
		if(dsi_config->te_mipi_en) {
			mipi_dsih_hal_tear_effect_ack_en(dsi, 1);
		} else {
			mipi_dsih_hal_tear_effect_ack_en(dsi, 0);
		}
		mipi_dsih_hal_gen_set_mode(dsi, 1);
		mipi_dsih_hal_dpi_color_coding(dsi, dsi->video_config->color_coding);
	}

	return 0;
}

static int jz_dsi_query_te(struct dsi_device *dsi)
{
	struct dsi_cmd_packet set_tear_on = {0x15, 0x35, 0x00};
	/* unsigned int cmd_mode_cfg; */

	if(!dsi->dsi_config->te_mipi_en)
		return 0;

	//return 0;

	/* According to DSI host spec. */
	/*
	Tearing effect request must always be triggered by a set_tear_on
	command in the DWC_mipi_dsi_host implementation
	*/
	write_command(dsi, set_tear_on);

	return 0;

}

/* define MIPI-DSI Master operations. */
static struct dsi_master_ops jz_master_ops = {
    .video_cfg      = jz_dsi_video_cfg,
    .mode_cfg	    = jz_dsi_mode_cfg,
    .cmd_write      = write_command,	/*jz_dsi_wr_data, */
    .query_te	    = jz_dsi_query_te,
    .cmd_read       = NULL,	/*jz_dsi_rd_data, */
    .ioctl          = jz_mipi_dsi_ioctl,
    .set_blank_mode = jz_mipi_dsi_blank_mode,
};

int mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
{
	struct mipi_dsim_ddi *dsim_ddi;

	if (!lcd_dev->name) {
		pr_err("dsim_lcd_device name is NULL.\n");
		return -EFAULT;
	}

	dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL);
	if (!dsim_ddi) {
		pr_err("failed to allocate dsim_ddi object.\n");
		return -ENOMEM;
	}

	dsim_ddi->dsim_lcd_dev = lcd_dev;

	mutex_lock(&mipi_dsim_lock);
	list_add_tail(&dsim_ddi->list, &dsim_ddi_list);
	mutex_unlock(&mipi_dsim_lock);

	return 0;
}

static struct mipi_dsim_ddi *mipi_dsi_find_lcd_device(
					struct mipi_dsim_lcd_driver *lcd_drv)
{
	struct mipi_dsim_ddi *dsim_ddi, *next;
	struct mipi_dsim_lcd_device *lcd_dev;

	mutex_lock(&mipi_dsim_lock);

	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
		if (!dsim_ddi)
			goto out;

		lcd_dev = dsim_ddi->dsim_lcd_dev;
		if (!lcd_dev)
			continue;

		if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) {
			/**
			 * bus_id would be used to identify
			 * connected bus.
			 */
			dsim_ddi->bus_id = lcd_dev->bus_id;
			mutex_unlock(&mipi_dsim_lock);

			return dsim_ddi;
		}

		list_del(&dsim_ddi->list);
		kfree(dsim_ddi);
	}

out:
	mutex_unlock(&mipi_dsim_lock);

	return NULL;
}

int mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
{
	struct mipi_dsim_ddi *dsim_ddi;

	if (!lcd_drv->name) {
		pr_err("dsim_lcd_driver name is NULL.\n");
		return -EFAULT;
	}

	dsim_ddi = mipi_dsi_find_lcd_device(lcd_drv);
	if (!dsim_ddi) {
		pr_err("mipi_dsim_ddi object not found.\n");
		return -EFAULT;
	}

	dsim_ddi->dsim_lcd_drv = lcd_drv;

	pr_info("registered panel driver(%s) to mipi-dsi driver.\n",
		lcd_drv->name);

	return 0;

}

static struct mipi_dsim_ddi *mipi_dsi_bind_lcd_ddi(
						struct dsi_device *dsim,
						const char *name)
{
	struct mipi_dsim_ddi *dsim_ddi, *next;
	struct mipi_dsim_lcd_driver *lcd_drv;
	struct mipi_dsim_lcd_device *lcd_dev;
	int ret;

	mutex_lock(&dsim->lock);

	list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
		lcd_drv = dsim_ddi->dsim_lcd_drv;
		lcd_dev = dsim_ddi->dsim_lcd_dev;

		pr_debug("dsi->dev: lcd_drv->name  = %s, name = %s\n",
				lcd_drv->name, name);
		if ((strcmp(lcd_drv->name, name) == 0)) {
			lcd_dev->master = dsim;

			dev_set_name(&lcd_dev->dev, "%s", lcd_drv->name);

			ret = device_register(&lcd_dev->dev);
			if (ret < 0) {
				pr_err("can't register %s, status %d\n",
					dev_name(&lcd_dev->dev), ret);
				mutex_unlock(&dsim->lock);
				return NULL;
			}

			dsim->dsim_lcd_dev = lcd_dev;
			dsim->dsim_lcd_drv = lcd_drv;

			mutex_unlock(&dsim->lock);

			return dsim_ddi;
		}else{
			pr_err("dsi->dev: lcd_drv->name is different with fb name\n");
		}
	}

	mutex_unlock(&dsim->lock);

	return NULL;
}

struct dsi_device * jzdsi_init(struct jzdsi_data *pdata)
{
	struct dsi_device *dsi;
	struct dsi_phy *dsi_phy;
	struct mipi_dsim_ddi *dsim_ddi;
	int ret = -EINVAL;
	pr_debug("entry %s()\n", __func__);

	dsi = (struct dsi_device *)kzalloc(sizeof(struct dsi_device), GFP_KERNEL);
	if (!dsi) {
		pr_err("dsi->dev: failed to allocate dsi object.\n");
		ret = -ENOMEM;
		goto err_dsi;
	}

	dsi_phy = (struct dsi_phy *)kzalloc(sizeof(struct dsi_phy), GFP_KERNEL);
	if (!dsi_phy) {
		pr_err("dsi->dev: failed to allocate dsi phy  object.\n");
		ret = -ENOMEM;
		goto err_dsi_phy;
	}
	dsi->dsi_config = &(pdata->dsi_config);

	dsi_phy->status = NOT_INITIALIZED;
	dsi_phy->reference_freq = REFERENCE_FREQ;
	dsi_phy->bsp_pre_config = set_base_dir_tx;
	dsi->dsi_phy = dsi_phy;
	dsi->video_config = &(pdata->video_config);
	dsi->video_config->refresh = pdata->modes->refresh;
	dsi->video_config->pixel_clock = PICOS2KHZ(pdata->modes->pixclock);	// dpi_clock
	dsi->video_config->h_polarity = pdata->modes->sync & FB_SYNC_HOR_HIGH_ACT;
	dsi->video_config->h_active_pixels = pdata->modes->xres;
	dsi->video_config->h_sync_pixels = pdata->modes->hsync_len;
	dsi->video_config->h_back_porch_pixels = pdata->modes->left_margin;
	dsi->video_config->h_total_pixels = pdata->modes->xres + pdata->modes->hsync_len + pdata->modes->left_margin + pdata->modes->right_margin;
	dsi->video_config->v_active_lines = pdata->modes->yres;
	dsi->video_config->v_polarity =  pdata->modes->sync & FB_SYNC_VERT_HIGH_ACT;
	dsi->video_config->v_sync_lines = pdata->modes->vsync_len;
	dsi->video_config->v_back_porch_lines = pdata->modes->upper_margin;
	dsi->video_config->v_total_lines = pdata->modes->yres + pdata->modes->upper_margin + pdata->modes->lower_margin + pdata->modes->vsync_len;

	pr_debug("dsi->video_config->h_total_pixels: %d\n", dsi->video_config->h_total_pixels);
	pr_debug("dsi->video_config->v_total_lines: %d\n", dsi->video_config->v_total_lines);
	pr_debug("jzfb_pdata.modes->refresh: %d\n", pdata->modes->refresh);
	pr_debug("jzfb_pdata.bpp: %d\n", pdata->bpp_info);
	pr_debug("dsi->video_config->no_of_lanes: %d\n", dsi->video_config->no_of_lanes);
	pr_debug("---dsi->video_config->byte_clock: %d\n", dsi->video_config->byte_clock);

	printk("dsi->video_config->h_total_pixels: %d\n", dsi->video_config->h_total_pixels);
	printk("dsi->video_config->v_total_lines: %d\n", dsi->video_config->v_total_lines);
	printk("jzfb_pdata.modes->refresh: %d\n", pdata->modes->refresh);
	printk("jzfb_pdata.bpp: %d\n", pdata->bpp_info);
	printk("dsi->video_config->no_of_lanes: %d\n", dsi->video_config->no_of_lanes);
	printk("---dsi->video_config->byte_clock: %d\n", dsi->video_config->byte_clock);

	if(!dsi->video_config->byte_clock) {
		dsi->video_config->byte_clock = dsi->video_config->h_total_pixels * dsi->video_config->v_total_lines *
							pdata->modes->refresh * pdata->bpp_info / dsi->video_config->no_of_lanes / 8 / 1000 ;
#if 0
		if (dsi->video_config->no_of_lanes == 2) {
			if (pdata->modes->refresh == 15)
				dsi->video_config->byte_clock = dsi->video_config->byte_clock*6 + dsi->video_config->byte_clock / 2;
			else if (pdata->modes->refresh == 20)
				dsi->video_config->byte_clock = dsi->video_config->byte_clock*5 + dsi->video_config->byte_clock / 2;
			else if (pdata->modes->refresh == 25)
				dsi->video_config->byte_clock = dsi->video_config->byte_clock*4 + dsi->video_config->byte_clock / 2;
			else if (pdata->modes->refresh == 30)
				dsi->video_config->byte_clock = dsi->video_config->byte_clock*3 + dsi->video_config->byte_clock / 2;
			else if (pdata->modes->refresh == 60)
				dsi->video_config->byte_clock = dsi->video_config->byte_clock + dsi->video_config->byte_clock / 2;
		} else if (dsi->video_config->no_of_lanes == 4){
			if (pdata->modes->refresh == 15)
				dsi->video_config->byte_clock = dsi->video_config->byte_clock*10;
			else if (pdata->modes->refresh == 20)
				dsi->video_config->byte_clock = dsi->video_config->byte_clock*9;
			else if (pdata->modes->refresh == 25)
				dsi->video_config->byte_clock = dsi->video_config->byte_clock*7;
			else if (pdata->modes->refresh == 30)
				dsi->video_config->byte_clock = dsi->video_config->byte_clock*5;
			else if (pdata->modes->refresh == 60)
				dsi->video_config->byte_clock = dsi->video_config->byte_clock*3;
		}
#endif
		/* switch(dsi->video_config->byte_clock_coef) {
		case MIPI_PHY_BYTE_CLK_COEF_MUL1:
			break;
		case MIPI_PHY_BYTE_CLK_COEF_MUL3_DIV2:
			dsi->video_config->byte_clock = dsi->video_config->byte_clock * 3 / 2;
			break;
		case MIPI_PHY_BYTE_CLK_COEF_MUL4_DIV3:
			dsi->video_config->byte_clock = dsi->video_config->byte_clock * 4 / 3;
			break;
		case MIPI_PHY_BYTE_CLK_COEF_MUL5_DIV4:
			dsi->video_config->byte_clock = dsi->video_config->byte_clock * 5 / 4;
			break;
		case MIPI_PHY_BYTE_CLK_COEF_MUL6_DIV5:
			dsi->video_config->byte_clock = dsi->video_config->byte_clock * 6 / 5;
			break;
		default:
			break;
		} */
	}

	if (dsi->video_config->byte_clock * 8 > dsi->dsi_config->max_bps * 1000) {
		pr_err("+++++++++++++warning: DATALANE_BPS is over lcd max_bps allowed ,auto set it lcd max_bps %d\n", dsi->video_config->byte_clock);
		//dsi->video_config->byte_clock = dsi->dsi_config->max_bps * 1000 / 8;
	}

	/*dsi->video_config->byte_clock = dsi->video_config->pixel_clock / 4;*/

	pr_debug("%s, %d byte_clock %d KHz, pixel_clock:%d KHz\n", __func__, __LINE__, dsi->video_config->byte_clock, dsi->video_config->pixel_clock);
	printk("%s, %d byte_clock %d KHz, pixel_clock:%d KHz\n", __func__, __LINE__, dsi->video_config->byte_clock, dsi->video_config->pixel_clock);

	dsi->master_ops = &jz_master_ops;

	dsi->clk = clk_get(NULL, "gate_dsi");
	if (IS_ERR(dsi->clk)) {
		pr_err("failed to get dsi clock source\n");
		goto err_put_clk;
	}
	clk_prepare_enable(dsi->clk);

	dsi->address = DSI_IOBASE;
	if (!dsi->address) {
		pr_err("Failed to ioremap register dsi memory region\n");
		goto err_iounmap;
	}
	dsi->phy_address = DSI_PHY_IOBASE;
	if(!dsi->phy_address) {
		pr_err("Failed to ioremap dsi phy memory region!\n");
		goto err_iounmap;
	}


	mutex_init(&dsi->lock);

	dsim_ddi = mipi_dsi_bind_lcd_ddi(dsi, pdata->modes->name);
	if (!dsim_ddi) {
		pr_err("dsi->dev: mipi_dsim_ddi object not found.\n");
		ret = -EINVAL;
		goto err_bind_lcd;
	}

	if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe)
		dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev);

	if (mipi_dsih_read_word(dsi, R_DSI_HOST_PWR_UP) & 0x1) {
		dsi->state = UBOOT_INITIALIZED;
	}

	if(dsi->state == UBOOT_INITIALIZED) {

		dsi->dsi_phy->status = INITIALIZED;
		dsi->state = INITIALIZED; /*must be here for set_sequence function*/
	} else {

		dsi->state = NOT_INITIALIZED; /*must be here for set_sequence function*/
		ret = jz_mipi_update_cfg(dsi);
		if (ret) {
			goto err_dsi_init;
		}

		if (dsim_ddi->dsim_lcd_drv) {
			if (dsim_ddi->dsim_lcd_drv->power_on)
				dsim_ddi->dsim_lcd_drv->power_on(dsim_ddi->dsim_lcd_dev, 1);
			if (dsim_ddi->dsim_lcd_drv->set_sequence)
				dsim_ddi->dsim_lcd_drv->set_sequence(dsim_ddi->dsim_lcd_dev);
		}else{
			pr_err("lcd mipi panel init failed!\n");
			goto err_panel_init;
		}
	}

	/* jz_mipi_dsi_init_interrupt(dsi); */

	dsi->suspended = false;

#ifdef CONFIG_DSI_DPI_DEBUG	/*test pattern */
	unsigned int tmp = 0;
	jz_dsi_video_cfg(dsi);

	tmp = mipi_dsih_read_word(dsi, R_DSI_HOST_VID_MODE_CFG);
	tmp |= 1 << 16 | 0 << 20 | 1 << 24;
	mipi_dsih_write_word(dsi, R_DSI_HOST_VID_MODE_CFG, tmp);
#endif

	return dsi;
err_panel_init:
	pr_err("dsi->dev: lcd mipi panel init error\n");
err_dsi_init:
	pr_err("dsi->dev: lcd mipi dsi init error\n");
err_bind_lcd:
	iounmap((void __iomem *)dsi->address);
err_iounmap:
	clk_put(dsi->clk);
err_put_clk:
	kfree(dsi_phy);
err_dsi_phy:
	kfree(dsi);
err_dsi:
	return NULL;
}

void jzdsi_remove(struct dsi_device *dsi)
{
	struct dsi_phy *dsi_phy;
	dsi_phy = dsi->dsi_phy;

	iounmap((void __iomem *)dsi->address);
	clk_disable(dsi->clk);
	clk_put(dsi->clk);
	kfree(dsi_phy);
	kfree(dsi);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值