--- /dev/null
+/*
+ * 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/mfd/rk616.h>
+#include <linux/rk_fb.h>
+#include <linux/rk_screen.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <asm/div64.h>
+
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/regulator/machine.h>
+
+
+#include <linux/dma-mapping.h>
+#include "mipi_dsi.h"
+#include "rk32_mipi_dsi.h"
+#include <linux/rockchip/iomap.h>
+
+
+
+#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 <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+
+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);
--- /dev/null
+/*
+drivers/video/rockchip/transmitter/rk616_mipi_dsi.h
+*/
+#include <linux/rockchip/grf.h>
+#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 */