From 3ce47ce17ac852f04b2fd56146b3bda9d05d34e4 Mon Sep 17 00:00:00 2001 From: hhb Date: Fri, 14 Jun 2013 16:00:08 +0800 Subject: [PATCH] mipi: modify dsi framework and add rk616 mipi dis dirver --- drivers/video/rockchip/screen/rk_screen.c | 8 +- drivers/video/rockchip/transmitter/Kconfig | 19 +- drivers/video/rockchip/transmitter/Makefile | 6 +- drivers/video/rockchip/transmitter/mipi_dsi.c | 15 +- drivers/video/rockchip/transmitter/mipi_dsi.h | 24 +- .../rockchip/transmitter/rk616_mipi_dsi.c | 1064 +++++++++++++++++ .../rockchip/transmitter/rk616_mipi_dsi.h | 316 +++++ drivers/video/rockchip/transmitter/ssd2828.c | 8 +- drivers/video/rockchip/transmitter/tc358768.c | 19 +- include/linux/rk_screen.h | 7 + 10 files changed, 1448 insertions(+), 38 deletions(-) create mode 100644 drivers/video/rockchip/transmitter/rk616_mipi_dsi.c create mode 100644 drivers/video/rockchip/transmitter/rk616_mipi_dsi.h diff --git a/drivers/video/rockchip/screen/rk_screen.c b/drivers/video/rockchip/screen/rk_screen.c index b7a4e580a587..06a0d00ad4df 100644 --- a/drivers/video/rockchip/screen/rk_screen.c +++ b/drivers/video/rockchip/screen/rk_screen.c @@ -227,7 +227,13 @@ void set_lcd_info(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info ) screen->swap_gb = SWAP_GB; screen->swap_delta = 0; screen->swap_dumy = 0; - + +#if defined(CONFIG_MIPI_DSI) + /* MIPI DSI */ + screen->dsi_lane = MIPI_DSI_LANE; + //screen->dsi_video_mode = MIPI_DSI_VIDEO_MODE; + screen->hs_tx_clk = MIPI_DSI_HS_CLK; +#endif /* Operation function*/ #if defined(RK_SCREEN_INIT) //some screen need to init by spi or i2c screen->init = rk_lcd_init; diff --git a/drivers/video/rockchip/transmitter/Kconfig b/drivers/video/rockchip/transmitter/Kconfig index 820fc1916377..cbd56e27e36b 100644 --- a/drivers/video/rockchip/transmitter/Kconfig +++ b/drivers/video/rockchip/transmitter/Kconfig @@ -28,17 +28,26 @@ config DP501 bool"RGB to Display Port transmitter dp501 support" depends on RK_TRSM -config TC358768_RGB2MIPI - bool "toshiba TC358768 RGB to MIPI DSI" +config MIPI_DSI depends on RK_TRSM + bool "Rockchip MIPI DSI support" + +config TC358768_RGB2MIPI + tristate "toshiba TC358768 RGB to MIPI DSI" + depends on MIPI_DSI help "a chip that change RGB interface parallel signal into DSI serial signal" config SSD2828_RGB2MIPI - bool "solomon SSD2828 RGB to MIPI DSI" - depends on RK_TRSM + tristate "solomon SSD2828 RGB to MIPI DSI" + depends on MIPI_DSI help "a chip that change RGB interface parallel signal into DSI serial signal" - + +config RK616_MIPI_DSI + tristate "RK616(JettaB) mipi dsi support" + depends on MFD_RK616 && MIPI_DSI + help + RK616(Jetta B) mipi dstristatei support. diff --git a/drivers/video/rockchip/transmitter/Makefile b/drivers/video/rockchip/transmitter/Makefile index 0fa2485703cb..010fc6a0d0af 100644 --- a/drivers/video/rockchip/transmitter/Makefile +++ b/drivers/video/rockchip/transmitter/Makefile @@ -4,7 +4,9 @@ obj-$(CONFIG_RK2928_LVDS) += rk2928_lvds.o obj-$(CONFIG_RK610_LVDS) += rk610_lcd.o obj-$(CONFIG_RK616_LVDS) += rk616_lvds.o -obj-$(CONFIG_TC358768_RGB2MIPI) += mipi_dsi.o tc358768.o -obj-$(CONFIG_SSD2828_RGB2MIPI) += mipi_dsi.o ssd2828.o obj-$(CONFIG_DP_ANX6345) += dp_anx6345.o obj-$(CONFIG_DP501) += dp501.o +obj-$(CONFIG_MIPI_DSI) += mipi_dsi.o +obj-$(CONFIG_RK616_MIPI_DSI) += rk616_mipi_dsi.o +obj-$(CONFIG_TC358768_RGB2MIPI) += tc358768.o +obj-$(CONFIG_SSD2828_RGB2MIPI) += ssd2828.o \ No newline at end of file diff --git a/drivers/video/rockchip/transmitter/mipi_dsi.c b/drivers/video/rockchip/transmitter/mipi_dsi.c index e14fd2a1800a..10fcc2231ed4 100644 --- a/drivers/video/rockchip/transmitter/mipi_dsi.c +++ b/drivers/video/rockchip/transmitter/mipi_dsi.c @@ -60,7 +60,7 @@ int del_dsi_ops(struct mipi_dsi_ops *ops) { EXPORT_SYMBOL(del_dsi_ops); int dsi_probe_current_chip(void) { - + int ret = 0; u32 i = 0, id; struct mipi_dsi_ops *ops = NULL; if(cur_dsi_ops) @@ -77,13 +77,14 @@ int dsi_probe_current_chip(void) { printk("mipi dsi chip is not found, read id:%08x, but %08x is correct\n", id, ops->id); dsi_ops[i] = NULL; cur_dsi_ops = NULL; + ret = -1; } } } if(i == MAX_DSI_CHIPS) printk("no mipi dsi chip\n"); - return 0; + return ret; } EXPORT_SYMBOL(dsi_probe_current_chip); @@ -108,7 +109,7 @@ int dsi_power_off(void) { } EXPORT_SYMBOL(dsi_power_off); -int dsi_set_regs(void *array, int n) { +int dsi_set_regs(void *array, u32 n) { if(!cur_dsi_ops) return -1; @@ -118,7 +119,7 @@ int dsi_set_regs(void *array, int n) { } EXPORT_SYMBOL(dsi_set_regs); -int dsi_init(void *array, int n) { +int dsi_init(void *array, u32 n) { if(!cur_dsi_ops) return -1; @@ -129,7 +130,7 @@ int dsi_init(void *array, int n) { EXPORT_SYMBOL(dsi_init); -int dsi_send_dcs_packet(unsigned char *packet, int n) { +int dsi_send_dcs_packet(unsigned char *packet, u32 n) { if(!cur_dsi_ops) return -1; @@ -140,7 +141,7 @@ int dsi_send_dcs_packet(unsigned char *packet, int n) { EXPORT_SYMBOL(dsi_send_dcs_packet); -int dsi_read_dcs_packet(unsigned char *packet, int n) { +int dsi_read_dcs_packet(unsigned char *packet, u32 n) { if(!cur_dsi_ops) return -1; @@ -151,7 +152,7 @@ int dsi_read_dcs_packet(unsigned char *packet, int n) { EXPORT_SYMBOL(dsi_read_dcs_packet); -int dsi_send_packet(void *packet, int n) { +int dsi_send_packet(void *packet, u32 n) { if(!cur_dsi_ops) return -1; diff --git a/drivers/video/rockchip/transmitter/mipi_dsi.h b/drivers/video/rockchip/transmitter/mipi_dsi.h index b0d54f803539..6a1f5596a203 100644 --- a/drivers/video/rockchip/transmitter/mipi_dsi.h +++ b/drivers/video/rockchip/transmitter/mipi_dsi.h @@ -113,11 +113,11 @@ struct mipi_dsi_ops { u32 id; char *name; int (*get_id)(void); - int (*dsi_init)(void *, int n); - int (*dsi_set_regs)(void *, int n); - int (*dsi_send_dcs_packet)(unsigned char *, int n); - int (*dsi_read_dcs_packet)(unsigned char *, int n); - int (*dsi_send_packet)(void *, int n); + int (*dsi_init)(void *, u32 n); + int (*dsi_set_regs)(void *, u32 n); + int (*dsi_send_dcs_packet)(unsigned char *, u32 n); + int (*dsi_read_dcs_packet)(unsigned char *, u32 n); + int (*dsi_send_packet)(void *, u32 n); int (*power_up)(void); int (*power_down)(void); }; @@ -128,9 +128,13 @@ int del_dsi_ops(struct mipi_dsi_ops *ops); int dsi_power_up(void); int dsi_power_off(void); int dsi_probe_current_chip(void); -int dsi_init(void *array, int n); -int dsi_set_regs(void *array, int n); -int dsi_send_dcs_packet(unsigned char *packet, int n); -int dsi_read_dcs_packet(unsigned char *packet, int n); -int dsi_send_packet(void *packet, int n); +int dsi_init(void *array, u32 n); + +int dsi_enable_video_mode(u32 enable); +int dsi_set_virtual_channel(u32 channel); + +int dsi_set_regs(void *array, u32 n); +int dsi_send_dcs_packet(unsigned char *packet, u32 n); +int dsi_read_dcs_packet(unsigned char *packet, u32 n); +int dsi_send_packet(void *packet, u32 n); #endif /* end of MIPI_DSI_H_ */ diff --git a/drivers/video/rockchip/transmitter/rk616_mipi_dsi.c b/drivers/video/rockchip/transmitter/rk616_mipi_dsi.c new file mode 100644 index 000000000000..5f1ef9035aa4 --- /dev/null +++ b/drivers/video/rockchip/transmitter/rk616_mipi_dsi.c @@ -0,0 +1,1064 @@ +/* +drivers/video/display/transmitter/rk616_mipi_dsi.c +debug sys/kernel/debug/rk616/mipi +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mipi_dsi.h" +#include "rk616_mipi_dsi.h" + +#if 0 +#define MIPI_DBG(x...) printk(KERN_INFO x) +#else +#define MIPI_DBG(x...) +#endif + + +static struct dsi gDsi; +static struct mfd_rk616 *dsi_rk616; +static struct mipi_dsi_ops rk_mipi_dsi_ops; +static struct rk29fb_screen *g_screen = NULL; +static unsigned char dcs_exit_sleep_mode[] = {0x11}; +static unsigned char dcs_set_diaplay_on[] = {0x29}; +static unsigned char dcs_enter_sleep_mode[] = {0x10}; +static unsigned char dcs_set_diaplay_off[] = {0x28}; +static unsigned char dcs_test[] = {0x3e, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}; +static int rk_mipi_dsi_send_dcs_packet(unsigned char regs[], u32 n); + +static int dsi_read_reg(u16 reg, u32 *pval) +{ + return dsi_rk616->read_dev(dsi_rk616, reg, pval); +} + + +static int dsi_write_reg(u16 reg, u32 *pval) +{ + return dsi_rk616->write_dev(dsi_rk616, reg, pval); +} + +static int dsi_get_bits(u32 reg) +{ + u32 val = 0; + u32 bits = (reg >> 8) & 0xff; + u16 reg_addr = (reg >> 16) & 0xffff; + u8 offset = reg & 0xff; + bits = (1 << bits) - 1; + dsi_read_reg(reg_addr, &val); + val >>= offset; + val &= bits; + return val; +} + +static int dsi_set_bits(u32 data, u32 reg) +{ + u32 val = 0; + u32 bits = (reg >> 8) & 0xff; + u16 reg_addr = (reg >> 16) & 0xffff; + u8 offset = reg & 0xff; + bits = (1 << bits) - 1; + + dsi_read_reg(reg_addr, &val); //CAN optimise speed and time cost warnning + val &= ~(bits << offset); + val |= (data & bits) << offset; + dsi_write_reg(reg_addr, &val); + + //if(dsi_get_bits(reg) != data) + // printk("write :%08x error\n", reg); + return 0; +} + +static int rk_mipi_dsi_phy_preset_gotp(void *array, int n) { + + u32 val = 0; + struct rk29fb_screen *screen = array; + + return 0; +} + +static int rk_mipi_dsi_phy_set_gotp(u32 offset, int n) { + + u32 val = 0, temp = 0, Tlpx = 0; + u32 ddr_clk = gDsi.phy.ddr_clk; + u32 Tddr_clk = gDsi.phy.Tddr_clk; + u32 Ttxbyte_clk = gDsi.phy.Ttxbyte_clk; + u32 Tsys_clk = gDsi.phy.Tsys_clk; + u32 Ttxclkesc = gDsi.phy.Ttxclkesc; + + + switch(offset) { + case DPHY_CLOCK_OFFSET: + MIPI_DBG("******set DPHY_CLOCK_OFFSET gotp******\n"); + break; + case DPHY_LANE0_OFFSET: + MIPI_DBG("******set DPHY_LANE0_OFFSET gotp******\n"); + break; + case DPHY_LANE1_OFFSET: + MIPI_DBG("******set DPHY_LANE1_OFFSET gotp******\n"); + break; + case DPHY_LANE2_OFFSET: + MIPI_DBG("******set DPHY_LANE2_OFFSET gotp******\n"); + break; + case DPHY_LANE3_OFFSET: + MIPI_DBG("******set DPHY_LANE3_OFFSET gotp******\n"); + break; + default: + break; + } + + if(ddr_clk < 110 * MHz) + val = 0; + else if(ddr_clk < 150 * MHz) + val = 1; + else if(ddr_clk < 200 * MHz) + val = 2; + else if(ddr_clk < 250 * MHz) + val = 3; + else if(ddr_clk < 300 * MHz) + val = 4; + else if(ddr_clk < 400 * MHz) + val = 5; + else if(ddr_clk < 500 * MHz) + val = 6; + else if(ddr_clk < 600 * MHz) + val = 7; + else if(ddr_clk < 700 * MHz) + val = 8; + else if(ddr_clk < 800 * MHz) + val = 9; + else if(ddr_clk <= 1000 * MHz) + val = 10; + dsi_write_reg(reg_ths_settle + offset, &val); + + if(ddr_clk < 110 * MHz) + val = 0x20; + else if(ddr_clk < 150 * MHz) + val = 0x06; + else if(ddr_clk < 200 * MHz) + val = 0x18; + else if(ddr_clk < 250 * MHz) + val = 0x05; + else if(ddr_clk < 300 * MHz) + val = 0x51; + else if(ddr_clk < 400 * MHz) + val = 0x64; + else if(ddr_clk < 500 * MHz) + val = 0x59; + else if(ddr_clk < 600 * MHz) + val = 0x6a; + else if(ddr_clk < 700 * MHz) + val = 0x3e; + else if(ddr_clk < 800 * MHz) + val = 0x21; + else if(ddr_clk <= 1000 * MHz) + val = 0x09; + + MIPI_DBG("reg_hs_ths_prepare: %d, %d\n", val, val*Tddr_clk/1000); + dsi_write_reg(reg_hs_ths_prepare + offset, &val); + + if(offset != DPHY_CLOCK_OFFSET) { + + if(ddr_clk < 110 * MHz) + val = 2; + else if(ddr_clk < 150 * MHz) + val = 3; + else if(ddr_clk < 200 * MHz) + val = 4; + else if(ddr_clk < 250 * MHz) + val = 5; + else if(ddr_clk < 300 * MHz) + val = 6; + else if(ddr_clk < 400 * MHz) + val = 7; + else if(ddr_clk < 500 * MHz) + val = 7; + else if(ddr_clk < 600 * MHz) + val = 8; + else if(ddr_clk < 700 * MHz) + val = 8; + else if(ddr_clk < 800 * MHz) + val = 9; + else if(ddr_clk <= 1000 * MHz) + val = 9; + } else { + + if(ddr_clk < 110 * MHz) + val = 0x16; + else if(ddr_clk < 150 * MHz) + val = 0x16; + else if(ddr_clk < 200 * MHz) + val = 0x17; + else if(ddr_clk < 250 * MHz) + val = 0x17; + else if(ddr_clk < 300 * MHz) + val = 0x18; + else if(ddr_clk < 400 * MHz) + val = 0x19; + else if(ddr_clk < 500 * MHz) + val = 0x1b; + else if(ddr_clk < 600 * MHz) + val = 0x1d; + else if(ddr_clk < 700 * MHz) + val = 0x1e; + else if(ddr_clk < 800 * MHz) + val = 0x1f; + else if(ddr_clk <= 1000 * MHz) + val = 0x20; + } + + MIPI_DBG("reg_hs_the_zero: %d, %d\n", val, (val + 5)*Ttxbyte_clk/1000); + dsi_write_reg(reg_hs_the_zero + offset, &val); + + if(ddr_clk < 110 * MHz) + val = 0x22; + else if(ddr_clk < 150 * MHz) + val = 0x45; + else if(ddr_clk < 200 * MHz) + val = 0x0b; + else if(ddr_clk < 250 * MHz) + val = 0x16; + else if(ddr_clk < 300 * MHz) + val = 0x2c; + else if(ddr_clk < 400 * MHz) + val = 0x33; + else if(ddr_clk < 500 * MHz) + val = 0x4e; + else if(ddr_clk < 600 * MHz) + val = 0x3a; + else if(ddr_clk < 700 * MHz) + val = 0x6a; + else if(ddr_clk < 800 * MHz) + val = 0x29; + else if(ddr_clk <= 1000 * MHz) + val = 0x27; + dsi_write_reg(reg_hs_ths_trail + offset, &val); + + val = 120000 / Ttxbyte_clk + 1; + MIPI_DBG("reg_hs_ths_exit: %d, %d\n", val, val*Ttxbyte_clk/1000); + dsi_write_reg(reg_hs_ths_exit + offset, &val); + + if(offset == DPHY_CLOCK_OFFSET) { + val = (80000 + 52*gDsi.phy.UI) / Ttxbyte_clk + 1; + MIPI_DBG("reg_hs_tclk_post: %d, %d\n", val, val*Ttxbyte_clk/1000); + dsi_write_reg(reg_hs_tclk_post + offset, &val); + val = 10*gDsi.phy.UI / Ttxbyte_clk + 1; + MIPI_DBG("reg_hs_tclk_pre: %d, %d\n", val, val*Ttxbyte_clk/1000); + dsi_write_reg(reg_hs_tclk_pre + offset, &val); + } + + val = 1010000000 / Tsys_clk + 1; + MIPI_DBG("reg_hs_twakup: %d, %d\n", val, val*Tsys_clk/1000); + if(val > 0x3ff) { + val = 0x2ff; + MIPI_DBG("val is too large, 0x3ff is the largest\n"); + } + temp = (val >> 8) & 0x03; + val &= 0xff; + dsi_write_reg(reg_hs_twakup_h + offset, &temp); + dsi_write_reg(reg_hs_twakup_l + offset, &val); + + if(Ttxclkesc > 50000) { + val = 2*Ttxclkesc; + MIPI_DBG("Ttxclkesc:%d\n", Ttxclkesc); + } + val = val / Ttxbyte_clk; + Tlpx = val*Ttxbyte_clk; + MIPI_DBG("reg_hs_tlpx: %d, %d\n", val, Tlpx); + val -= 2; + dsi_write_reg(reg_hs_tlpx + offset, &val); + + Tlpx = 2*Ttxclkesc; + val = 4*Tlpx / Ttxclkesc; + MIPI_DBG("reg_hs_tta_go: %d, %d\n", val, val*Ttxclkesc); + dsi_write_reg(reg_hs_tta_go + offset, &val); + + val = 3 * Tlpx / 2 / Ttxclkesc; + MIPI_DBG("reg_hs_tta_sure: %d, %d\n", val, val*Ttxclkesc); + dsi_write_reg(reg_hs_tta_sure + offset, &val); + + val = 5 * Tlpx / Ttxclkesc; + MIPI_DBG("reg_hs_tta_wait: %d, %d\n", val, val*Ttxclkesc); + dsi_write_reg(reg_hs_tta_wait + offset, &val); +#if 1 + val = 0x5b; + dsi_write_reg(offset + 0x18, &val); + val = 0x38; + dsi_write_reg(offset + 0x20, &val); +#endif + return 0; +} + + +static int rk_mipi_dsi_phy_init(void *array, int n) { + + u32 val = 0; + struct rk29fb_screen *screen = array; + //DPHY init + dsi_set_bits((gDsi.phy.fbdiv >> 8) & 0x01, reg_fbdiv_8); + dsi_set_bits(gDsi.phy.prediv, reg_prediv); + dsi_set_bits(gDsi.phy.fbdiv & 0xff, reg_fbdiv); + + val = 0xe4; + dsi_write_reg(DPHY_REGISTER1, &val); + + switch(gDsi.host.lane) { + case 4: + dsi_set_bits(1, lane_en_3); + case 3: + dsi_set_bits(1, lane_en_2); + case 2: + dsi_set_bits(1, lane_en_1); + case 1: + dsi_set_bits(1, lane_en_0); + dsi_set_bits(1, lane_en_ck); + break; + default: + break; + } + + val = 0xe0; + dsi_write_reg(DPHY_REGISTER1, &val); + udelay(10); + + val = 0x1e; + dsi_write_reg(DPHY_REGISTER20, &val); + val = 0x1f; + dsi_write_reg(DPHY_REGISTER20, &val); +#if 0 + //new temp + val = 0xff; + dsi_write_reg(0x0c24, &val); + + val = 0x77; + dsi_write_reg(0x0c18, &val); + val = 0x77; + dsi_write_reg(0x0c1c, &val); + + val = 0x4f; + dsi_write_reg(0x0c20, &val); + + val = 0xc0; + dsi_write_reg(0x0c28, &val); +#endif + +#if 0 + val = 0xff; + dsi_write_reg(RK_ADDR(0x09), &val); + val = 0x4e; + dsi_write_reg(RK_ADDR(0x08), &val); + val = 0x84; + dsi_write_reg(RK_ADDR(0x0a), &val); +#endif + + val = 0x30; + dsi_write_reg(RK_ADDR(0x05), &val); + + //if(800 <= gDsi.phy.ddr_clk && gDsi.phy.ddr_clk <= 1000) + switch(gDsi.host.lane) { + case 4: + rk_mipi_dsi_phy_set_gotp(DPHY_LANE3_OFFSET, n); + case 3: + rk_mipi_dsi_phy_set_gotp(DPHY_LANE2_OFFSET, n); + case 2: + rk_mipi_dsi_phy_set_gotp(DPHY_LANE1_OFFSET, n); + case 1: + rk_mipi_dsi_phy_set_gotp(DPHY_LANE0_OFFSET, n); + rk_mipi_dsi_phy_set_gotp(DPHY_CLOCK_OFFSET, n); + break; + default: + break; + } + return 0; +} + + +static int rk_mipi_dsi_host_init(void *array, int n) { + + u32 val = 0, bytes_px = 0; + struct rk29fb_screen *screen = array; + u32 decimals = gDsi.phy.Ttxbyte_clk, temp = 0, i = 0; + u32 m = 1, lane = gDsi.host.lane, Tpclk = gDsi.phy.Tpclk, Ttxbyte_clk = gDsi.phy.Ttxbyte_clk; + + val = 0x04000000; + dsi_write_reg(CRU_CRU_CLKSEL1_CON, &val); + + dsi_set_bits(gDsi.host.lane - 1, n_lanes); + dsi_set_bits(gDsi.vid, dpi_vid); + + switch(screen->face) { + case OUT_P888: + dsi_set_bits(7, dpi_color_coding); + bytes_px = 3; + break; + case OUT_D888_P666: + case OUT_P666: + dsi_set_bits(3, dpi_color_coding); + dsi_set_bits(1, en18_loosely); + bytes_px = 3; + break; + case OUT_P565: + dsi_set_bits(0, dpi_color_coding); + bytes_px = 2; + default: + break; + } + + dsi_set_bits(!screen->pin_hsync, hsync_active_low); + dsi_set_bits(!screen->pin_vsync, vsync_active_low); + dsi_set_bits(screen->pin_den, dataen_active_low); + dsi_set_bits(1, colorm_active_low); + dsi_set_bits(1, shutd_active_low); + + dsi_set_bits(gDsi.host.video_mode, vid_mode_type); //burst mode //need to expand + switch(gDsi.host.video_mode) { + case VM_BM: + dsi_set_bits(screen->x_res, vid_pkt_size); + break; + case VM_NBMWSE: + case VM_NBMWSP: + for(i = 8; i < 32; i++){ + temp = i * lane * Tpclk % Ttxbyte_clk; + if(decimals > temp) { + decimals = temp; + m = i; + } + if(decimals == 0) + break; + } + dsi_set_bits(1, en_multi_pkt); + dsi_set_bits(screen->x_res / m + 1, num_chunks); + dsi_set_bits(m, vid_pkt_size); + temp = m * lane * Tpclk / Ttxbyte_clk - m * bytes_px; + MIPI_DBG("%s:%d, %d\n", __func__, m, temp); + if(temp >= 12) { + dsi_set_bits(1, en_null_pkt); + dsi_set_bits(temp - 12, null_pkt_size); + } + break; + default: + break; + } + + val = 0x0; + dsi_write_reg(CMD_MODE_CFG, &val); + + dsi_set_bits(gDsi.phy.Tpclk * (screen->x_res + screen->left_margin + screen->hsync_len + screen->right_margin) \ + / gDsi.phy.Ttxbyte_clk, hline_time); + dsi_set_bits(gDsi.phy.Tpclk * screen->left_margin / gDsi.phy.Ttxbyte_clk, hbp_time); + dsi_set_bits(gDsi.phy.Tpclk * screen->hsync_len / gDsi.phy.Ttxbyte_clk, hsa_time); + + dsi_set_bits(screen->y_res, v_active_lines); + dsi_set_bits(screen->lower_margin, vfp_lines); + dsi_set_bits(screen->upper_margin, vbp_lines); + dsi_set_bits(screen->vsync_len, vsa_lines); + + gDsi.phy.txclkesc = 10 * MHz; + val = gDsi.phy.txbyte_clk / gDsi.phy.txclkesc + 1; + gDsi.phy.txclkesc = gDsi.phy.txbyte_clk / val; + dsi_set_bits(val, TX_ESC_CLK_DIVISION); + + + dsi_set_bits(10, TO_CLK_DIVISION); + dsi_set_bits(1000, lprx_to_cnt); + dsi_set_bits(1000, hstx_to_cnt); + dsi_set_bits(100, phy_stop_wait_time); + + dsi_set_bits(4, outvact_lpcmd_time); //byte + dsi_set_bits(4, invact_lpcmd_time); + + dsi_set_bits(20, phy_hs2lp_time); + dsi_set_bits(16, phy_lp2hs_time); + + dsi_set_bits(10, max_rd_time); + + dsi_set_bits(1, dpicolom); + dsi_set_bits(1, dpishutdn); + + //interrupt //need + val = 0x1fffff; + dsi_write_reg(ERROR_MSK0, &val); + val = 0x1ffff; + dsi_write_reg(ERROR_MSK1, &val); + + dsi_set_bits(1, en_lp_hfp); + //dsi_set_bits(1, en_lp_hbp); + dsi_set_bits(1, en_lp_vact); + dsi_set_bits(1, en_lp_vfp); + dsi_set_bits(1, en_lp_vbp); + dsi_set_bits(1, en_lp_vsa); + + //dsi_set_bits(1, frame_BTA_ack); + dsi_set_bits(1, shutdownz); + //dsi_set_bits(1, phy_enableclk); + + val = 10; + while(!dsi_get_bits(phylock) && val--) { + udelay(10); + }; + if(val == 0) + printk("%s:phylock fail\n", __func__); + val = 10; + while(!dsi_get_bits(phystopstateclklane) && val--) { + udelay(10); + }; + + dsi_set_bits(4, phy_tx_triggers); + //dsi_set_bits(1, phy_txexitulpslan); + //dsi_set_bits(1, phy_txexitulpsclk); + dsi_set_bits(1, phy_txrequestclkhs); + dsi_set_bits(0, en_video_mode); + + return 0; +} + + + +/* + mipi protocol layer definition +*/ +static int rk_mipi_dsi_init(void *array, u32 n) { + u32 decimals = 1000, i = 0, pre = 0; + struct rk29fb_screen *screen = array; + struct rk_lcdc_device_driver *dev_drv; + + if(!g_screen && screen) + g_screen = screen; + + if(g_screen->type != SCREEN_MIPI) { + printk("only mipi dsi lcd is supported\n"); + return -1; + } + + gDsi.phy.Tpclk = rk_fb_get_prmry_screen_pixclock(); + + if(dsi_rk616->mclk) + gDsi.phy.ref_clk = clk_get_rate(dsi_rk616->mclk); + else + gDsi.phy.ref_clk = 24 * MHz; + + gDsi.phy.sys_clk = gDsi.phy.ref_clk; + + if((screen->hs_tx_clk <= 80 * MHz) || (screen->hs_tx_clk >= 1000 * MHz)) + gDsi.phy.ddr_clk = 1000 * MHz; //default is 1HGz + else + gDsi.phy.ddr_clk = screen->hs_tx_clk; + + if(n != 0) { + gDsi.phy.ddr_clk = n; + } + + decimals = gDsi.phy.ref_clk; + for(i = 1; i < 6; i++) { + pre = gDsi.phy.ref_clk / i; + if((decimals > (gDsi.phy.ddr_clk % pre)) && (gDsi.phy.ddr_clk / pre < 512)) { + decimals = gDsi.phy.ddr_clk % pre; + gDsi.phy.prediv = i; + gDsi.phy.fbdiv = gDsi.phy.ddr_clk / pre; + } + if(decimals == 0) + break; + } + + MIPI_DBG("prediv:%d, fbdiv:%d\n", gDsi.phy.prediv, gDsi.phy.fbdiv); + gDsi.phy.ddr_clk = gDsi.phy.ref_clk / gDsi.phy.prediv * gDsi.phy.fbdiv; + gDsi.phy.txbyte_clk = gDsi.phy.ddr_clk / 8; + + gDsi.phy.txclkesc = 10 * MHz; // < 10MHz + gDsi.phy.txclkesc = gDsi.phy.txbyte_clk / (gDsi.phy.txbyte_clk / gDsi.phy.txclkesc + 1); + + gDsi.phy.pclk = div_u64(1000000000000llu, gDsi.phy.Tpclk); + gDsi.phy.Ttxclkesc = div_u64(1000000000000llu, gDsi.phy.txclkesc); + gDsi.phy.Tsys_clk = div_u64(1000000000000llu, gDsi.phy.sys_clk); + gDsi.phy.Tddr_clk = div_u64(1000000000000llu, gDsi.phy.ddr_clk); + gDsi.phy.Ttxbyte_clk = div_u64(1000000000000llu, gDsi.phy.txbyte_clk); + + gDsi.phy.UI = gDsi.phy.Tddr_clk; + gDsi.vid = 0; + + if(screen->dsi_lane > 0 && screen->dsi_lane <= 4) + gDsi.host.lane = screen->dsi_lane; + else + gDsi.host.lane = 4; + + gDsi.host.video_mode = VM_BM; + + MIPI_DBG("UI:%d\n", gDsi.phy.UI); + MIPI_DBG("ref_clk:%d\n", gDsi.phy.ref_clk); + MIPI_DBG("pclk:%d, Tpclk:%d\n", gDsi.phy.pclk, gDsi.phy.Tpclk); + MIPI_DBG("sys_clk:%d, Tsys_clk:%d\n", gDsi.phy.sys_clk, gDsi.phy.Tsys_clk); + MIPI_DBG("ddr_clk:%d, Tddr_clk:%d\n", gDsi.phy.ddr_clk, gDsi.phy.Tddr_clk); + MIPI_DBG("txbyte_clk:%d, Ttxbyte_clk:%d\n", gDsi.phy.txbyte_clk, gDsi.phy.Ttxbyte_clk); + MIPI_DBG("txclkesc:%d, Ttxclkesc:%d\n", gDsi.phy.txclkesc, gDsi.phy.Ttxclkesc); + + dsi_set_bits(0, en_video_mode); + dsi_set_bits(0, shutdownz); + + rk_mipi_dsi_phy_init(screen, n); + rk_mipi_dsi_host_init(screen, n); + + + if(!screen->init) { + rk_mipi_dsi_send_dcs_packet(dcs_exit_sleep_mode, sizeof(dcs_exit_sleep_mode)); + msleep(1); + rk_mipi_dsi_send_dcs_packet(dcs_set_diaplay_on, sizeof(dcs_set_diaplay_on)); + msleep(10); + } + + dsi_set_bits(1, en_video_mode); + + msleep(10); + rk_mipi_dsi_send_dcs_packet(dcs_enter_sleep_mode, sizeof(dcs_enter_sleep_mode)); + rk_mipi_dsi_send_dcs_packet(dcs_set_diaplay_off, sizeof(dcs_set_diaplay_off)); + + rk616_display_router_cfg(dsi_rk616, screen, 0); +} + + +static int rk_mipi_dsi_send_dcs_packet(unsigned char regs[], u32 n) { + + u32 data = 0, i = 0, j = 0; + if(n <= 0) + return -1; + + if(dsi_get_bits(gen_cmd_full) == 1) { + printk("gen_cmd_full\n"); + return -1; + } + dsi_set_bits(0, lpcmden); //send in high speed mode + + if(n <= 2) { + data = (gDsi.vid << 6) | ((n-1) << 4) | 0x05; + data |= regs[0] << 8; + if(n == 2) + data |= regs[1] << 16; + } else { + data = 0; + for(i = 0; i < n; i++) { + j = i % 4; + data |= regs[i] << (j * 8); + if(j == 3 || ((i + 1) == n)) { + if(dsi_get_bits(gen_pld_w_full) == 1) { + printk("gen_pld_w_full :%d\n", i); + break; + } + dsi_write_reg(GEN_PLD_DATA, &data); + MIPI_DBG("write GEN_PLD_DATA:%d, %08x\n", i, data); + data = 0; + } + } + data = (gDsi.vid << 6) | 0x39; + data |= n << 8; + } + //MIPI_DBG("write GEN_HDR:%08x\n", data); + dsi_write_reg(GEN_HDR, &data); + i = 10; + + while(!dsi_get_bits(gen_cmd_empty) && i--) { + MIPI_DBG("."); + udelay(10); + } + //MIPI_DBG("send command"); + //MIPI_DBG("\n"); + return 0; +} + + +static int rk_mipi_dsi_send_packet(unsigned char type, unsigned char regs[], u32 n) { + + return 0; +} + +static int rk_mipi_dsi_read_dcs_packet(unsigned char *data, u32 n) { + //DCS READ + unsigned int i = 0; + + return 0; +} + +static int rk_mipi_dsi_power_up(void) { + + return 0; +} + +static int rk_mipi_dsi_power_down(void) { + + return 0; +} + +static u32 rk_mipi_dsi_get_id(void) { + + u32 id = 0; + dsi_read_reg(VERSION, &id); + + return id; +} + +static struct mipi_dsi_ops rk_mipi_dsi_ops = { + .id = DWC_DSI_VERSION, + .name = "rk_mipi_dsi", + .get_id = rk_mipi_dsi_get_id, + //.dsi_set_regs = NULL, + .dsi_send_dcs_packet = rk_mipi_dsi_send_dcs_packet, + .dsi_read_dcs_packet = rk_mipi_dsi_read_dcs_packet, + .power_up = rk_mipi_dsi_power_up, + .power_down = rk_mipi_dsi_power_down, + .dsi_init = rk_mipi_dsi_init, +}; + + +#if MIPI_DSI_REGISTER_IO +#include +#include +#include + +static struct proc_dir_entry *reg_proc_entry; + +int reg_proc_write(struct file *file, const char __user *buff, size_t count, loff_t *offp) +{ + int ret = -1, i = 0; + u32 read_val = 0; + char *buf = kmalloc(count, GFP_KERNEL); + char *data = buf; + char str[32]; + char command = 0; + u64 regs_val = 0; + struct regulator *ldo; + ret = copy_from_user((void*)buf, buff, count); + + data = strstr(data, "-"); + if(data == NULL) + goto reg_proc_write_exit; + command = *(++data); + + switch(command) { + case 'w': + while(1) { + + data = strstr(data, "0x"); + if(data == NULL) + goto reg_proc_write_exit; + sscanf(data, "0x%llx", ®s_val); + if((regs_val & 0xffff00000000) == 0) + goto reg_proc_write_exit; + read_val = regs_val & 0xffffffff; + dsi_write_reg(regs_val >> 32, &read_val); + dsi_read_reg(regs_val >> 32, &read_val); + regs_val &= 0xffffffff; + if(read_val != regs_val) + printk("%s fail:0x%08x\n", __func__, read_val); + + data += 3; + msleep(1); + } + + break; + case 'r': + data = strstr(data, "0x"); + if(data == NULL) + goto reg_proc_write_exit; + sscanf(data, "0x%x", ®s_val); + dsi_read_reg((u16)regs_val, &read_val); + printk("*%04x : %08x\n", (u16)regs_val, read_val); + msleep(1); + break; + + case 's': + while(*(++data) == ' '); + sscanf(data, "%d", &read_val); + rk_mipi_dsi_init(g_screen, read_val * MHz); + break; + case 'p': + while(*(++data) == ' '); + sscanf(data, "%d", &read_val); + while(*(++data) == ' '); + sscanf(data, "%s", str); + printk(" get %s\n", str); + ldo = regulator_get(NULL, str); + if(!ldo) + break; + if(read_val == 0) { + while(regulator_is_enabled(ldo)>0) + regulator_disable(ldo); + } else { + regulator_enable(ldo); + } + regulator_put(ldo); + + break; + + default: + break; + } + +reg_proc_write_exit: + kfree(buf); + msleep(10); + return count; +} + + + +int reg_proc_read(struct file *file, char __user *buff, size_t count, loff_t *offp) +{ + int i = 0; + u32 val = 0; + u8 buf[4] = "hhb"; + copy_to_user(buff, buf, 4); + count = 4; + for(i = VERSION; i <= LP_CMD_TIM; i += 4) { + dsi_read_reg(i, &val); + printk("%04x: %08x\n", i, val); + msleep(1); + } + + printk("\n"); + for(i = DPHY_REGISTER0; i <= DPHY_REGISTER4; i += 4) { + dsi_read_reg(i, &val); + printk("%04x: %08x\n", i, val); + msleep(1); + } + printk("\n"); + i = DPHY_REGISTER20; + dsi_read_reg(i, &val); + printk("%04x: %08x\n", i, val); + msleep(1); +#if 1 + printk("\n"); + for(i = DPHY_CLOCK_OFFSET; i <= (DPHY_CLOCK_OFFSET + reg_hs_tta_wait); i += 4) { + dsi_read_reg(i, &val); + printk("%04x: %08x\n", i, val); + msleep(1); + } + + + printk("\n"); + for(i = DPHY_LANE0_OFFSET; i <= (DPHY_LANE0_OFFSET + reg_hs_tta_wait); i += 4) { + dsi_read_reg(i, &val); + printk("%04x: %08x\n", i, val); + msleep(1); + } + + printk("\n"); + for(i = DPHY_LANE1_OFFSET; i <= (DPHY_LANE1_OFFSET + reg_hs_tta_wait); i += 4) { + dsi_read_reg(i, &val); + printk("%04x: %08x\n", i, val); + msleep(1); + } + + printk("\n"); + for(i = DPHY_LANE2_OFFSET; i <= (DPHY_LANE2_OFFSET + reg_hs_tta_wait); i += 4) { + dsi_read_reg(i, &val); + printk("%04x: %08x\n", i, val); + msleep(1); + } + + printk("\n"); + for(i = DPHY_LANE3_OFFSET; i <= (DPHY_LANE3_OFFSET + reg_hs_tta_wait); i += 4) { + dsi_read_reg(i, &val); + printk("%04x: %08x\n", i, val); + msleep(1); + } +#endif + return -1; +} + +int reg_proc_open(struct inode *inode, struct file *file) +{ + //printk("%s\n", __func__); + //msleep(10); + return 0; +} + +int reg_proc_close(struct inode *inode, struct file *file) +{ + //printk("%s\n", __func__); + //msleep(10); + return 0; +} + +struct file_operations reg_proc_fops = { + .owner = THIS_MODULE, + .open = reg_proc_open, + .release = reg_proc_close, + .write = reg_proc_write, + .read = reg_proc_read, +}; + +static int reg_proc_init(char *name) +{ + int ret = 0; +#if 1 + debugfs_create_file("mipi", S_IRUSR, dsi_rk616->debugfs_dir, dsi_rk616, ®_proc_fops); +#else + reg_proc_entry = create_proc_entry(name, 0666, NULL); + if(reg_proc_entry == NULL) { + printk("Couldn't create proc entry : %s!\n", name); + ret = -ENOMEM; + return ret ; + } + else { + printk("Create proc entry:%s success!\n", name); + reg_proc_entry->proc_fops = ®_proc_fops; + } +#endif + return 0; +} + +static int __init rk_mipi_dsi_reg(void) +{ + return reg_proc_init("mipi_dsi"); +} +module_init(rk_mipi_dsi_reg); + +#endif + + + +#if defined(CONFIG_HAS_EARLYSUSPEND) +static void rk616_mipi_dsi_early_suspend(struct early_suspend *h) +{ + u32 val = 0X01; + struct regulator *ldo; + + dsi_set_bits(0, en_video_mode); + + dsi_write_reg(DPHY_REGISTER0, &val); + + val = 0xe3; + dsi_write_reg(DPHY_REGISTER1, &val); + + dsi_set_bits(0, shutdownz); + + ldo = regulator_get(NULL, "ricoh_ldo3"); + if(ldo) { + while(regulator_is_enabled(ldo)>0) + regulator_disable(ldo); + regulator_put(ldo); + } + + + MIPI_DBG("%s\n", __func__); +} + +static void rk616_mipi_dsi_late_resume(struct early_suspend *h) +{ + struct regulator *ldo; + rk_mipi_dsi_phy_init(g_screen, 0); + + //dsi_set_bits(1, shutdownz); + + rk_mipi_dsi_host_init(g_screen, 0); + + rk_mipi_dsi_send_dcs_packet(dcs_exit_sleep_mode, sizeof(dcs_exit_sleep_mode)); + msleep(1); + rk_mipi_dsi_send_dcs_packet(dcs_set_diaplay_on, sizeof(dcs_set_diaplay_on)); + msleep(10); + + dsi_set_bits(1, en_video_mode); + rk616_display_router_cfg(dsi_rk616, g_screen, 0); + + + ldo = regulator_get(NULL, "ricoh_ldo3"); + if(ldo) { + regulator_enable(ldo); + regulator_put(ldo); + } + MIPI_DBG("%s\n", __func__); +} + +#endif + + + +static int rk616_mipi_dsi_probe(struct platform_device *pdev) +{ + int ret = 0; + u32 val; + rk_screen *screen; + struct mfd_rk616 *rk616 = dev_get_drvdata(pdev->dev.parent); + if(!rk616) + { + dev_err(&pdev->dev,"null mfd device rk616!\n"); + return -ENODEV; + } + else + dsi_rk616 = rk616; + + register_dsi_ops(&rk_mipi_dsi_ops); + + ret = dsi_probe_current_chip(); + if(ret) { + dev_err(&pdev->dev,"mipi dsi probe fail\n"); + return -ENODEV; + } + + screen = rk_fb_get_prmry_screen(); + if(!screen) + { + dev_err(&pdev->dev,"the fb prmry screen is null!\n"); + return -ENODEV; + } + + rk_mipi_dsi_init(screen, 0); + +#ifdef CONFIG_HAS_EARLYSUSPEND + gDsi.early_suspend.suspend = rk616_mipi_dsi_early_suspend; + gDsi.early_suspend.resume = rk616_mipi_dsi_late_resume; + gDsi.early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 1; + register_early_suspend(&gDsi.early_suspend); +#endif + + dev_info(&pdev->dev,"rk616 mipi_dsi probe success!\n"); + + return 0; + +} + +static int rk616_mipi_dsi_remove(struct platform_device *pdev) +{ + + return 0; +} + +static void rk616_mipi_dsi_shutdown(struct platform_device *pdev) +{ + + return; +} + +static struct platform_driver rk616_mipi_dsi_driver = { + .driver = { + .name = "rk616-mipi", + .owner = THIS_MODULE, + }, + .probe = rk616_mipi_dsi_probe, + .remove = rk616_mipi_dsi_remove, + .shutdown = rk616_mipi_dsi_shutdown, +}; + +static int __init rk616_mipi_dsi_init(void) +{ + return platform_driver_register(&rk616_mipi_dsi_driver); +} +fs_initcall(rk616_mipi_dsi_init); + +static void __exit rk616_mipi_dsi_exit(void) +{ + platform_driver_unregister(&rk616_mipi_dsi_driver); +} +module_exit(rk616_mipi_dsi_exit); diff --git a/drivers/video/rockchip/transmitter/rk616_mipi_dsi.h b/drivers/video/rockchip/transmitter/rk616_mipi_dsi.h new file mode 100644 index 000000000000..8513a206a45a --- /dev/null +++ b/drivers/video/rockchip/transmitter/rk616_mipi_dsi.h @@ -0,0 +1,316 @@ +/* +drivers/video/display/transmitter/rk616_mipi_dsi.h +*/ +#ifndef RK616_MIPI_DSI_H +#define RK616_MIPI_DSI_H + +#define DWC_DSI_VERSION 0x3131302A + + +#define MIPI_DSI_PHY_OFFSET 0X0C00 +#define MIPI_DSI_HOST_OFFSET 0x1000 + +#define RK_ADDR(A) (MIPI_DSI_PHY_OFFSET + (A << 2)) + +//MIPI DSI HOST REGISTER +#define VERSION (MIPI_DSI_HOST_OFFSET + 0x00) // Version of the DSI host controller 0x3130312A +#define PWR_UP (MIPI_DSI_HOST_OFFSET + 0x04) //R/W Core power up 0x0 +#define CLKMGR_CFG (MIPI_DSI_HOST_OFFSET + 0x08) //R/W Number of active data lanes +#define DPI_CFG (MIPI_DSI_HOST_OFFSET + 0x0C) //R/W DPI interface configuration +//#define DBI_CFG (MIPI_DSI_HOST_OFFSET + 0x10) //R/W DBI interface configuration 0x0 +//#define DBI_CMDSIZE (MIPI_DSI_HOST_OFFSET + 0x14) //R/W DBI command size configuration 0x0 +#define PCKHDL_CFG (MIPI_DSI_HOST_OFFSET + 0x18) //R/W Packet handler configuration 0x0 +#define VID_MODE_CFG (MIPI_DSI_HOST_OFFSET + 0x1C) //R/W Video mode Configuration 0x0 +#define VID_PKT_CFG (MIPI_DSI_HOST_OFFSET + 0x20) //R/W Video packet configuration 0x0 +#define CMD_MODE_CFG (MIPI_DSI_HOST_OFFSET + 0x24) //R/W Command mode configuration 0x0 +#define TMR_LINE_CFG (MIPI_DSI_HOST_OFFSET + 0x28) //R/W Line timer configuration 0x0 +#define VTIMING_CFG (MIPI_DSI_HOST_OFFSET + 0x2C) //R/W Vertical timing configuration 0x0 +#define PHY_TMR_CFG (MIPI_DSI_HOST_OFFSET + 0x30) //R/W D-PHY timing configuration 0x0 +#define GEN_HDR (MIPI_DSI_HOST_OFFSET + 0x34) //R/W Generic packet header configuration 0x0 +#define GEN_PLD_DATA (MIPI_DSI_HOST_OFFSET + 0x38) //R/W Generic payload data in/out 0x0 +#define CMD_PKT_STATUS (MIPI_DSI_HOST_OFFSET + 0x3C) //R Command packet status 0x1515 +#define TO_CNT_CFG (MIPI_DSI_HOST_OFFSET + 0x40) //R/W Timeout timers configuration +#define ERROR_ST0 (MIPI_DSI_HOST_OFFSET + 0x44) //R Interrupt status register 0 +#define ERROR_ST1 (MIPI_DSI_HOST_OFFSET + 0x48) //R Interrupt status register 1 0x0 +#define ERROR_MSK0 (MIPI_DSI_HOST_OFFSET + 0x4C) //R/W Masks the interrupt generation triggered 0x0 +#define ERROR_MSK1 (MIPI_DSI_HOST_OFFSET + 0x50) //R/W Masks the interrupt generation triggered 0x0 +#define PHY_RSTZ (MIPI_DSI_HOST_OFFSET + 0x54) //R/W D-PHY reset control 0x0 +#define PHY_IF_CFG (MIPI_DSI_HOST_OFFSET + 0x58) //R/W D-PHY interface configuration 0x0 +#define PHY_IF_CTRL (MIPI_DSI_HOST_OFFSET + 0x5C) //R/W D-PHY PPI interface control 0x0 +#define PHY_STATUS (MIPI_DSI_HOST_OFFSET + 0x60) //R D-PHY PPI status interface 0x0 +#define PHY_TST_CTRL0 (MIPI_DSI_HOST_OFFSET + 0x64) //R/W D-PHY test interface control 0 0x1 +#define PHY_TST_CTRL1 (MIPI_DSI_HOST_OFFSET + 0x68) //R/W D-PHY test interface control 1 0x0 +//#define EDPI_CFG (MIPI_DSI_HOST_OFFSET + 0x6C) //R/W eDPI interface configuration 0x0 +#define LP_CMD_TIM (MIPI_DSI_HOST_OFFSET + 0x70) //R/W Low-Power command timing 0x0 configuration + + +//function bits definition register addr | bits | offest +#define REG_ADDR(a) (a << 16) +#define REG_BITS(a) (a << 8) +#define BITS_OFFSET(a) (a) + +#define shutdownz (PWR_UP << 16 | 1 << 8 | 0 ) +#define en18_loosely ((DPI_CFG << 16) | (1 << 8) | (10)) +#define colorm_active_low ((DPI_CFG << 16) | (1 << 8) | (9)) +#define shutd_active_low ((DPI_CFG << 16) | (1 << 8) | (8)) +#define hsync_active_low ((DPI_CFG << 16) | (1 << 8) | (7)) +#define vsync_active_low ((DPI_CFG << 16) | (1 << 8) | (6)) +#define dataen_active_low ((DPI_CFG << 16) | (1 << 8) | (5)) +#define dpi_color_coding ((DPI_CFG << 16) | (3 << 8) | (2)) +#define dpi_vid ((DPI_CFG << 16) | (1 << 8) | (0)) + +#define hline_time (TMR_LINE_CFG << 16 | 14 << 8 | 18 ) +#define hbp_time (TMR_LINE_CFG << 16 | 9 << 8 | 9 ) +#define hsa_time (TMR_LINE_CFG << 16 | 9 << 8 | 0 ) + +#define v_active_lines (VTIMING_CFG << 16 | 11 << 8 | 16 ) +#define vfp_lines (VTIMING_CFG << 16 | 6 << 8 | 10 ) +#define vbp_lines (VTIMING_CFG << 16 | 6 << 8 | 4 ) +#define vsa_lines (VTIMING_CFG << 16 | 4 << 8 | 0 ) + + +#define TO_CLK_DIVISION (REG_ADDR(CLKMGR_CFG) | REG_BITS(8) | BITS_OFFSET(8)) +#define TX_ESC_CLK_DIVISION (REG_ADDR(CLKMGR_CFG) | REG_BITS(8) | BITS_OFFSET(0)) + +#define gen_vid_rx (REG_ADDR(PCKHDL_CFG) | REG_BITS(2) | BITS_OFFSET(5)) +#define en_CRC_rx (REG_ADDR(PCKHDL_CFG) | REG_BITS(1) | BITS_OFFSET(4)) +#define en_ECC_rx (REG_ADDR(PCKHDL_CFG) | REG_BITS(1) | BITS_OFFSET(3)) +#define en_BTA (REG_ADDR(PCKHDL_CFG) | REG_BITS(1) | BITS_OFFSET(2)) +#define en_EOTp_rx (REG_ADDR(PCKHDL_CFG) | REG_BITS(1) | BITS_OFFSET(1)) +#define en_EOTp_tx (REG_ADDR(PCKHDL_CFG) | REG_BITS(1) | BITS_OFFSET(0)) + +#define lpcmden (REG_ADDR(VID_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(12)) +#define frame_BTA_ack (REG_ADDR(VID_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(11)) +#define en_null_pkt (REG_ADDR(VID_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(10)) +#define en_multi_pkt (REG_ADDR(VID_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(9)) +#define en_lp_hfp (REG_ADDR(VID_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(8)) +#define en_lp_hbp (REG_ADDR(VID_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(7)) +#define en_lp_vact (REG_ADDR(VID_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(6)) +#define en_lp_vfp (REG_ADDR(VID_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(5)) +#define en_lp_vbp (REG_ADDR(VID_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(4)) +#define en_lp_vsa (REG_ADDR(VID_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(3)) +#define vid_mode_type (REG_ADDR(VID_MODE_CFG) | REG_BITS(2) | BITS_OFFSET(1)) +#define en_video_mode (REG_ADDR(VID_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(0)) + +#define null_pkt_size (REG_ADDR(VID_PKT_CFG) | REG_BITS(10) | BITS_OFFSET(21)) +#define num_chunks (REG_ADDR(VID_PKT_CFG) | REG_BITS(10) | BITS_OFFSET(11)) +#define vid_pkt_size (REG_ADDR(VID_PKT_CFG) | REG_BITS(11) | BITS_OFFSET(0)) + +#define en_tear_fx (REG_ADDR(CMD_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(14)) +#define en_ack_rqst (REG_ADDR(CMD_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(13)) +#define dcs_lw_tx (REG_ADDR(CMD_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(12)) +#define gen_lw_tx (REG_ADDR(CMD_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(11)) +#define max_rd_pkt_size (REG_ADDR(CMD_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(10)) +#define dcs_sr_0p_tx (REG_ADDR(CMD_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(9)) +#define dcs_sw_1p_tx (REG_ADDR(CMD_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(8)) +#define dcs_sw_0p_tx (REG_ADDR(CMD_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(7)) +#define gen_sr_2p_tx (REG_ADDR(CMD_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(6)) +#define gen_sr_1p_tx (REG_ADDR(CMD_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(5)) +#define gen_sr_0p_tx (REG_ADDR(CMD_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(4)) +#define gen_sw_2p_tx (REG_ADDR(CMD_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(3)) +#define gen_sw_1p_tx (REG_ADDR(CMD_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(2)) +#define gen_sw_0p_tx (REG_ADDR(CMD_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(1)) +#define en_cmd_mode (REG_ADDR(CMD_MODE_CFG) | REG_BITS(1) | BITS_OFFSET(0)) + +#define phy_hs2lp_time (REG_ADDR(PHY_TMR_CFG) | REG_BITS(8) | BITS_OFFSET(24)) +#define phy_lp2hs_time (REG_ADDR(PHY_TMR_CFG) | REG_BITS(8) | BITS_OFFSET(16)) +#define max_rd_time (REG_ADDR(PHY_TMR_CFG) | REG_BITS(15) | BITS_OFFSET(0)) + +#define lprx_to_cnt (REG_ADDR(TO_CNT_CFG) | REG_BITS(16) | BITS_OFFSET(16)) +#define hstx_to_cnt (REG_ADDR(TO_CNT_CFG) | REG_BITS(16) | BITS_OFFSET(0)) + +#define phy_enableclk (REG_ADDR(PHY_RSTZ) | REG_BITS(1) | BITS_OFFSET(2)) +//#define phy_rstz (REG_ADDR(PHY_RSTZ) | REG_BITS(1) | BITS_OFFSET(1)) +//#define phy_shutdownz (REG_ADDR(PHY_RSTZ) | REG_BITS(1) | BITS_OFFSET(0)) + +#define phy_stop_wait_time (REG_ADDR(PHY_IF_CFG) | REG_BITS(8) | BITS_OFFSET(2)) +#define n_lanes (REG_ADDR(PHY_IF_CFG) | REG_BITS(2) | BITS_OFFSET(0)) + + +#define phy_tx_triggers (REG_ADDR(PHY_IF_CTRL) | REG_BITS(4) | BITS_OFFSET(5)) +#define phy_txexitulpslan (REG_ADDR(PHY_IF_CTRL) | REG_BITS(1) | BITS_OFFSET(4)) +#define phy_txrequlpslan (REG_ADDR(PHY_IF_CTRL) | REG_BITS(1) | BITS_OFFSET(3)) +#define phy_txexitulpsclk (REG_ADDR(PHY_IF_CTRL) | REG_BITS(1) | BITS_OFFSET(2)) +#define phy_txrequlpsclk (REG_ADDR(PHY_IF_CTRL) | REG_BITS(1) | BITS_OFFSET(1)) +#define phy_txrequestclkhs (REG_ADDR(PHY_IF_CTRL) | REG_BITS(1) | BITS_OFFSET(0)) + + +#define phy_testclk (REG_ADDR(PHY_TST_CTRL0) | REG_BITS(1) | BITS_OFFSET(1)) +#define phy_testclr (REG_ADDR(PHY_TST_CTRL0) | REG_BITS(1) | BITS_OFFSET(0)) + +#define phy_testen (REG_ADDR(PHY_TST_CTRL1) | REG_BITS(1) | BITS_OFFSET(16)) +#define phy_testdout (REG_ADDR(PHY_TST_CTRL1) | REG_BITS(8) | BITS_OFFSET(8)) +#define phy_testdin (REG_ADDR(PHY_TST_CTRL1) | REG_BITS(8) | BITS_OFFSET(0)) + +#define outvact_lpcmd_time (REG_ADDR(LP_CMD_TIM) | REG_BITS(8) | BITS_OFFSET(8)) +#define invact_lpcmd_time (REG_ADDR(LP_CMD_TIM) | REG_BITS(8) | BITS_OFFSET(0)) + +#define gen_rd_cmd_busy (REG_ADDR(CMD_PKT_STATUS) | REG_BITS(1) | BITS_OFFSET(6)) +#define gen_pld_r_full (REG_ADDR(CMD_PKT_STATUS) | REG_BITS(1) | BITS_OFFSET(5)) +#define gen_pld_r_empty (REG_ADDR(CMD_PKT_STATUS) | REG_BITS(1) | BITS_OFFSET(4)) +#define gen_pld_w_full (REG_ADDR(CMD_PKT_STATUS) | REG_BITS(1) | BITS_OFFSET(3)) //800byte write GEN_PLD_DATA +#define gen_pld_w_empty (REG_ADDR(CMD_PKT_STATUS) | REG_BITS(1) | BITS_OFFSET(2)) +#define gen_cmd_full (REG_ADDR(CMD_PKT_STATUS) | REG_BITS(1) | BITS_OFFSET(1)) //20 write GEN_HDR +#define gen_cmd_empty (REG_ADDR(CMD_PKT_STATUS) | REG_BITS(1) | BITS_OFFSET(0)) + +#define phystopstateclklane (REG_ADDR(PHY_STATUS) | REG_BITS(1) | BITS_OFFSET(2)) +#define phylock (REG_ADDR(PHY_STATUS) | REG_BITS(1) | BITS_OFFSET(0)) + + +//MIPI DSI DPHY REGISTERS +#define DPHY_REGISTER0 (MIPI_DSI_PHY_OFFSET + 0X0000) +#define DPHY_REGISTER1 (MIPI_DSI_PHY_OFFSET + 0X0004) +#define DPHY_REGISTER3 (MIPI_DSI_PHY_OFFSET + 0X000C) +#define DPHY_REGISTER4 (MIPI_DSI_PHY_OFFSET + 0X0010) +#define DPHY_REGISTER20 (MIPI_DSI_PHY_OFFSET + 0X0080) + +#define lane_en_ck (REG_ADDR(DPHY_REGISTER0) | REG_BITS(1) | BITS_OFFSET(6)) +#define lane_en_3 (REG_ADDR(DPHY_REGISTER0) | REG_BITS(1) | BITS_OFFSET(5)) +#define lane_en_2 (REG_ADDR(DPHY_REGISTER0) | REG_BITS(1) | BITS_OFFSET(4)) +#define lane_en_1 (REG_ADDR(DPHY_REGISTER0) | REG_BITS(1) | BITS_OFFSET(3)) +#define lane_en_0 (REG_ADDR(DPHY_REGISTER0) | REG_BITS(1) | BITS_OFFSET(2)) + + +#define reg_da_syncrst (REG_ADDR(DPHY_REGISTER1) | REG_BITS(1) | BITS_OFFSET(2)) +#define reg_da_ldopd (REG_ADDR(DPHY_REGISTER1) | REG_BITS(1) | BITS_OFFSET(1)) +#define reg_da_pllpd (REG_ADDR(DPHY_REGISTER1) | REG_BITS(1) | BITS_OFFSET(0)) + + +#define reg_fbdiv_8 (REG_ADDR(DPHY_REGISTER3) | REG_BITS(1) | BITS_OFFSET(5)) +#define reg_prediv (REG_ADDR(DPHY_REGISTER3) | REG_BITS(5) | BITS_OFFSET(0)) +#define reg_fbdiv (REG_ADDR(DPHY_REGISTER4) | REG_BITS(8) | BITS_OFFSET(0)) + +#define reg_dig_rstn (REG_ADDR(DPHY_REGISTER20) | REG_BITS(1) | BITS_OFFSET(0)) + + +#define DPHY_CLOCK_OFFSET (MIPI_DSI_PHY_OFFSET + 0X0100) +#define DPHY_LANE0_OFFSET (MIPI_DSI_PHY_OFFSET + 0X0180) +#define DPHY_LANE1_OFFSET (MIPI_DSI_PHY_OFFSET + 0X0200) +#define DPHY_LANE2_OFFSET (MIPI_DSI_PHY_OFFSET + 0X0280) +#define DPHY_LANE3_OFFSET (MIPI_DSI_PHY_OFFSET + 0X0300) + +#define reg_ths_settle 0x0000 +#define reg_hs_tlpx 0x0014 +#define reg_hs_ths_prepare 0x0018 +#define reg_hs_the_zero 0x001c +#define reg_hs_ths_trail 0x0020 +#define reg_hs_ths_exit 0x0024 +#define reg_hs_tclk_post 0x0028 +#define reserved 0x002c +#define reg_hs_twakup_h 0x0030 +#define reg_hs_twakup_l 0x0034 +#define reg_hs_tclk_pre 0x0038 +#define reg_hs_tta_go 0x0040 +#define reg_hs_tta_sure 0x0044 +#define reg_hs_tta_wait 0x0048 + + +//MISC REGISTERS +#define CRU_CRU_CLKSEL1_CON (0x005c) +#define CRU_CFG_MISC_CON (0x009c) + +#define cfg_mipiclk_gaten (REG_ADDR(CRU_CRU_CLKSEL1_CON) | REG_BITS(1) | BITS_OFFSET(10)) + +#define mipi_int (REG_ADDR(CRU_CFG_MISC_CON) | REG_BITS(1) | BITS_OFFSET(19)) +#define mipi_edpihalt (REG_ADDR(CRU_CFG_MISC_CON) | REG_BITS(1) | BITS_OFFSET(16)) +#define pin_forcetxstopmode_3 (REG_ADDR(CRU_CFG_MISC_CON) | REG_BITS(1) | BITS_OFFSET(11)) +#define pin_forcetxstopmode_2 (REG_ADDR(CRU_CFG_MISC_CON) | REG_BITS(1) | BITS_OFFSET(10)) +#define pin_forcetxstopmode_1 (REG_ADDR(CRU_CFG_MISC_CON) | REG_BITS(1) | BITS_OFFSET(9)) +#define pin_forcetxstopmode_0 (REG_ADDR(CRU_CFG_MISC_CON) | REG_BITS(1) | BITS_OFFSET(8)) +#define pin_forcerxmode_0 (REG_ADDR(CRU_CFG_MISC_CON) | REG_BITS(1) | BITS_OFFSET(7)) +#define pin_turndisable_0 (REG_ADDR(CRU_CFG_MISC_CON) | REG_BITS(1) | BITS_OFFSET(6)) +#define dpicolom (REG_ADDR(CRU_CFG_MISC_CON) | REG_BITS(1) | BITS_OFFSET(2)) +#define dpishutdn (REG_ADDR(CRU_CFG_MISC_CON) | REG_BITS(1) | BITS_OFFSET(1)) + + + +//global operation timing parameter +struct gotp_m { + //time uint is ns + u32 min; + u32 value; + u32 max; +}; + +//default time unit is ns +//Unit Interval, equal to the duration of any HS state on the Clock Lane +struct gotp { + u32 CLK_MISS; //min:no max:60 + u32 CLK_POST; //min:60 ns + 52*UI max:no + u32 CLK_PRE; //min:8*UI max:no + u32 CLK_PREPARE; //min:38 max:95 + u32 CLK_SETTLE; //min:95 max:300 + u32 CLK_TERM_EN; //min:Time for Dn to reach VTERM-EN max:38 + u32 CLK_TRAIL; //min:60 max:no + u32 CLK_ZERO; //min:300 - CLK_PREPARE max:no + u32 D_TERM_EN; //min:Time for Dn to reach VTERM-EN max:35 ns + 4*UI + u32 EOT; //min:no max:105 ns + n*12*UI + u32 HS_EXIT; //min:100 max:no + u32 HS_PREPARE; //min:40 ns + 4*UI max:85 ns + 6*UI + u32 HS_ZERO; //min:145 ns + 10*UI - HS_PREPARE max:no + u32 HS_SETTLE; //min:85 ns + 6*UI max:145 ns + 10*UI + u32 HS_SKIP; //min:40 max:55 ns + 4*UI + u32 HS_TRAIL; //min: max( n*8*UI, 60 ns + n*4*UI ) max:no + u32 NIT; //min:100us max:no + u32 LPX; //min:50 max:no + u32 TA_GET; //min:5*TLPX + u32 TA_GO; //min:4*TLPX + u32 TA_SURE; //min:TLPX max:2*TLPX + u32 WAKEUP; //min:1ms max:no +}; + + +struct dsi_phy { + u32 UI; + u32 ref_clk; //input_clk + u32 ddr_clk; //data bit clk + u32 txbyte_clk; //1/8 of ddr_clk + u32 sys_clk; // + u32 pclk; // + u32 txclkesc; + + u32 Tddr_clk; //ps + u32 Ttxbyte_clk; //ps + u32 Tsys_clk; //ps + u32 Tpclk; //ps + u32 Ttxclkesc; //ps + + u16 prediv; + u16 fbdiv; + u8 flag; + struct gotp gotp; + +}; + + +struct dsi_host { + u8 flag; + u8 lane; + u8 format; + u8 video_mode; + u32 clk; + +}; + +struct dsi { + + u8 lcdc_id; + u8 vid; + struct dsi_phy phy; + struct dsi_host host; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif + +}; + + + +//config +#define MIPI_DSI_REGISTER_IO 0 + +#ifndef MHz +#define MHz 1000000 +#endif + +#endif /* end of RK616_MIPI_DSI_H */ diff --git a/drivers/video/rockchip/transmitter/ssd2828.c b/drivers/video/rockchip/transmitter/ssd2828.c index 74bb6b3876d2..92e76c126ddf 100644 --- a/drivers/video/rockchip/transmitter/ssd2828.c +++ b/drivers/video/rockchip/transmitter/ssd2828.c @@ -445,7 +445,7 @@ int ssd_set_registers(unsigned int reg_array[], int n) { return 0; } -int ssd_mipi_dsi_send_dcs_packet(unsigned char regs[], int n) { +int ssd_mipi_dsi_send_dcs_packet(unsigned char regs[], u32 n) { //unsigned int data = 0, i = 0; ssd_set_register(0x00B70343); // ssd_set_register(0x00B80000); @@ -458,17 +458,17 @@ int ssd_mipi_dsi_send_dcs_packet(unsigned char regs[], int n) { } -int _ssd2828_send_packet(unsigned char type, unsigned char regs[], int n) { +int _ssd2828_send_packet(unsigned char type, unsigned char regs[], u32 n) { return 0; } -int ssd2828_send_packet(unsigned char type, unsigned char regs[], int n) { +int ssd2828_send_packet(unsigned char type, unsigned char regs[], u32 n) { return _ssd2828_send_packet(type, regs, n); } -int ssd_mipi_dsi_read_dcs_packet(unsigned char *data, int n) { +int ssd_mipi_dsi_read_dcs_packet(unsigned char *data, u32 n) { //DCS READ unsigned int i = 0; diff --git a/drivers/video/rockchip/transmitter/tc358768.c b/drivers/video/rockchip/transmitter/tc358768.c index 5f573b3dce8e..f001160aba2c 100644 --- a/drivers/video/rockchip/transmitter/tc358768.c +++ b/drivers/video/rockchip/transmitter/tc358768.c @@ -241,6 +241,7 @@ int tc358768_power_down(void) { tc->vddio.disable(&tc->vddio); tc->vdd_mipi.disable(&tc->vdd_mipi); tc->vddc.disable(&tc->vddc); + gpio_set_value(tc358768->reset.reset_pin, 0); return ret; } @@ -459,7 +460,7 @@ void tc_print(u32 addr) { } #define tc358768_wr_regs_32bits(reg_array) _tc358768_wr_regs_32bits(reg_array, ARRAY_SIZE(reg_array)) -int _tc358768_wr_regs_32bits(unsigned int reg_array[], int n) { +int _tc358768_wr_regs_32bits(unsigned int reg_array[], u32 n) { int i = 0; dsi_debug("%s:%d\n", __func__, n); @@ -477,7 +478,7 @@ int _tc358768_wr_regs_32bits(unsigned int reg_array[], int n) { return 0; } -int tc358768_command_tx_less8bytes(unsigned char type, unsigned char *regs, int n) { +int tc358768_command_tx_less8bytes(unsigned char type, unsigned char *regs, u32 n) { int i = 0; unsigned int command[] = { 0x06020000, @@ -520,7 +521,7 @@ int tc358768_command_tx_less8bytes(unsigned char type, unsigned char *regs, int return 0; } -int tc358768_command_tx_more8bytes_hs(unsigned char type, unsigned char regs[], int n) { +int tc358768_command_tx_more8bytes_hs(unsigned char type, unsigned char regs[], u32 n) { int i = 0; unsigned int dbg_data = 0x00E80000, temp = 0; @@ -560,7 +561,7 @@ int tc358768_command_tx_more8bytes_hs(unsigned char type, unsigned char regs[], } //low power mode only for tc358768a -int tc358768_command_tx_more8bytes_lp(unsigned char type, unsigned char regs[], int n) { +int tc358768_command_tx_more8bytes_lp(unsigned char type, unsigned char regs[], u32 n) { int i = 0; unsigned int dbg_data = 0x00E80000, temp = 0; @@ -595,7 +596,7 @@ int tc358768_command_tx_more8bytes_lp(unsigned char type, unsigned char regs[], return 0; } -int _tc358768_send_packet(unsigned char type, unsigned char regs[], int n) { +int _tc358768_send_packet(unsigned char type, unsigned char regs[], u32 n) { if(n <= 8) { tc358768_command_tx_less8bytes(type, regs, n); @@ -606,7 +607,7 @@ int _tc358768_send_packet(unsigned char type, unsigned char regs[], int n) { return 0; } -int tc358768_send_packet(unsigned char type, unsigned char regs[], int n) { +int tc358768_send_packet(unsigned char type, unsigned char regs[], u32 n) { return _tc358768_send_packet(type, regs, n); } @@ -616,7 +617,7 @@ The DCS is separated into two functional areas: the User Command Set and the Man Set. Each command is an eight-bit code with 00h to AFh assigned to the User Command Set and all other codes assigned to the Manufacturer Command Set. */ -int _mipi_dsi_send_dcs_packet(unsigned char regs[], int n) { +int _mipi_dsi_send_dcs_packet(unsigned char regs[], u32 n) { unsigned char type = 0; if(n == 1) { @@ -630,7 +631,7 @@ int _mipi_dsi_send_dcs_packet(unsigned char regs[], int n) { return 0; } -int mipi_dsi_send_dcs_packet(unsigned char regs[], int n) { +int mipi_dsi_send_dcs_packet(unsigned char regs[], u32 n) { return _mipi_dsi_send_dcs_packet(regs, n); } @@ -688,7 +689,7 @@ int _tc358768_rd_lcd_regs(unsigned char type, char comd, int size, unsigned char return 0; } -int mipi_dsi_read_dcs_packet(unsigned char *data, int n) { +int mipi_dsi_read_dcs_packet(unsigned char *data, u32 n) { //DCS READ _tc358768_rd_lcd_regs(0x06, *data, n, data); return 0; diff --git a/include/linux/rk_screen.h b/include/linux/rk_screen.h index 6f3f0469c322..7fbc5bccf653 100644 --- a/include/linux/rk_screen.h +++ b/include/linux/rk_screen.h @@ -177,6 +177,13 @@ typedef struct rk29fb_screen { u8 swap_rb; u8 swap_delta; u8 swap_dumy; + +#if defined(CONFIG_MIPI_DSI) + /* MIPI DSI */ + u8 dsi_lane; + u8 dsi_video_mode; + u32 hs_tx_clk; +#endif int xpos; //horizontal display start position on the sceen ,then can be changed by application int ypos; -- 2.34.1