From: libing Date: Wed, 16 Apr 2014 10:31:20 +0000 (+0800) Subject: rk32880mipi-dsi: separate of the rk3288 mipi dsi file. X-Git-Tag: firefly_0821_release~5524 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=10be602c6f95abcf19f3d5c88154bc86ad5e027c;p=firefly-linux-kernel-4.4.55.git rk32880mipi-dsi: separate of the rk3288 mipi dsi file. --- diff --git a/drivers/video/rockchip/transmitter/Kconfig b/drivers/video/rockchip/transmitter/Kconfig old mode 100644 new mode 100755 index 10f6d14422ea..7558517f9e6d --- a/drivers/video/rockchip/transmitter/Kconfig +++ b/drivers/video/rockchip/transmitter/Kconfig @@ -57,8 +57,8 @@ config SSD2828_RGB2MIPI help "a chip that change RGB interface parallel signal into DSI serial signal" -config RK616_MIPI_DSI - tristate "Rockchip mipi dsi support" +config RK32_MIPI_DSI + tristate "rk32 mipi dsi support" depends on MIPI_DSI help Rockchip mipi dsi support. diff --git a/drivers/video/rockchip/transmitter/Makefile b/drivers/video/rockchip/transmitter/Makefile old mode 100644 new mode 100755 index 381eb1c72cc8..0c5f6e57bd27 --- a/drivers/video/rockchip/transmitter/Makefile +++ b/drivers/video/rockchip/transmitter/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_DP501) += dp501.o obj-$(CONFIG_RK32_DP) += rk32_dp.o rk32_dp_reg.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 +obj-$(CONFIG_RK32_MIPI_DSI) += rk32_mipi_dsi.o +obj-$(CONFIG_TC358768_RGB2MIPI) += tc358768.o +obj-$(CONFIG_SSD2828_RGB2MIPI) += ssd2828.o diff --git a/drivers/video/rockchip/transmitter/rk32_mipi_dsi.c b/drivers/video/rockchip/transmitter/rk32_mipi_dsi.c new file mode 100755 index 000000000000..06538e6631fc --- /dev/null +++ b/drivers/video/rockchip/transmitter/rk32_mipi_dsi.c @@ -0,0 +1,1780 @@ +/* + * Copyright (C) 2013 ROCKCHIP, Inc. + * drivers/video/display/transmitter/rk32_mipi_dsi.c + * author: libing@rock-chips.com + * create date: 2014-04-16 + * debug sys/kernel/debug/rk616/mipi + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +//config +#define MIPI_DSI_REGISTER_IO 0 +#define CONFIG_MIPI_DSI_LINUX 0 + +#define CONFIG_ARCH_RK3288 1 + +#ifdef CONFIG_MIPI_DSI_LINUX +#if defined(CONFIG_MFD_RK616) +#define DWC_DSI_VERSION 0x3131302A +#define DWC_DSI_VERSION_0x3131302A 1 +#elif defined(CONFIG_ARCH_RK319X) +#define DWC_DSI_VERSION 0x3132312A +#define DWC_DSI_VERSION_0x3132312A 1 +#elif defined(CONFIG_ARCH_RK3288) +#define DWC_DSI_VERSION 0x3133302A +#define DWC_DSI_VERSION_0x3133302A 1 +#else +#define DWC_DSI_VERSION -1 +#endif /* CONFIG_MFD_RK616 */ +#else +#define DWC_DSI_VERSION 0x3131302A +#endif /* end of CONFIG_MIPI_DSI_LINUX*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +#include +#include "mipi_dsi.h" +#include "rk32_mipi_dsi.h" +#include + + + +#if 1 +#define MIPI_DBG(x...) printk(KERN_INFO x) +#else +#define MIPI_DBG(x...) +#endif + +#ifdef CONFIG_MIPI_DSI_LINUX +#define MIPI_TRACE(x...) printk(KERN_INFO x) +#else +#define MIPI_TRACE(...) \ + do\ + {\ + printf(__VA_ARGS__);\ + printf("\n");\ + }while(0); + +#endif + +/* +* Driver Version Note +* +*v1.0 : this driver is rk32 mipi dsi driver of rockchip; + +*/ +#define RK_MIPI_DSI_VERSION_AND_TIME "rockchip mipi_dsi v1.0 2014-04-16" + +static struct dsi *dsi0; +static struct dsi *dsi1; + +static int rk_mipi_dsi_is_active(void *arg); +static int rk_mipi_dsi_enable_hs_clk(void *arg, u32 enable); +static int rk_mipi_dsi_enable_video_mode(void *arg, u32 enable); +static int rk_mipi_dsi_enable_command_mode(void *arg, u32 enable); +static int rk_mipi_dsi_send_dcs_packet(void *arg, unsigned char regs[], u32 n); +static int rk_mipi_dsi_is_enable(void *arg, u32 enable); +int rk_mipi_screen_standby(u8 enable); + +static int dsi_read_reg(struct dsi *dsi, u16 reg, u32 *pval) +{ + *pval = __raw_readl(dsi->host.membase + (reg - MIPI_DSI_HOST_OFFSET)); + return 0; +} + + +static int dsi_write_reg(struct dsi *dsi, u16 reg, u32 *pval) +{ + __raw_writel(*pval, dsi->host.membase + (reg - MIPI_DSI_HOST_OFFSET)); + return 0; +} + +static int dsi_get_bits(struct dsi *dsi, u32 reg) +{ + u32 val = 0; + u32 bits = (reg >> 8) & 0xff; + u16 reg_addr = (reg >> 16) & 0xffff; + u8 offset = reg & 0xff; + if(bits < 32) + bits = (1 << bits) - 1; + else + bits = 0xffffffff; + dsi_read_reg(dsi, reg_addr, &val); + val >>= offset; + val &= bits; + return val; +} + +static int dsi_set_bits(struct dsi *dsi, u32 data, u32 reg) +{ + u32 val = 0; + u32 bits = (reg >> 8) & 0xff; + u16 reg_addr = (reg >> 16) & 0xffff; + u8 offset = reg & 0xff; + if(bits < 32) + bits = (1 << bits) - 1; + else + bits = 0xffffffff; + + if(bits != 0xffffffff) { + + dsi_read_reg(dsi, reg_addr, &val); + + } + + val &= ~(bits << offset); + val |= (data & bits) << offset; + //printk("%s:%04x->%08x\n", __func__, reg_addr, val); + dsi_write_reg(dsi, reg_addr, &val); + + + if(data > bits) { + MIPI_TRACE("%s error reg_addr:0x%04x, offset:%d, bits:0x%04x, value:0x%04x\n", + __func__, reg_addr, offset, bits, data); + } + return 0; +} + +static int dwc_phy_test_rd(struct dsi *dsi, unsigned char test_code) +{ + int val = 0; + dsi_set_bits(dsi, 1, phy_testclk); + dsi_set_bits(dsi, test_code, phy_testdin); + dsi_set_bits(dsi, 1, phy_testen); + dsi_set_bits(dsi, 0, phy_testclk); + dsi_set_bits(dsi, 0, phy_testen);; + + dsi_set_bits(dsi, 0, phy_testen); + val = dsi_get_bits(dsi,phy_testdout); + dsi_set_bits(dsi, 1, phy_testclk); + dsi_set_bits(dsi, 0, phy_testclk); + + return val; +} + + +static int dwc_phy_test_wr(struct dsi *dsi, unsigned char test_code, unsigned char *test_data, unsigned char size) +{ + int i = 0; + + dsi_set_bits(dsi, 0x10000 | test_code, PHY_TEST_CTRL1); + dsi_set_bits(dsi, 0x2, PHY_TEST_CTRL0); + dsi_set_bits(dsi, 0x0, PHY_TEST_CTRL0); + + for(i = 0; i < size; i++) { + dsi_set_bits(dsi, test_data[i], PHY_TEST_CTRL1); + dsi_set_bits(dsi, 0x2, PHY_TEST_CTRL0); + dsi_set_bits(dsi, 0x0, PHY_TEST_CTRL0); + MIPI_DBG("dwc_phy_test_wr:%08x\n", dsi_get_bits(dsi, PHY_TEST_CTRL1)); + } + return 0; +} + +static int rk32_phy_power_up(struct dsi *dsi) +{ + //enable ref clock + clk_prepare_enable(dsi->phy.refclk); + clk_prepare_enable(dsi->dsi_pclk); + udelay(10); + + switch(dsi->host.lane) { + case 4: + dsi_set_bits(dsi, 3, n_lanes); + case 3: + dsi_set_bits(dsi, 2, n_lanes); + case 2: + dsi_set_bits(dsi, 1, n_lanes); + case 1: + dsi_set_bits(dsi, 0, n_lanes); + break; + default: + break; + } + dsi_set_bits(dsi, 1, phy_shutdownz); + dsi_set_bits(dsi, 1, phy_rstz); + dsi_set_bits(dsi, 1, phy_enableclk); + dsi_set_bits(dsi, 1, phy_forcepll); + return 0; +} + +static int rk32_phy_power_down(struct dsi *dsi) +{ + dsi_set_bits(dsi, 0, phy_shutdownz); + clk_disable_unprepare(dsi->phy.refclk); + clk_disable_unprepare(dsi->dsi_pclk); + return 0; +} + +static int rk32_phy_init(struct dsi *dsi) +{ + u32 val = 0; + u32 ddr_clk = dsi->phy.ddr_clk; + u16 prediv = dsi->phy.prediv; + u16 fbdiv = dsi->phy.fbdiv; + // u32 Ttxclkesc = dsi->phy.Ttxclkesc; + unsigned char test_data[2] = {0}; + + if(ddr_clk < 90 * MHz) + val = 0x01; + else if(ddr_clk < 100 * MHz) + val = 0x10; + else if(ddr_clk < 110 * MHz) + val = 0x20; + else if(ddr_clk < 130 * MHz) + val = 0x01; + else if(ddr_clk < 140 * MHz) + val = 0x11; + else if(ddr_clk < 150 * MHz) + val = 0x21; + else if(ddr_clk < 170 * MHz) + val = 0x02; + else if(ddr_clk < 180 * MHz) + val = 0x12; + else if(ddr_clk < 200 * MHz) + val = 0x22; + else if(ddr_clk < 220 * MHz) + val = 0x03; + else if(ddr_clk < 240 * MHz) + val = 0x13; + else if(ddr_clk < 250 * MHz) + val = 0x23; + else if(ddr_clk < 270 * MHz) + val = 0x04; + else if(ddr_clk < 300 * MHz) + val = 0x14; + else if(ddr_clk < 330 * MHz) + val = 0x05; + else if(ddr_clk < 360 * MHz) + val = 0x15; + else if(ddr_clk < 400 * MHz) + val = 0x25; + else if(ddr_clk < 450 * MHz) + val = 0x06; + else if(ddr_clk < 500 * MHz) + val = 0x16; + else if(ddr_clk < 550 * MHz) + val = 0x07; + else if(ddr_clk < 600 * MHz) + val = 0x17; + else if(ddr_clk < 650 * MHz) + val = 0x08; + else if(ddr_clk < 700 * MHz) + val = 0x18; + else if(ddr_clk < 750 * MHz) + val = 0x09; + else if(ddr_clk < 800 * MHz) + val = 0x19; + else if(ddr_clk < 850 * MHz) + val = 0x29; + else if(ddr_clk < 900 * MHz) + val = 0x39; + else if(ddr_clk < 950 * MHz) + val = 0x0a; + else if(ddr_clk < 1000 * MHz) + val = 0x1a; + else if(ddr_clk < 1050 * MHz) + val = 0x2a; + else if(ddr_clk < 1100* MHz) + val = 0x3a; + else if(ddr_clk < 1150* MHz) + val = 0x0b; + else if(ddr_clk < 1200 * MHz) + val = 0x1b; + else if(ddr_clk < 1250 * MHz) + val = 0x2b; + else if(ddr_clk < 1300 * MHz) + val = 0x3b; + else if(ddr_clk < 1350 * MHz) + val = 0x0c; + else if(ddr_clk < 1400* MHz) + val = 0x1c; + else if(ddr_clk < 1450* MHz) + val = 0x2c; + else if(ddr_clk <= 1500* MHz) + val = 0x3c; + + //N=2,M=84 + test_data[0] = val << 1; + dwc_phy_test_wr(dsi, code_hs_rx_lane0, test_data, 1); + + test_data[0] = prediv- 1; + dwc_phy_test_wr(dsi, code_pll_input_div_rat, test_data, 1); + + test_data[0] = (fbdiv - 1) & 0x1f; //0x14; + dwc_phy_test_wr(dsi, code_pll_loop_div_rat, test_data, 1); + + test_data[0] = (fbdiv - 1) >> 5 | 0x80; //0x82 + dwc_phy_test_wr(dsi, code_pll_loop_div_rat, test_data, 1); + + test_data[0] = 0x30; + dwc_phy_test_wr(dsi, code_pll_input_loop_div_rat, test_data, 1); + mdelay(100); + + test_data[0] = 0x00; + // dwc_phy_test_wr(dsi, 0x60, test_data, 1); + + test_data[0] = 0x81; + // dwc_phy_test_wr(dsi, 0x61, test_data, 1); + + test_data[0] = 0x0; + // dwc_phy_test_wr(dsi, 0x62, test_data, 1); + + test_data[0] = 0x80 | 15; + dwc_phy_test_wr(dsi, code_hstxdatalanerequsetstatetime, test_data, 1); + + test_data[0] = 0x80 | 85; + dwc_phy_test_wr(dsi, code_hstxdatalanepreparestatetime, test_data, 1); + + test_data[0] = 0x40 | 10; + dwc_phy_test_wr(dsi, code_hstxdatalanehszerostatetime, test_data, 1); + + + // test_data[0] = 0x80 | 127; + // dwc_phy_test_wr(dsi, 0x71, test_data, 1); + + // test_data[0] = 0x3; + // dwc_phy_test_wr(dsi, 0x57, test_data, 1); + + return 0; +} + +static int rk_mipi_dsi_phy_power_up(struct dsi *dsi) +{ + return rk32_phy_power_up(dsi); + +} + + +static int rk_mipi_dsi_phy_power_down(struct dsi *dsi) +{ + return rk32_phy_power_down(dsi); +} + +static int rk_mipi_dsi_phy_init(struct dsi *dsi) +{ + return rk32_phy_init(dsi); + + return 0; +} + +static int rk_mipi_dsi_host_power_up(struct dsi *dsi) +{ + int ret = 0; + u32 val = 0; + + //disable all interrupt +#ifdef DWC_DSI_VERSION_0x3131302A + dsi_set_bits(dsi, 0x1fffff, ERROR_MSK0); + dsi_set_bits(dsi, 0x1ffff, ERROR_MSK1); +#else + dsi_set_bits(dsi, 0x1fffff, INT_MKS0); + dsi_set_bits(dsi, 0x1ffff, INT_MKS1); +#endif + + rk_mipi_dsi_is_enable(dsi, 1); + + val = 10; + while(!dsi_get_bits(dsi, phylock) && val--) { + udelay(10); + }; + + if(val == 0) { + ret = -1; + MIPI_TRACE("%s:phylock fail\n", __func__); + } + + val = 10; + while(!dsi_get_bits(dsi, phystopstateclklane) && val--) { + udelay(10); + }; + + return ret; +} + +static int rk_mipi_dsi_host_power_down(struct dsi *dsi) +{ + rk_mipi_dsi_enable_video_mode(dsi, 0); + rk_mipi_dsi_enable_hs_clk(dsi, 0); + rk_mipi_dsi_is_enable(dsi, 0); + return 0; +} + +static int rk_mipi_dsi_host_init(struct dsi *dsi) +{ + u32 val = 0, bytes_px = 0; + struct mipi_dsi_screen *screen = &dsi->screen; + u32 decimals = dsi->phy.Ttxbyte_clk, temp = 0, i = 0; + u32 m = 1, lane = dsi->host.lane, Tpclk = dsi->phy.Tpclk, + Ttxbyte_clk = dsi->phy.Ttxbyte_clk; + + dsi_set_bits(dsi, dsi->host.lane - 1, n_lanes); + dsi_set_bits(dsi, dsi->vid, dpi_vcid); + + switch(screen->face) { + case OUT_P888: + dsi_set_bits(dsi, 5, dpi_color_coding); + bytes_px = 3; + break; + case OUT_D888_P666: + case OUT_P666: + dsi_set_bits(dsi, 3, dpi_color_coding); + dsi_set_bits(dsi, 1, en18_loosely); + bytes_px = 3; + break; + case OUT_P565: + dsi_set_bits(dsi, 0, dpi_color_coding); + bytes_px = 2; + default: + break; + } + + dsi_set_bits(dsi, 1, hsync_active_low); + dsi_set_bits(dsi, 1, vsync_active_low); + + dsi_set_bits(dsi, 0, dataen_active_low); + dsi_set_bits(dsi, 0, colorm_active_low); + dsi_set_bits(dsi, 0, shutd_active_low); + + dsi_set_bits(dsi, dsi->host.video_mode, vid_mode_type); //burst mode + switch(dsi->host.video_mode) { + case VM_BM: + if(screen->type == SCREEN_DUAL_MIPI) + dsi_set_bits(dsi, screen->x_res / 2 + 4, vid_pkt_size); + else + dsi_set_bits(dsi, 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(dsi, screen->x_res / m + 1, num_chunks); + dsi_set_bits(dsi, 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(dsi, temp - 12, null_pkt_size); + } + break; + default: + break; + } + + //dsi_set_bits(dsi, 0, CMD_MODE_CFG << 16); + if(screen->type == SCREEN_MIPI){ + dsi_set_bits(dsi, dsi->phy.Tpclk * (screen->x_res + screen->left_margin + + screen->hsync_len + screen->right_margin) \ + / dsi->phy.Ttxbyte_clk, vid_hline_time); + } + else{ + dsi_set_bits(dsi, dsi->phy.Tpclk * (screen->x_res + 8 + screen->left_margin + + screen->hsync_len + screen->right_margin) \ + / dsi->phy.Ttxbyte_clk, vid_hline_time); + } + dsi_set_bits(dsi, dsi->phy.Tpclk * (screen->left_margin) / dsi->phy.Ttxbyte_clk, + vid_hbp_time); + dsi_set_bits(dsi, dsi->phy.Tpclk * (screen->hsync_len) / dsi->phy.Ttxbyte_clk, + vid_hsa_time); + + dsi_set_bits(dsi, screen->y_res , vid_active_lines); + dsi_set_bits(dsi, screen->lower_margin, vid_vfp_lines); + dsi_set_bits(dsi, screen->upper_margin, vid_vbp_lines); + dsi_set_bits(dsi, screen->vsync_len, vid_vsa_lines); + + dsi->phy.txclkesc = 20 * MHz; + val = dsi->phy.txbyte_clk / dsi->phy.txclkesc + 1; + dsi->phy.txclkesc = dsi->phy.txbyte_clk / val; + dsi_set_bits(dsi, val, TX_ESC_CLK_DIVISION); + + dsi_set_bits(dsi, 10, TO_CLK_DIVISION); + dsi_set_bits(dsi, 1000, hstx_to_cnt); //no sure + dsi_set_bits(dsi, 1000, lprx_to_cnt); + dsi_set_bits(dsi, 100, phy_stop_wait_time); + + //dsi_set_bits(dsi, 0, outvact_lpcmd_time); //byte + //dsi_set_bits(dsi, 0, invact_lpcmd_time); + + dsi_set_bits(dsi, 20, phy_hs2lp_time); + dsi_set_bits(dsi, 16, phy_lp2hs_time); + +#if defined(CONFIG_ARCH_RK3288) + // dsi_set_bits(dsi, 87, phy_hs2lp_time_clk_lane); //no sure + // dsi_set_bits(dsi, 25, phy_hs2hs_time_clk_lane); //no sure +#endif + + dsi_set_bits(dsi, 10000, max_rd_time); +#ifdef DWC_DSI_VERSION_0x3131302A + dsi_set_bits(dsi, 1, dpicolom); + dsi_set_bits(dsi, 1, dpishutdn); +#endif +#if 1 + dsi_set_bits(dsi, 1, lp_hfp_en); + //dsi_set_bits(dsi, 1, lp_hbp_en); //no sure + dsi_set_bits(dsi, 1, lp_vact_en); + dsi_set_bits(dsi, 1, lp_vfp_en); + dsi_set_bits(dsi, 1, lp_vbp_en); + dsi_set_bits(dsi, 1, lp_vsa_en); +#endif + //dsi_set_bits(dsi, 1, frame_bta_ack_en); + dsi_set_bits(dsi, 1, phy_enableclk); + dsi_set_bits(dsi, 0, phy_tx_triggers); + //dsi_set_bits(dsi, 1, phy_txexitulpslan); + //dsi_set_bits(dsi, 1, phy_txexitulpsclk); + return 0; +} + +/* + mipi protocol layer definition +*/ +static int rk_mipi_dsi_init(void *arg, u32 n) +{ + u32 decimals = 1000, i = 0, pre = 0; + struct dsi *dsi = arg; + struct mipi_dsi_screen *screen = &dsi->screen; + + if(!screen) + return -1; + + if((screen->type != SCREEN_MIPI) && (screen->type != SCREEN_DUAL_MIPI) ) { + MIPI_TRACE("only mipi dsi lcd is supported!\n"); + return -1; + } + + if(((screen->type == SCREEN_DUAL_MIPI) && (rk_mipi_get_dsi_num() == 1)) || ((screen->type == SCREEN_MIPI) && (rk_mipi_get_dsi_num() == 2))){ + MIPI_TRACE("dsi number and mipi type not match!\n"); + return -1; + } + +#ifdef CONFIG_MIPI_DSI_FT + dsi->phy.pclk = screen->pixclock; + dsi->phy.ref_clk = MIPI_DSI_MCLK; +#else + + dsi->phy.Tpclk = rk_fb_get_prmry_screen_pixclock(); + + printk("dsi->phy.Tpclk=%d\n",dsi->phy.Tpclk); + +#if defined(CONFIG_MFD_RK616) + if(dsi_rk616->mclk) + dsi->phy.ref_clk = clk_get_rate(dsi_rk616->mclk); +#elif defined(CONFIG_ARCH_RK319X) + if(dsi->phy.refclk) + dsi->phy.ref_clk = clk_get_rate(dsi->phy.refclk) / 2; // 1/2 of input refclk +#endif /* CONFIG_MFD_RK616 */ + //dsi->phy.ref_clk = 24 * MHz; +#endif /* CONFIG_MIPI_DSI_FT */ + + if(dsi->phy.refclk) + dsi->phy.ref_clk = clk_get_rate(dsi->phy.refclk) ; + + dsi->phy.sys_clk = dsi->phy.ref_clk; + + printk( + +"dsi->phy.sys_clk =%d\n",dsi->phy.sys_clk ); + +#ifndef CONFIG_ARCH_RK3288 + if((screen->hs_tx_clk <= 80 * MHz) || (screen->hs_tx_clk >= 1000 * MHz)) + dsi->phy.ddr_clk = 1000 * MHz; //default is 1HGz + else + dsi->phy.ddr_clk = screen->hs_tx_clk; +#else + if((screen->hs_tx_clk <= 90 * MHz) || (screen->hs_tx_clk >= 1500 * MHz)) + dsi->phy.ddr_clk = 1500 * MHz; //default is 1.5HGz + else + dsi->phy.ddr_clk = screen->hs_tx_clk; +#endif + + +/* if(n != 0) { + dsi->phy.ddr_clk = n; + } + */ + + decimals = dsi->phy.ref_clk; + for(i = 1; i < 6; i++) { + pre = dsi->phy.ref_clk / i; + if((decimals > (dsi->phy.ddr_clk % pre)) && (dsi->phy.ddr_clk / pre < 512)) { + decimals = dsi->phy.ddr_clk % pre; + dsi->phy.prediv = i; + dsi->phy.fbdiv = dsi->phy.ddr_clk / pre; + } + if(decimals == 0) + break; + } + + MIPI_DBG("prediv:%d, fbdiv:%d,dsi->phy.ddr_clk:%d\n", dsi->phy.prediv, dsi->phy.fbdiv,dsi->phy.ref_clk / dsi->phy.prediv * dsi->phy.fbdiv); + + dsi->phy.ddr_clk = dsi->phy.ref_clk / dsi->phy.prediv * dsi->phy.fbdiv; + MIPI_DBG("dsi->phy.ddr_clk =%d\n",dsi->phy.ddr_clk); + dsi->phy.txbyte_clk = dsi->phy.ddr_clk / 8; + + dsi->phy.txclkesc = 20 * MHz; // < 20MHz + dsi->phy.txclkesc = dsi->phy.txbyte_clk / (dsi->phy.txbyte_clk / dsi->phy.txclkesc + 1); + + dsi->phy.pclk = div_u64(1000000000000llu, dsi->phy.Tpclk); + dsi->phy.Ttxclkesc = div_u64(1000000000000llu, dsi->phy.txclkesc); + dsi->phy.Tsys_clk = div_u64(1000000000000llu, dsi->phy.sys_clk); + dsi->phy.Tddr_clk = div_u64(1000000000000llu, dsi->phy.ddr_clk); + dsi->phy.Ttxbyte_clk = div_u64(1000000000000llu, dsi->phy.txbyte_clk); + + dsi->phy.UI = dsi->phy.Tddr_clk; + dsi->vid = 0; + + if(screen->dsi_lane > 0 && screen->dsi_lane <= 4) + dsi->host.lane = screen->dsi_lane; + else + dsi->host.lane = 4; + + dsi->host.video_mode = VM_BM; + + MIPI_DBG("UI:%d\n", dsi->phy.UI); + MIPI_DBG("ref_clk:%d\n", dsi->phy.ref_clk); + MIPI_DBG("pclk:%d, Tpclk:%d\n", dsi->phy.pclk, dsi->phy.Tpclk); + MIPI_DBG("sys_clk:%d, Tsys_clk:%d\n", dsi->phy.sys_clk, dsi->phy.Tsys_clk); + MIPI_DBG("ddr_clk:%d, Tddr_clk:%d\n", dsi->phy.ddr_clk, dsi->phy.Tddr_clk); + MIPI_DBG("txbyte_clk:%d, Ttxbyte_clk:%d\n", dsi->phy.txbyte_clk, + dsi->phy.Ttxbyte_clk); + MIPI_DBG("txclkesc:%d, Ttxclkesc:%d\n", dsi->phy.txclkesc, dsi->phy.Ttxclkesc); + + rk_mipi_dsi_phy_power_up(dsi); + rk_mipi_dsi_host_power_up(dsi); + rk_mipi_dsi_phy_init(dsi); + rk_mipi_dsi_host_init(dsi); + + return 0; +} + + + +static int rk_mipi_dsi_is_enable(void *arg, u32 enable) +{ + struct dsi *dsi = arg; + + dsi_set_bits(dsi, enable, shutdownz); + + return 0; +} + +static int rk_mipi_dsi_enable_video_mode(void *arg, u32 enable) +{ + struct dsi *dsi = arg; +#ifdef DWC_DSI_VERSION_0x3131302A + dsi_set_bits(dsi, enable, en_video_mode); +#else + dsi_set_bits(dsi, !enable, cmd_video_mode); +#endif + + return 0; +} + +static int rk_mipi_dsi_enable_command_mode(void *arg, u32 enable) +{ + struct dsi *dsi = arg; +#ifdef DWC_DSI_VERSION_0x3131302A + dsi_set_bits(dsi, enable, en_cmd_mode); +#else + dsi_set_bits(dsi, enable, cmd_video_mode); +#endif + return 0; +} + +static int rk_mipi_dsi_enable_hs_clk(void *arg, u32 enable) +{ + struct dsi *dsi = arg; + dsi_set_bits(dsi, enable, phy_txrequestclkhs); + return 0; +} + +static int rk_mipi_dsi_is_active(void *arg) +{ + struct dsi *dsi = arg; + return dsi_get_bits(dsi, shutdownz); +} +static int mipi_dsi_send_packet(void *arg, unsigned char regs[], u32 n); + +static int rk_mipi_dsi_send_packet(struct dsi *dsi, u32 type, unsigned char regs[], u32 n) +{ + u32 data = 0, i = 0, j = 0; +#ifdef DWC_DSI_VERSION_0x3131302A + u32 flag = 0; +#endif + if((n == 0) && (type != DTYPE_GEN_SWRITE_0P)) + return -1; +#ifndef CONFIG_MFD_RK616 + if(dsi_get_bits(dsi, gen_cmd_full) == 1) { + MIPI_TRACE("gen_cmd_full\n"); + return -1; + } +#endif + +#ifdef DWC_DSI_VERSION_0x3131302A + if(dsi_get_bits(dsi, en_video_mode) == 1) { + //rk_mipi_dsi_enable_video_mode(dsi, 0); + flag = 1; + } +#endif + //rk_mipi_dsi_enable_command_mode(dsi, 1); + udelay(10); + + printk("rk_mipi_dsi_send_packet--type=0x%x----%d\n",type,n); + if(n <= 2) { + if(type == 0x29) + { + printk("type=0x%x\n", type); + data = 0; + for(i = 0; i < n; i++) { + j = i % 4; + data |= regs[i] << (j * 8); + if(j == 3 || ((i + 1) == n)) { + #ifndef CONFIG_MFD_RK616 + if(dsi_get_bits(dsi, gen_pld_w_full) == 1) { + MIPI_TRACE("gen_pld_w_full :%d\n", i); + break; + } + #endif + dsi_set_bits(dsi, data, GEN_PLD_DATA); + MIPI_DBG("write GEN_PLD_DATA:%d, %08x\n", i, data); + data = 0; + } + } + data = (dsi->vid << 6) | type; + data |= (n & 0xffff) << 8; + } + else + { + if(type == DTYPE_GEN_SWRITE_0P) + data = (dsi->vid << 6) | (n << 4) | type; + else + data = (dsi->vid << 6) | ((n-1) << 4) | type; + + 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)) { + #ifndef CONFIG_MFD_RK616 + if(dsi_get_bits(dsi, gen_pld_w_full) == 1) { + MIPI_TRACE("gen_pld_w_full :%d\n", i); + break; + } + #endif + dsi_set_bits(dsi, data, GEN_PLD_DATA); + MIPI_DBG("write GEN_PLD_DATA:%d, %08x\n", i, data); + data = 0; + } + } + data = (dsi->vid << 6) | type; + data |= (n & 0xffff) << 8; + } + + MIPI_DBG("write GEN_HDR:%08x\n", data); + dsi_set_bits(dsi, data, GEN_HDR); +#ifndef CONFIG_MFD_RK616 + i = 10; + while(!dsi_get_bits(dsi, gen_cmd_empty) && i--) { + MIPI_DBG("."); + udelay(10); + } + udelay(10); +#endif + +#ifdef DWC_DSI_VERSION_0x3131302A + //rk_mipi_dsi_enable_command_mode(dsi, 0); + if(flag == 1) { + // rk_mipi_dsi_enable_video_mode(dsi, 1); + } +#endif + return 0; +} + +static int rk_mipi_dsi_send_dcs_packet(void *arg, unsigned char regs[], u32 n) +{ + struct dsi *dsi = arg; + n -= 1; + printk("rk_mipi_dsi_send_dcs_packet n=%d\n",n); +#if 1 + mipi_dsi_send_packet(dsi, regs, n); + +#else + if((regs[1] ==0x2c) || (regs[1] ==0x3c)) + { + dsi_set_bits(dsi, regs[0], dcs_sw_0p_tx); + rk_mipi_dsi_send_packet(dsi, DTYPE_DCS_LWRITE, regs + 1, n); + }else + if(n <= 2) { + if(n == 1) + dsi_set_bits(dsi, regs[0], dcs_sw_0p_tx); + else + dsi_set_bits(dsi, regs[0], dcs_sw_1p_tx); + rk_mipi_dsi_send_packet(dsi, DTYPE_DCS_SWRITE_0P, regs + 1, n); + } else { + dsi_set_bits(dsi, regs[0], dcs_lw_tx); + rk_mipi_dsi_send_packet(dsi, DTYPE_DCS_LWRITE, regs + 1, n); + } + //MIPI_DBG("***%s:%d command sent in %s size:%d\n", __func__, __LINE__, regs[0] ? "LP mode" : "HS mode", n); +#endif + return 0; +} + +static int rk_mipi_dsi_send_gen_packet(void *arg, void *data, u32 n) +{ + struct dsi *dsi = arg; + unsigned char *regs = data; + n -= 1; + printk("-------------rk_mipi_dsi_send_gen_packet n=%d\n",n); + +#if 1 + mipi_dsi_send_packet(dsi, regs, n); +#else + +#endif + //MIPI_DBG("***%s:%d command sent in %s size:%d\n", __func__, __LINE__, regs[0] ? "LP mode" : "HS mode", n); + return 0; +} + +static int mipi_dsi_send_packet(void *arg, unsigned char regs[], u32 n) +{ + struct dsi *dsi = arg; + u32 type = regs[1]; + u32 data = 0, i = 0, j = 0; + n -= 1; + + if(dsi_get_bits(dsi, gen_cmd_full) == 1) { + MIPI_TRACE("gen_cmd_full\n"); + return -1; + } + + switch(type) + { + case DTYPE_DCS_SWRITE_0P: + dsi_set_bits(dsi, regs[0], dcs_sw_0p_tx); + data = regs[2] << 8 | type; + break; + + case DTYPE_DCS_SWRITE_1P: + dsi_set_bits(dsi, regs[0], dcs_sw_1p_tx); + data = regs[2] << 8 | type; + data |= regs[3] << 16; + break; + + case DTYPE_DCS_LWRITE: + dsi_set_bits(dsi, regs[0], dcs_lw_tx); + for(i = 0; i < n; i++) + { + regs[i] = regs[i+2]; + } + for(i = 0; i < n; i++) { + j = i % 4; + data |= regs[i] << (j * 8); + if(j == 3 || ((i + 1) == n)) { + #ifndef CONFIG_MFD_RK616 + if(dsi_get_bits(dsi, gen_pld_w_full) == 1) { + MIPI_TRACE("gen_pld_w_full :%d\n", i); + break; + } + #endif + dsi_set_bits(dsi, data, GEN_PLD_DATA); + MIPI_DBG("write GEN_PLD_DATA:%d, %08x\n", i, data); + data = 0; + } + } + + data = type; + data |= (n & 0xffff) << 8; + + break; + + case DTYPE_GEN_LWRITE: + dsi_set_bits(dsi, regs[0], gen_lw_tx); + + for(i = 0; i < n; i++) + { + regs[i] = regs[i+2]; + } + + for(i = 0; i < n; i++) { + j = i % 4; + data |= regs[i] << (j * 8); + if(j == 3 || ((i + 1) == n)) { + #ifndef CONFIG_MFD_RK616 + if(dsi_get_bits(dsi, gen_pld_w_full) == 1) { + MIPI_TRACE("gen_pld_w_full :%d\n", i); + break; + } + #endif + dsi_set_bits(dsi, data, GEN_PLD_DATA); + MIPI_DBG("write GEN_PLD_DATA:%d, %08x\n", i, data); + data = 0; + } + } + data = (dsi->vid << 6) | type; + data |= (n & 0xffff) << 8; + break; + + case DTYPE_GEN_SWRITE_2P: + + dsi_set_bits(dsi, regs[0], gen_sw_2p_tx); + for(i = 0; i < n; i++) + { + regs[i] = regs[i+2]; + } + + for(i = 0; i < n; i++) { + j = i % 4; + data |= regs[i] << (j * 8); + if(j == 3 || ((i + 1) == n)) { + #ifndef CONFIG_MFD_RK616 + if(dsi_get_bits(dsi, gen_pld_w_full) == 1) { + MIPI_TRACE("gen_pld_w_full :%d\n", i); + break; + } + #endif + dsi_set_bits(dsi, data, GEN_PLD_DATA); + MIPI_DBG("write GEN_PLD_DATA:%d, %08x\n", i, data); + data = 0; + } + } + data = type; + data |= (n & 0xffff) << 8; + + break; + + case DTYPE_GEN_SWRITE_1P: + dsi_set_bits(dsi, regs[0], gen_sw_1p_tx); + data = type; + data |= regs[2] << 8; + data |= regs[3] << 16; + break; + + case DTYPE_GEN_SWRITE_0P: + dsi_set_bits(dsi, regs[0], gen_sw_0p_tx); + data = type; + data |= regs[2] << 8; + + break; + + } + + //MIPI_DBG("***%s:%d command sent in %s size:%d\n", __func__, __LINE__, regs[0] ? "LP mode" : "HS mode", n); + + MIPI_DBG("write GEN_HDR:%08x\n", data); + dsi_set_bits(dsi, data, GEN_HDR); + + i = 10; + while(!dsi_get_bits(dsi, gen_cmd_empty) && i--) { + MIPI_DBG("."); + udelay(10); + } + udelay(10); + + return 0; +} + +static int rk_mipi_dsi_read_dcs_packet(void *arg, unsigned char *data1, u32 n) +{ + struct dsi *dsi = arg; + //DCS READ + //unsigned char *regs = data; + unsigned char regs[2]; + u32 data = 0; + int type = 0x06; + regs[0] = LPDT; + regs[1] = 0x0a; + n = n - 1; + + + dsi_set_bits(dsi, regs[0], dcs_sr_0p_tx); + + + /* if(type == DTYPE_GEN_SWRITE_0P) + data = (dsi->vid << 6) | (n << 4) | type; + else + data = (dsi->vid << 6) | ((n-1) << 4) | type;*/ + + data |= regs[1] << 8 | type; + // if(n == 2) + // data |= regs[1] << 16; + + MIPI_DBG("write GEN_HDR:%08x\n", data); + dsi_set_bits(dsi, data, GEN_HDR); + msleep(100); + + // dsi_set_bits(dsi, regs[0], gen_sr_0p_tx); + + printk("rk_mipi_dsi_read_dcs_packet==0x%x\n",dsi_get_bits(dsi, GEN_PLD_DATA)); + msleep(100); + + // dsi_set_bits(dsi, regs[0], max_rd_pkt_size); + + msleep(100); + // printk("_____rk_mipi_dsi_read_dcs_packet==0x%x\n",dsi_get_bits(dsi, GEN_PLD_DATA)); + + msleep(100); + return 0; +} + +static int rk_mipi_dsi_power_up(void *arg) +{ + struct dsi *dsi = arg; + rk_mipi_dsi_phy_power_up(dsi); + rk_mipi_dsi_host_power_up(dsi); + return 0; +} + +static int rk_mipi_dsi_power_down(void *arg) +{ + u8 dcs[4] = {0}; + struct dsi *dsi = arg; + struct mipi_dsi_screen *screen = &dsi->screen; + + if(!screen) + return -1; + + if(!screen->standby) { + rk_mipi_dsi_enable_video_mode(dsi, 0); + dcs[0] = HSDT; + dcs[1] = dcs_set_display_off; + rk_mipi_dsi_send_dcs_packet(dsi, dcs, 2); + msleep(1); + dcs[0] = HSDT; + dcs[1] = dcs_enter_sleep_mode; + rk_mipi_dsi_send_dcs_packet(dsi, dcs, 2); + msleep(1); + } else { + screen->standby(1); + } + + rk_mipi_dsi_host_power_down(dsi); + rk_mipi_dsi_phy_power_down(dsi); + + MIPI_TRACE("%s:%d\n", __func__, __LINE__); + return 0; +} + +static int rk_mipi_dsi_get_id(void *arg) +{ + u32 id = 0; + struct dsi *dsi = arg; + id = dsi_get_bits(dsi, VERSION); + return id; +} + +/* the most top level of mipi dsi init */ +static int rk_mipi_dsi_probe(struct dsi *dsi) +{ + int ret = 0; + + register_dsi_ops(dsi->dsi_id, &dsi->ops); + + ret = dsi_probe_current_chip(dsi->dsi_id); + if(ret) { + MIPI_TRACE("mipi dsi probe fail\n"); + return -ENODEV; + } + + return 0; +} + +#ifdef MIPI_DSI_REGISTER_IO +#include +#include +#include + +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; + memset(buf, 0, count); + 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 & 0xffff00000000ULL) == 0) + goto reg_proc_write_exit; + read_val = regs_val & 0xffffffff; + printk("regs_val=0x%llx\n",regs_val); + dsi_write_reg(dsi0, regs_val >> 32, &read_val); + dsi_read_reg(dsi0, regs_val >> 32, &read_val); + regs_val &= 0xffffffff; + if(read_val != regs_val) + MIPI_TRACE("%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%llx", ®s_val); + dsi_read_reg(dsi0, (u16)regs_val, &read_val); + MIPI_TRACE("*%04x : %08x\n", (u16)regs_val, read_val); + msleep(1); + break; + + case 's': + while(*(++data) == ' '); + sscanf(data, "%d", &read_val); + if(read_val == 11) + read_val = 11289600; + else + read_val *= MHz; +#ifdef CONFIG_MFD_RK616 + clk_set_rate(dsi_rk616->mclk, read_val); +#endif + //rk_mipi_dsi_init_lite(dsi); + break; + case 'd': + case 'g': + case 'c': + while(*(++data) == ' '); + i = 0; + MIPI_TRACE("****%d:%d\n", data-buf, count); + + do { + if(i > 31) { + MIPI_TRACE("payload entry is larger than 32\n"); + break; + } + sscanf(data, "%x,", str + i); //-c 1,29,02,03,05,06,> pro + data = strstr(data, ","); + if(data == NULL) + break; + data++; + i++; + } while(1); + read_val = i; + + i = 2; + while(i--) { + msleep(10); + if(command == 'd') + rk_mipi_dsi_send_dcs_packet(dsi0, str, read_val); + else + rk_mipi_dsi_send_gen_packet(dsi0, str, read_val); + } + i = 1; + while(i--) { + msleep(1000); + } + break; + + default: + break; + } + +reg_proc_write_exit: + kfree(buf); + msleep(20); + return count; +} + +int reg_proc_read(struct file *file, char __user *buff, size_t count, + loff_t *offp) +{ + int i = 0; + u32 val = 0; + + + for(i = VERSION; i < (VERSION + (0xdc<<16)); i += 4<<16) { + val = dsi_get_bits(dsi0, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + } + + MIPI_TRACE("\n"); + /*for(i = DPHY_REGISTER0; i <= DPHY_REGISTER4; i += 4<<16) { + val = dsi_get_bits(dsi0, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + } + MIPI_TRACE("\n"); + i = DPHY_REGISTER20; + val = dsi_get_bits(dsi0, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + + MIPI_TRACE("\n"); + for(i = (DPHY_CLOCK_OFFSET + DSI_DPHY_BITS(0x0000, 32, 0)); i <= ((DPHY_CLOCK_OFFSET + DSI_DPHY_BITS(0x0048, 32, 0))); i += 4<<16) { + val = dsi_get_bits(dsi0, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + } + + MIPI_TRACE("\n"); + for(i = (DPHY_LANE0_OFFSET + DSI_DPHY_BITS(0x0000, 32, 0)); i <= ((DPHY_LANE0_OFFSET + DSI_DPHY_BITS(0x0048, 32, 0))); i += 4<<16) { + val = dsi_get_bits(dsi0, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + } + + MIPI_TRACE("\n"); + for(i = (DPHY_LANE1_OFFSET + DSI_DPHY_BITS(0x0000, 32, 0)); i <= ((DPHY_LANE1_OFFSET + DSI_DPHY_BITS(0x0048, 32, 0))); i += 4<<16) { + val = dsi_get_bits(dsi0, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + } + + MIPI_TRACE("\n"); + for(i = (DPHY_LANE2_OFFSET + DSI_DPHY_BITS(0x0000, 32, 0)); i <= ((DPHY_LANE2_OFFSET + DSI_DPHY_BITS(0x0048, 32, 0))); i += 4<<16) { + val = dsi_get_bits(dsi0, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + } + + MIPI_TRACE("\n"); + for(i = (DPHY_LANE3_OFFSET + DSI_DPHY_BITS(0x0000, 32, 0)); i <= ((DPHY_LANE3_OFFSET + DSI_DPHY_BITS(0x0048, 32, 0))); i += 4<<16) { + val = dsi_get_bits(dsi0, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + }*/ + return -1; +} + +int reg_proc_open(struct inode *inode, struct file *file) +{ + return 0; +} + +int reg_proc_close(struct inode *inode, struct file *file) +{ + 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, +}; + + +int reg_proc_write1(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; + memset(buf, 0, count); + 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 & 0xffff00000000ULL) == 0) + goto reg_proc_write_exit; + read_val = regs_val & 0xffffffff; + dsi_write_reg(dsi1, regs_val >> 32, &read_val); + dsi_read_reg(dsi1, regs_val >> 32, &read_val); + regs_val &= 0xffffffff; + if(read_val != regs_val) + MIPI_TRACE("%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%llx", ®s_val); + dsi_read_reg(dsi1, (u16)regs_val, &read_val); + MIPI_TRACE("*%04x : %08x\n", (u16)regs_val, read_val); + msleep(1); + break; + + case 's': + while(*(++data) == ' '); + sscanf(data, "%d", &read_val); + if(read_val == 11) + read_val = 11289600; + else + read_val *= MHz; +#ifdef CONFIG_MFD_RK616 + clk_set_rate(dsi_rk616->mclk, read_val); +#endif + //rk_mipi_dsi_init_lite(dsi); + break; + case 'd': + case 'g': + case 'c': + while(*(++data) == ' '); + i = 0; + MIPI_TRACE("****%d:%d\n", data-buf, count); + + do { + if(i > 31) { + MIPI_TRACE("payload entry is larger than 32\n"); + break; + } + sscanf(data, "%x,", str + i); //-c 1,29,02,03,05,06,> pro + data = strstr(data, ","); + if(data == NULL) + break; + data++; + i++; + } while(1); + read_val = i; + + i = 2; + while(i--) { + msleep(10); + if(command == 'd') + rk_mipi_dsi_send_dcs_packet(dsi1, str, read_val); + else + rk_mipi_dsi_send_gen_packet(dsi1, str, read_val); + } + i = 1; + while(i--) { + msleep(1000); + } + break; + + default: + break; + } + +reg_proc_write_exit: + kfree(buf); + msleep(20); + return count; +} + +int reg_proc_read1(struct file *file, char __user *buff, size_t count, + loff_t *offp) +{ + int i = 0; + u32 val = 0; + + for(i = VERSION; i < (VERSION + (0xdc<<16)); i += 4<<16) { + val = dsi_get_bits(dsi1, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + } + + MIPI_TRACE("\n"); +/* for(i = DPHY_REGISTER0; i <= DPHY_REGISTER4; i += 4<<16) { + val = dsi_get_bits(dsi1, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + } + MIPI_TRACE("\n"); + i = DPHY_REGISTER20; + val = dsi_get_bits(dsi1, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + + MIPI_TRACE("\n"); + for(i = (DPHY_CLOCK_OFFSET + DSI_DPHY_BITS(0x0000, 32, 0)); i <= ((DPHY_CLOCK_OFFSET + DSI_DPHY_BITS(0x0048, 32, 0))); i += 4<<16) { + val = dsi_get_bits(dsi1, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + } + + MIPI_TRACE("\n"); + for(i = (DPHY_LANE0_OFFSET + DSI_DPHY_BITS(0x0000, 32, 0)); i <= ((DPHY_LANE0_OFFSET + DSI_DPHY_BITS(0x0048, 32, 0))); i += 4<<16) { + val = dsi_get_bits(dsi1, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + } + + MIPI_TRACE("\n"); + for(i = (DPHY_LANE1_OFFSET + DSI_DPHY_BITS(0x0000, 32, 0)); i <= ((DPHY_LANE1_OFFSET + DSI_DPHY_BITS(0x0048, 32, 0))); i += 4<<16) { + val = dsi_get_bits(dsi1, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + } + + MIPI_TRACE("\n"); + for(i = (DPHY_LANE2_OFFSET + DSI_DPHY_BITS(0x0000, 32, 0)); i <= ((DPHY_LANE2_OFFSET + DSI_DPHY_BITS(0x0048, 32, 0))); i += 4<<16) { + val = dsi_get_bits(dsi1, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + } + + MIPI_TRACE("\n"); + for(i = (DPHY_LANE3_OFFSET + DSI_DPHY_BITS(0x0000, 32, 0)); i <= ((DPHY_LANE3_OFFSET + DSI_DPHY_BITS(0x0048, 32, 0))); i += 4<<16) { + val = dsi_get_bits(dsi1, i); + MIPI_TRACE("%04x: %08x\n", i>>16, val); + msleep(1); + }*/ + return -1; +} + +int reg_proc_open1(struct inode *inode, struct file *file) +{ + return 0; +} + +int reg_proc_close1(struct inode *inode, struct file *file) +{ + return 0; +} + +struct file_operations reg_proc_fops1 = { + .owner = THIS_MODULE, + .open = reg_proc_open1, + .release= reg_proc_close1, + .write = reg_proc_write1, + .read = reg_proc_read1, +}; + +#endif + + + +static irqreturn_t rk32_mipi_dsi_irq_handler(int irq, void *data) +{ + return IRQ_HANDLED; + //return IRQ_NONE; +} + + +static int rk32_dsi_enable(void) +{ + MIPI_DBG("rk32_dsi_enable-------\n"); + + dsi_init(0, 0); + if (rk_mipi_get_dsi_num() ==2) + dsi_init(1, 0); + + rk_mipi_screen_standby(0); + + /* + After the core reset, DPI waits for the first VSYNC active transition to start signal sampling, including + pixel data, and preventing image transmission in the middle of a frame. + */ + dsi_is_enable(0, 0); + if (rk_mipi_get_dsi_num() ==2) + dsi_is_enable(1, 0); + + dsi_enable_video_mode(0, 1); + dsi_enable_video_mode(1, 1); + + + dsi_is_enable(0, 1); + if (rk_mipi_get_dsi_num() ==2) + dsi_is_enable(1, 1); + + return 0; +} + +static int rk32_dsi_disable(void) +{ + MIPI_DBG("rk32_dsi_disable-------\n"); + + rk_mipi_screen_standby(1); + dsi_power_off(0); + if (rk_mipi_get_dsi_num() ==2) + dsi_power_off(1); + + return 0; +} + + +static struct rk_fb_trsm_ops trsm_dsi_ops = +{ + .enable = rk32_dsi_enable, + .disable = rk32_dsi_disable, +}; + +static void rk32_init_phy_mode(int lcdc_id) +{ + int val0 = 0, val1 = 0; + + MIPI_DBG("rk32_init_phy_mode----------lcdc_id=%d\n",lcdc_id); + //D-PHY mode select + if( rk_mipi_get_dsi_num() ==1 ){ + + if(lcdc_id == 1) + //val0 =0x1 << 25 | 0x1 << 9; + val0 = 0x1 << 22 | 0x1 << 6; //1'b1: VOP LIT output to DSI host0;1'b0: VOP BIG output to DSI host0 + else + val0 = 0x1 << 22 | 0x0 << 6; + + writel_relaxed(val0, RK_GRF_VIRT + RK3288_GRF_SOC_CON6); + } + else{ + if(lcdc_id == 1){ + val0 = 0x1 << 25 | 0x1 << 9 | 0x1 << 22 | 0x1 << 6; + val1 = 0x1 << 31 | 0x1 << 30 | 0x0 << 15 | 0x1 << 14; + } + else{ + val0 = 0x1 << 25 | 0x0 << 9 | 0x1 << 22 | 0x0 << 14; + val1 = 0x1 << 31 | 0x1 << 30 | 0x0 << 15 | 0x1 << 14; + } + + writel_relaxed(val0, RK_GRF_VIRT + RK3288_GRF_SOC_CON6); + writel_relaxed(val1, RK_GRF_VIRT + RK3288_GRF_SOC_CON14); + } + +} + +static int rk32_mipi_dsi_probe(struct platform_device *pdev) +{ + int ret = 0; + struct dsi *dsi; + struct mipi_dsi_ops *ops; + struct rk_screen *screen; + struct mipi_dsi_screen *dsi_screen; + static int id = 0; + + struct resource *res_host; + + dsi = devm_kzalloc(&pdev->dev, sizeof(struct dsi), GFP_KERNEL); + if(!dsi) { + dev_err(&pdev->dev,"request struct dsi fail!\n"); + return -ENOMEM; + } + + res_host = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dsi->host.membase = devm_request_and_ioremap(&pdev->dev, res_host); + if (!dsi->host.membase) + return -ENOMEM; + + dsi->phy.refclk = devm_clk_get(&pdev->dev, "clk_mipi_24m"); + if (unlikely(IS_ERR(dsi->phy.refclk))) { + dev_err(&pdev->dev, "get mipi_ref clock fail\n"); + ret = PTR_ERR(dsi->phy.refclk); + //goto probe_err6; + } + + dsi->dsi_pclk = devm_clk_get(&pdev->dev, "pclk_mipi_dsi"); + if (unlikely(IS_ERR(dsi->dsi_pclk))) { + dev_err(&pdev->dev, "get pclk_mipi_dsi clock fail\n"); + ret = PTR_ERR(dsi->dsi_pclk); + //goto probe_err7; + } + + dsi->host.irq = platform_get_irq(pdev, 0); + if (dsi->host.irq < 0) { + dev_err(&pdev->dev, "no irq resource?\n"); + return dsi->host.irq; + } + + ret = request_irq(dsi->host.irq, rk32_mipi_dsi_irq_handler, 0,dev_name(&pdev->dev), dsi); + if(ret) { + dev_err(&pdev->dev, "request mipi_dsi irq fail\n"); + ret = -EINVAL; + goto probe_err1; + } + printk("dsi->host.irq =%d\n",dsi->host.irq); + + disable_irq(dsi->host.irq); + + screen = devm_kzalloc(&pdev->dev, sizeof(struct rk_screen), GFP_KERNEL); + if(!screen) { + dev_err(&pdev->dev,"request struct rk_screen fail!\n"); + goto probe_err9; + } + rk_fb_get_prmry_screen(screen); + + dsi->pdev = pdev; + ops = &dsi->ops; + ops->dsi = dsi; + ops->id = DWC_DSI_VERSION, + ops->get_id = rk_mipi_dsi_get_id, + ops->dsi_send_packet = rk_mipi_dsi_send_gen_packet, + ops->dsi_send_dcs_packet = rk_mipi_dsi_send_dcs_packet, + ops->dsi_read_dcs_packet = rk_mipi_dsi_read_dcs_packet, + ops->dsi_enable_video_mode = rk_mipi_dsi_enable_video_mode, + ops->dsi_enable_command_mode = rk_mipi_dsi_enable_command_mode, + ops->dsi_enable_hs_clk = rk_mipi_dsi_enable_hs_clk, + ops->dsi_is_active = rk_mipi_dsi_is_active, + ops->dsi_is_enable= rk_mipi_dsi_is_enable, + ops->power_up = rk_mipi_dsi_power_up, + ops->power_down = rk_mipi_dsi_power_down, + ops->dsi_init = rk_mipi_dsi_init, + + dsi_screen = &dsi->screen; + dsi_screen->type = screen->type; + dsi_screen->face = screen->face; + dsi_screen->lcdc_id = screen->lcdc_id; + dsi_screen->screen_id = screen->screen_id; + dsi_screen->pixclock = screen->mode.pixclock; + dsi_screen->left_margin = screen->mode.left_margin; + dsi_screen->right_margin = screen->mode.right_margin; + dsi_screen->hsync_len = screen->mode.hsync_len; + dsi_screen->upper_margin = screen->mode.upper_margin; + dsi_screen->lower_margin = screen->mode.lower_margin; + dsi_screen->vsync_len = screen->mode.vsync_len; + dsi_screen->x_res = screen->mode.xres; + dsi_screen->y_res = screen->mode.yres; + dsi_screen->pin_hsync = screen->pin_hsync; + dsi_screen->pin_vsync = screen->pin_vsync; + dsi_screen->pin_den = screen->pin_den; + dsi_screen->pin_dclk = screen->pin_dclk; + dsi_screen->dsi_lane = rk_mipi_get_dsi_lane(); +// dsi_screen->dsi_video_mode = screen->dsi_video_mode; //no sure + dsi_screen->dsi_lane = rk_mipi_get_dsi_lane(); + dsi_screen->hs_tx_clk = rk_mipi_get_dsi_clk(); + dsi_screen->lcdc_id = 1; + + dsi->dsi_id = id++;//of_alias_get_id(pdev->dev.of_node, "dsi"); + + sprintf(ops->name, "rk_mipi_dsi.%d", dsi->dsi_id); + platform_set_drvdata(pdev, dsi); + + + + ret = rk_mipi_dsi_probe(dsi); + if(ret) { + dev_err(&pdev->dev,"rk mipi_dsi probe fail!\n"); + dev_err(&pdev->dev,"%s\n", RK_MIPI_DSI_VERSION_AND_TIME); + goto probe_err11; + } + + + if(id == 1){ + rk32_init_phy_mode(dsi_screen->lcdc_id); + rk_fb_trsm_ops_register(&trsm_dsi_ops, SCREEN_MIPI); + +#ifdef MIPI_DSI_REGISTER_IO + debugfs_create_file("mipidsi0", S_IFREG | S_IRUGO, dsi->debugfs_dir, dsi, + ®_proc_fops); +#endif + dsi0 = dsi; + + }else{ + dsi1 = dsi; + +#ifdef MIPI_DSI_REGISTER_IO + debugfs_create_file("mipidsi1", S_IFREG | S_IRUGO, dsi->debugfs_dir, dsi, + ®_proc_fops1); +#endif + + } + + dev_info(&pdev->dev,"rk mipi_dsi probe success!\n"); + dev_info(&pdev->dev,"%s\n", RK_MIPI_DSI_VERSION_AND_TIME); + return 0; + +probe_err11: + + +probe_err9: +#if defined(CONFIG_ARCH_RK319X) + clk_put(dsi->dsi_pd); +probe_err8: + clk_put(dsi->dsi_pclk); +probe_err7: + clk_put(dsi->phy.refclk); +probe_err6: + free_irq(dsi->host.irq, dsi); +probe_err5: + iounmap(dsi->phy.membase); +probe_err4: + release_mem_region(res_phy->start, resource_size(res_phy)); +probe_err3: + iounmap(dsi->host.membase); +probe_err2: + release_mem_region(res_host->start, resource_size(res_host)); +#endif + +probe_err1: + + return ret; + +} + + +#ifdef CONFIG_OF +static const struct of_device_id of_rk_mipi_dsi_match[] = { + { .compatible = "rockchip,rk32-dsi" }, + { /* Sentinel */ } +}; +#endif + +static struct platform_driver rk616_mipi_dsi_driver = { + .driver = { + .name = "rk616-mipi", +#ifdef CONFIG_OF + .of_match_table = of_rk_mipi_dsi_match, +#endif + .owner = THIS_MODULE, + }, + .probe = rk32_mipi_dsi_probe, + +}; + +static int __init rk32_mipi_dsi_init(void) +{ + return platform_driver_register(&rk616_mipi_dsi_driver); +} +fs_initcall(rk32_mipi_dsi_init); + +static void __exit rk32_mipi_dsi_exit(void) +{ + platform_driver_unregister(&rk616_mipi_dsi_driver); +} +module_exit(rk32_mipi_dsi_exit); diff --git a/drivers/video/rockchip/transmitter/rk32_mipi_dsi.h b/drivers/video/rockchip/transmitter/rk32_mipi_dsi.h new file mode 100755 index 000000000000..987e86ae3e96 --- /dev/null +++ b/drivers/video/rockchip/transmitter/rk32_mipi_dsi.h @@ -0,0 +1,452 @@ +/* +drivers/video/rockchip/transmitter/rk616_mipi_dsi.h +*/ +#include +#ifndef RK616_MIPI_DSI_H +#define RK616_MIPI_DSI_H + +#define MIPI_DSI_PHY_OFFSET 0x0C00 +#define MIPI_DSI_PHY_SIZE 0x34c +#define MIPI_DSI_HOST_OFFSET 0x1000 + +#ifdef DWC_DSI_VERSION_0x3131302A +#define MIPI_DSI_HOST_SIZE 0x74 +#else +#define MIPI_DSI_HOST_SIZE 0xcc +#endif + +//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 DSI_HOST_BITS(addr, bits, bit_offset) (REG_ADDR((addr)+MIPI_DSI_HOST_OFFSET) \ + | REG_BITS(bits) | BITS_OFFSET(bit_offset)) +#define DSI_DPHY_BITS(addr, bits, bit_offset) (REG_ADDR((addr)+MIPI_DSI_PHY_OFFSET) \ + | REG_BITS(bits) | BITS_OFFSET(bit_offset)) + +#ifdef DWC_DSI_VERSION_0x3131302A + +#define VERSION DSI_HOST_BITS(0x00, 32, 0) +#define GEN_HDR DSI_HOST_BITS(0x34, 32, 0) +#define GEN_PLD_DATA DSI_HOST_BITS(0x38, 32, 0) +#define ERROR_ST0 DSI_HOST_BITS(0x44, 21, 0) +#define ERROR_ST1 DSI_HOST_BITS(0x48, 18, 0) +#define ERROR_MSK0 DSI_HOST_BITS(0x4C, 21, 0) +#define ERROR_MSK1 DSI_HOST_BITS(0x50, 18, 0) + +#define shutdownz DSI_HOST_BITS(0x04, 1, 0) +#define en18_loosely DSI_HOST_BITS(0x0c, 1, 10) +#define colorm_active_low DSI_HOST_BITS(0x0c, 1, 9) +#define shutd_active_low DSI_HOST_BITS(0x0c, 1, 8) +#define hsync_active_low DSI_HOST_BITS(0x0c, 1, 7) +#define vsync_active_low DSI_HOST_BITS(0x0c, 1, 6) +#define dataen_active_low DSI_HOST_BITS(0x0c, 1, 5) +#define dpi_color_coding DSI_HOST_BITS(0x0c, 3, 2) +#define dpi_vcid DSI_HOST_BITS(0x0c, 1, 0) +#define vid_hline_time DSI_HOST_BITS(0x28, 14, 18) +#define vid_hbp_time DSI_HOST_BITS(0x28, 9, 9) +#define vid_hsa_time DSI_HOST_BITS(0x28, 9, 0) +#define vid_active_lines DSI_HOST_BITS(0x2c, 11, 16) +#define vid_vfp_lines DSI_HOST_BITS(0x2c, 6, 10) +#define vid_vbp_lines DSI_HOST_BITS(0x2c, 6, 4) +#define vid_vsa_lines DSI_HOST_BITS(0x2c, 4, 0) +#define TO_CLK_DIVISION DSI_HOST_BITS(0x08, 8, 8) +#define TX_ESC_CLK_DIVISION DSI_HOST_BITS(0x08, 8, 0) +#define gen_vid_rx DSI_HOST_BITS(0x18, 2, 5) +#define crc_rx_en DSI_HOST_BITS(0x18, 1, 4) +#define ecc_rx_en DSI_HOST_BITS(0x18, 1, 3) +#define bta_en DSI_HOST_BITS(0x18, 1, 2) +#define eotp_rx_en DSI_HOST_BITS(0x18, 1, 1) +#define eotp_tx_en DSI_HOST_BITS(0x18, 1, 0) +#define lp_cmd_en DSI_HOST_BITS(0x1c, 1, 12) +#define frame_bta_ack_en DSI_HOST_BITS(0x1c, 1, 11) +#define en_null_pkt DSI_HOST_BITS(0x1c, 1, 10) +#define en_multi_pkt DSI_HOST_BITS(0x1c, 1, 9) +#define lp_hfp_en DSI_HOST_BITS(0x1c, 1, 8) +#define lp_hbp_en DSI_HOST_BITS(0x1c, 1, 7) +#define lp_vact_en DSI_HOST_BITS(0x1c, 1, 6) +#define lp_vfp_en DSI_HOST_BITS(0x1c, 1, 5) +#define lp_vbp_en DSI_HOST_BITS(0x1c, 1, 4) +#define lp_vsa_en DSI_HOST_BITS(0x1c, 1, 3) +#define vid_mode_type DSI_HOST_BITS(0x1c, 2, 1) +#define en_video_mode DSI_HOST_BITS(0x1c, 1, 0) +#define null_pkt_size DSI_HOST_BITS(0x20, 10, 21) +#define num_chunks DSI_HOST_BITS(0x20, 10, 11) +#define vid_pkt_size DSI_HOST_BITS(0x20, 11, 0) +#define tear_fx_en DSI_HOST_BITS(0x24, 1, 14) +#define ack_rqst_en DSI_HOST_BITS(0x24, 1, 13) +#define dcs_lw_tx DSI_HOST_BITS(0x24, 1, 12) +#define gen_lw_tx DSI_HOST_BITS(0x24, 1, 11) +#define max_rd_pkt_size DSI_HOST_BITS(0x24, 1, 10) +#define dcs_sr_0p_tx DSI_HOST_BITS(0x24, 1, 9) +#define dcs_sw_1p_tx DSI_HOST_BITS(0x24, 1, 8) +#define dcs_sw_0p_tx DSI_HOST_BITS(0x24, 1, 7) +#define gen_sr_2p_tx DSI_HOST_BITS(0x24, 1, 6) +#define gen_sr_1p_tx DSI_HOST_BITS(0x24, 1, 5) +#define gen_sr_0p_tx DSI_HOST_BITS(0x24, 1, 4) +#define gen_sw_2p_tx DSI_HOST_BITS(0x24, 1, 3) +#define gen_sw_1p_tx DSI_HOST_BITS(0x24, 1, 2) +#define gen_sw_0p_tx DSI_HOST_BITS(0x24, 1, 1) +#define en_cmd_mode DSI_HOST_BITS(0x24, 1, 0) +#define phy_hs2lp_time DSI_HOST_BITS(0x30, 8, 24) +#define phy_lp2hs_time DSI_HOST_BITS(0x30, 8, 16) +#define max_rd_time DSI_HOST_BITS(0x30, 15, 0) +#define lprx_to_cnt DSI_HOST_BITS(0x40, 16, 16) +#define hstx_to_cnt DSI_HOST_BITS(0x40, 16, 0) +#define phy_enableclk DSI_HOST_BITS(0x54, 1, 2) +//#define phy_rstz DSI_HOST_BITS(0x54, 1, 1) +//#define phy_shutdownz DSI_HOST_BITS(0x54, 1, 0) + +#define phy_stop_wait_time DSI_HOST_BITS(0x58, 8, 2) +#define n_lanes DSI_HOST_BITS(0x58, 2, 0) +#define phy_tx_triggers DSI_HOST_BITS(0x5c, 4, 5) +#define phy_txexitulpslan DSI_HOST_BITS(0x5c, 1, 4) +#define phy_txrequlpslan DSI_HOST_BITS(0x5c, 1, 3) +#define phy_txexitulpsclk DSI_HOST_BITS(0x5c, 1, 2) +#define phy_txrequlpsclk DSI_HOST_BITS(0x5c, 1, 1) +#define phy_txrequestclkhs DSI_HOST_BITS(0x5c, 1, 0) +#define phy_testclk DSI_HOST_BITS(0x64, 1, 1) +#define phy_testclr DSI_HOST_BITS(0x64, 1, 0) +#define phy_testen DSI_HOST_BITS(0x68, 1, 16) +#define phy_testdout DSI_HOST_BITS(0x68, 8, 8) +#define phy_testdin DSI_HOST_BITS(0x68, 8, 0) +#define outvact_lpcmd_time DSI_HOST_BITS(0x70, 8, 8) +#define invact_lpcmd_time DSI_HOST_BITS(0x70, 8, 0) +#define gen_rd_cmd_busy DSI_HOST_BITS(0x3c, 1, 6) +#define gen_pld_r_full DSI_HOST_BITS(0x3c, 1, 5) +#define gen_pld_r_empty DSI_HOST_BITS(0x3c, 1, 4) +#define gen_pld_w_full DSI_HOST_BITS(0x3c, 1, 3) //800byte write GEN_PLD_DATA +#define gen_pld_w_empty DSI_HOST_BITS(0x3c, 1, 2) +#define gen_cmd_full DSI_HOST_BITS(0x3c, 1, 1) //20 write GEN_HDR +#define gen_cmd_empty DSI_HOST_BITS(0x3c, 1, 0) +#define phystopstateclklane DSI_HOST_BITS(0x60, 1, 2) +#define phylock DSI_HOST_BITS(0x60, 1, 0) + +#else //***************************************************************// +//DWC_DSI_VERSION_0x3133302A +#define VERSION DSI_HOST_BITS(0x000, 32, 0) +#define shutdownz DSI_HOST_BITS(0x004, 1, 0) +#define TO_CLK_DIVISION DSI_HOST_BITS(0x008, 8, 8) +#define TX_ESC_CLK_DIVISION DSI_HOST_BITS(0x008, 8, 0) +#define dpi_vcid DSI_HOST_BITS(0x00c, 2, 0) +#define en18_loosely DSI_HOST_BITS(0x010, 1, 8) +#define dpi_color_coding DSI_HOST_BITS(0x010, 4, 0) //need modify in code +#define colorm_active_low DSI_HOST_BITS(0x014, 1, 4) +#define shutd_active_low DSI_HOST_BITS(0x014, 1, 3) +#define hsync_active_low DSI_HOST_BITS(0x014, 1, 2) +#define vsync_active_low DSI_HOST_BITS(0x014, 1, 1) +#define dataen_active_low DSI_HOST_BITS(0x014, 1, 0) +#define outvact_lpcmd_time DSI_HOST_BITS(0x018, 8, 16) //attence +#define invact_lpcmd_time DSI_HOST_BITS(0x018, 8, 0) +//#define dbi_vcid DSI_HOST_BITS(0x01c, 2, 0) +#define crc_rx_en DSI_HOST_BITS(0x02c, 1, 4) +#define ecc_rx_en DSI_HOST_BITS(0x02c, 1, 3) +#define bta_en DSI_HOST_BITS(0x02c, 1, 2) +#define eotp_rx_en DSI_HOST_BITS(0x02c, 1, 1) +#define eotp_tx_en DSI_HOST_BITS(0x02c, 1, 0) +#define gen_vid_rx DSI_HOST_BITS(0x030, 2, 0) //libing (0x030, 2, 5)-> (0x030, 2, 0) +#define cmd_video_mode DSI_HOST_BITS(0x034, 1, 0) +#define vpg_orientation DSI_HOST_BITS(0x038, 1, 24) //libing +#define vpg_mode DSI_HOST_BITS(0x038, 1, 20) //libing +#define vpg_en DSI_HOST_BITS(0x038, 1, 16) //libing +#define lp_cmd_en DSI_HOST_BITS(0x038, 1, 15) +#define frame_bta_ack_en DSI_HOST_BITS(0x038, 1, 14) +#define lp_hfp_en DSI_HOST_BITS(0x038, 1, 13) +#define lp_hbp_en DSI_HOST_BITS(0x038, 1, 12) +#define lp_vact_en DSI_HOST_BITS(0x038, 1, 11) +#define lp_vfp_en DSI_HOST_BITS(0x038, 1, 10) +#define lp_vbp_en DSI_HOST_BITS(0x038, 1, 9) +#define lp_vsa_en DSI_HOST_BITS(0x038, 1, 8) +#define vid_mode_type DSI_HOST_BITS(0x038, 2, 0) +#define vid_pkt_size DSI_HOST_BITS(0x03c, 14, 0) +#define num_chunks DSI_HOST_BITS(0x040, 13, 0) +#define null_pkt_size DSI_HOST_BITS(0x044, 13, 0) +#define vid_hsa_time DSI_HOST_BITS(0x048, 12, 0) +#define vid_hbp_time DSI_HOST_BITS(0x04c, 12, 0) +#define vid_hline_time DSI_HOST_BITS(0x050, 15, 0) +#define vid_vsa_lines DSI_HOST_BITS(0x054, 10, 0) +#define vid_vbp_lines DSI_HOST_BITS(0x058, 10, 0) +#define vid_vfp_lines DSI_HOST_BITS(0x05c, 10, 0) +#define vid_active_lines DSI_HOST_BITS(0x060, 14, 0) +#define max_rd_pkt_size DSI_HOST_BITS(0x068, 1, 24) +#define dcs_lw_tx DSI_HOST_BITS(0x068, 1, 19) +#define dcs_sr_0p_tx DSI_HOST_BITS(0x068, 1, 18) +#define dcs_sw_1p_tx DSI_HOST_BITS(0x068, 1, 17) +#define dcs_sw_0p_tx DSI_HOST_BITS(0x068, 1, 16) +#define gen_lw_tx DSI_HOST_BITS(0x068, 1, 14) +#define gen_sr_2p_tx DSI_HOST_BITS(0x068, 1, 13) +#define gen_sr_1p_tx DSI_HOST_BITS(0x068, 1, 12) +#define gen_sr_0p_tx DSI_HOST_BITS(0x068, 1, 11) +#define gen_sw_2p_tx DSI_HOST_BITS(0x068, 1, 10) +#define gen_sw_1p_tx DSI_HOST_BITS(0x068, 1, 9) +#define gen_sw_0p_tx DSI_HOST_BITS(0x068, 1, 8) +#define ack_rqst_en DSI_HOST_BITS(0x068, 1, 1) +#define tear_fx_en DSI_HOST_BITS(0x068, 1, 0) +#define GEN_HDR DSI_HOST_BITS(0x06c, 32, 0) +#define GEN_PLD_DATA DSI_HOST_BITS(0x070, 32, 0) //need modify +#define gen_rd_cmd_busy DSI_HOST_BITS(0x074, 1, 6) +#define gen_pld_r_full DSI_HOST_BITS(0x074, 1, 5) +#define gen_pld_r_empty DSI_HOST_BITS(0x074, 1, 4) +#define gen_pld_w_full DSI_HOST_BITS(0x074, 1, 3) //800byte write GEN_PLD_DATA +#define gen_pld_w_empty DSI_HOST_BITS(0x074, 1, 2) +#define gen_cmd_full DSI_HOST_BITS(0x074, 1, 1) //20 write GEN_HDR +#define gen_cmd_empty DSI_HOST_BITS(0x074, 1, 0) +#define hstx_to_cnt DSI_HOST_BITS(0x078, 16, 16) //need modify +#define lprx_to_cnt DSI_HOST_BITS(0x078, 16, 0) +#define hs_rd_to_cnt DSI_HOST_BITS(0x07c, 16, 0) //new(read) +#define lp_rd_to_cnt DSI_HOST_BITS(0x080, 16, 0) //new(read) +#define presp_to_mode DSI_HOST_BITS(0x084, 1, 24) //new +#define hs_wr_to_cnt DSI_HOST_BITS(0x084, 16, 0) //new +#define lp_wr_to_cnt DSI_HOST_BITS(0x088, 16, 0) //new +#define bta_to_cnt DSI_HOST_BITS(0x08c, 16, 0) //new +//#define send_3d_cfg DSI_HOST_BITS(0x090, 1, 16) //new +//#define right_first DSI_HOST_BITS(0x090, 1, 5) //new +//#define second_vsync DSI_HOST_BITS(0x090, 1, 4) //new +//#define format_3d DSI_HOST_BITS(0x090, 2, 2) //new +//#define mode_3d DSI_HOST_BITS(0x090, 2, 0) //new +#define auto_clklane_ctrl DSI_HOST_BITS(0x094, 1, 1) //new +#define phy_txrequestclkhs DSI_HOST_BITS(0x094, 1, 0) +#define phy_hs2lp_time_clk_lane DSI_HOST_BITS(0x098, 10, 16) //libing +#define phy_hs2hs_time_clk_lane DSI_HOST_BITS(0x098, 10, 0) //libing +#define phy_hs2lp_time DSI_HOST_BITS(0x09c, 8, 24) +#define phy_lp2hs_time DSI_HOST_BITS(0x09c, 8, 16) +#define max_rd_time DSI_HOST_BITS(0x09c, 15, 0) +#define phy_forcepll DSI_HOST_BITS(0x0a0, 1, 3) //new Dependency: DSI_HOST_FPGA = 0. Otherwise, this bit is reserved. +#define phy_enableclk DSI_HOST_BITS(0x0a0, 1, 2) +#define phy_rstz DSI_HOST_BITS(0x0a0, 1, 1) //libing +#define phy_shutdownz DSI_HOST_BITS(0x0a0, 1, 0) //libing +#define phy_stop_wait_time DSI_HOST_BITS(0x0a4, 8, 8) +#define n_lanes DSI_HOST_BITS(0x0a4, 2, 0) +#define phy_txexitulpslan DSI_HOST_BITS(0x0a8, 1, 3) +#define phy_txrequlpslan DSI_HOST_BITS(0x0a8, 1, 2) +#define phy_txexitulpsclk DSI_HOST_BITS(0x0a8, 1, 1) +#define phy_txrequlpsclk DSI_HOST_BITS(0x0a8, 1, 0) +#define phy_tx_triggers DSI_HOST_BITS(0x0ac, 4, 0) + +#define phystopstateclklane DSI_HOST_BITS(0x0b0, 1, 2) +#define phylock DSI_HOST_BITS(0x0b0, 1, 0) +#define phy_testclk DSI_HOST_BITS(0x0b4, 1, 1) +#define phy_testclr DSI_HOST_BITS(0x0b4, 1, 0) +#define phy_testen DSI_HOST_BITS(0x0b8, 1, 16) +#define phy_testdout DSI_HOST_BITS(0x0b8, 8, 8) +#define phy_testdin DSI_HOST_BITS(0x0b8, 8, 0) + +#define PHY_TEST_CTRL1 DSI_HOST_BITS(0x0b8, 17, 0) +#define PHY_TEST_CTRL0 DSI_HOST_BITS(0x0b4, 2, 0) + +#define INT_ST0 DSI_HOST_BITS(0x0bc, 21, 0) +#define INT_ST1 DSI_HOST_BITS(0x0c0, 18, 0) +#define INT_MKS0 DSI_HOST_BITS(0x0c4, 21, 0) +#define INT_MKS1 DSI_HOST_BITS(0x0c8, 18, 0) //libing +#define INT_FORCE0 DSI_HOST_BITS(0x0d8, 21, 0) //libing +#define INT_FORCE1 DSI_HOST_BITS(0x0dc, 18, 0) //libing + +#define code_hs_rx_clock 0x34 +#define code_hs_rx_lane0 0x44 +#define code_hs_rx_lane1 0x54 +#define code_hs_rx_lane2 0x84 +#define code_hs_rx_lane3 0x94 + +#define code_pll_input_div_rat 0x17 +#define code_pll_loop_div_rat 0x18 +#define code_pll_input_loop_div_rat 0x19 + +#define code_hstxdatalanerequsetstatetime 0x70 +#define code_hstxdatalanepreparestatetime 0x71 +#define code_hstxdatalanehszerostatetime 0x72 + + + + + +//#define en_null_pkt DSI_HOST_BITS(0x1c, 1, 13) //delete +//#define en_multi_pkt DSI_HOST_BITS(0x1c, 1, 13) //delete +#endif /* end of DWC_DSI_VERSION_0x3131302A */ + + + +//MIPI DSI DPHY REGISTERS +#define DPHY_REGISTER0 DSI_DPHY_BITS(0x00, 32, 0) +#define DPHY_REGISTER1 DSI_DPHY_BITS(0x04, 32, 0) +#define DPHY_REGISTER3 DSI_DPHY_BITS(0x0c, 32, 0) +#define DPHY_REGISTER4 DSI_DPHY_BITS(0x10, 32, 0) +#define DPHY_REGISTER20 DSI_DPHY_BITS(0X80, 32, 0) + +#define lane_en_ck DSI_DPHY_BITS(0x00, 1, 6) +#define lane_en_3 DSI_DPHY_BITS(0x00, 1, 5) +#define lane_en_2 DSI_DPHY_BITS(0x00, 1, 4) +#define lane_en_1 DSI_DPHY_BITS(0x00, 1, 3) +#define lane_en_0 DSI_DPHY_BITS(0x00, 1, 2) + +#define reg_da_ppfc DSI_DPHY_BITS(0x04, 1, 4) +#define reg_da_syncrst DSI_DPHY_BITS(0x04, 1, 2) +#define reg_da_ldopd DSI_DPHY_BITS(0x04, 1, 1) +#define reg_da_pllpd DSI_DPHY_BITS(0x04, 1, 0) + +#define reg_fbdiv_8 DSI_DPHY_BITS(0x0c, 1, 5) +#define reg_prediv DSI_DPHY_BITS(0x0c, 5, 0) +#define reg_fbdiv DSI_DPHY_BITS(0x10, 8, 0) + +#define reg_dig_rstn DSI_DPHY_BITS(0X80, 1, 0) + +#define DPHY_CLOCK_OFFSET REG_ADDR(0X0100) +#define DPHY_LANE0_OFFSET REG_ADDR(0X0180) +#define DPHY_LANE1_OFFSET REG_ADDR(0X0200) +#define DPHY_LANE2_OFFSET REG_ADDR(0X0280) +#define DPHY_LANE3_OFFSET REG_ADDR(0X0300) + +#define reg_ths_settle DSI_DPHY_BITS(0x0000, 4, 0) +#define reg_hs_tlpx DSI_DPHY_BITS(0x0014, 6, 0) +#define reg_hs_ths_prepare DSI_DPHY_BITS(0x0018, 7, 0) +#define reg_hs_the_zero DSI_DPHY_BITS(0x001c, 6, 0) +#define reg_hs_ths_trail DSI_DPHY_BITS(0x0020, 7, 0) +#define reg_hs_ths_exit DSI_DPHY_BITS(0x0024, 5, 0) +#define reg_hs_tclk_post DSI_DPHY_BITS(0x0028, 4, 0) +#define reserved DSI_DPHY_BITS(0x002c, 1, 0) +#define reg_hs_twakup_h DSI_DPHY_BITS(0x0030, 2, 0) +#define reg_hs_twakup_l DSI_DPHY_BITS(0x0034, 8, 0) +#define reg_hs_tclk_pre DSI_DPHY_BITS(0x0038, 4, 0) +#define reg_hs_tta_go DSI_DPHY_BITS(0x0040, 6, 0) +#define reg_hs_tta_sure DSI_DPHY_BITS(0x0044, 6, 0) +#define reg_hs_tta_wait DSI_DPHY_BITS(0x0048, 6, 0) + + +#ifdef DWC_DSI_VERSION_0x3131302A +//MISC REGISTERS +#define DSI_MISC_BITS(addr, bits, bit_offset) (REG_ADDR(addr) \ + | REG_BITS(bits) | BITS_OFFSET(bit_offset)) + +#define CRU_CRU_CLKSEL1_CON (0x005c) +#define CRU_CFG_MISC_CON (0x009c) + +#define cfg_mipiclk_gaten DSI_MISC_BITS(CRU_CRU_CLKSEL1_CON, 1, 10) + +#define mipi_int DSI_MISC_BITS(CRU_CFG_MISC_CON, 1, 19) +#define mipi_edpihalt DSI_MISC_BITS(CRU_CFG_MISC_CON, 1, 16) +#define pin_forcetxstopmode_3 DSI_MISC_BITS(CRU_CFG_MISC_CON, 1, 11) +#define pin_forcetxstopmode_2 DSI_MISC_BITS(CRU_CFG_MISC_CON, 1, 10) +#define pin_forcetxstopmode_1 DSI_MISC_BITS(CRU_CFG_MISC_CON, 1, 9) +#define pin_forcetxstopmode_0 DSI_MISC_BITS(CRU_CFG_MISC_CON, 1, 8) +#define pin_forcerxmode_0 DSI_MISC_BITS(CRU_CFG_MISC_CON, 1, 7) +#define pin_turndisable_0 DSI_MISC_BITS(CRU_CFG_MISC_CON, 1, 6) +#define dpicolom DSI_MISC_BITS(CRU_CFG_MISC_CON, 1, 2) +#define dpishutdn DSI_MISC_BITS(CRU_CFG_MISC_CON, 1, 1) + +#else + +//#define mipi_int +//#define mipi_edpihalt +#define pin_forcetxstopmode_3 +#define pin_forcetxstopmode_2 +#define pin_forcetxstopmode_1 +#define pin_forcetxstopmode_0 +#define pin_forcerxmode_0 +#define pin_turndisable_0 +#define dpicolom +#define dpishutdn + +#endif + + +//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 + +#ifdef CONFIG_MIPI_DSI_LINUX + struct clk *refclk; + unsigned long iobase; + void __iomem *membase; +#endif + u16 prediv; + u16 fbdiv; + u8 flag; + struct gotp gotp; + +}; + +struct dsi_host { + u8 flag; + u8 lane; + u8 format; + u8 video_mode; + u32 clk; + u32 irq; +#ifdef CONFIG_MIPI_DSI_LINUX + unsigned long iobase; + void __iomem *membase; +#endif +}; + +struct dsi { + u8 dsi_id; + u8 lcdc_id; + u8 vid; + struct dsi_phy phy; + struct dsi_host host; + struct mipi_dsi_ops ops; + struct mipi_dsi_screen screen; +#ifdef CONFIG_MIPI_DSI_LINUX + struct clk *dsi_pclk; + struct clk *dsi_pd; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif +#endif + struct dentry *debugfs_dir; + struct platform_device *pdev; +}; + +int rk_mipi_get_dsi_clk(void); +int rk_mipi_get_dsi_num(void); +int rk_mipi_get_dsi_lane(void); + +extern int rk616_mipi_dsi_ft_init(void); +int rk_mipi_dsi_init_lite(struct dsi *dsi); +#endif /* end of RK616_MIPI_DSI_H */