summaryrefslogtreecommitdiff
path: root/drivers/video/sprdfb/sprdfb_dsi.c
diff options
context:
space:
mode:
authorYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
committerYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
commit8e4bff4cab0ddac6060645b0715210484d02ff40 (patch)
tree3a5c3024371a04692a3a6d9974d001cdff8ebf84 /drivers/video/sprdfb/sprdfb_dsi.c
Initial file dump from open source releaseHEADmaster
Diffstat (limited to 'drivers/video/sprdfb/sprdfb_dsi.c')
-rw-r--r--drivers/video/sprdfb/sprdfb_dsi.c1010
1 files changed, 1010 insertions, 0 deletions
diff --git a/drivers/video/sprdfb/sprdfb_dsi.c b/drivers/video/sprdfb/sprdfb_dsi.c
new file mode 100644
index 00000000..7f0e8b81
--- /dev/null
+++ b/drivers/video/sprdfb/sprdfb_dsi.c
@@ -0,0 +1,1010 @@
+/*
+ * Copyright (C) 2012 Spreadtrum Communications Inc.
+ *
+ * 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.
+ */
+
+#include <linux/kgdb.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/irqreturn.h>
+#include <linux/interrupt.h>
+#ifdef CONFIG_OF
+#include <linux/fb.h>
+
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#endif
+
+#include "sprdfb_chip_common.h"
+#include "sprdfb.h"
+#include "sprdfb_panel.h"
+
+#if (defined(CONFIG_FB_SCX30G) || defined(CONFIG_FB_SCX35L))
+#define FB_DSIH_VERSION_1P21A
+#endif
+
+#ifdef FB_DSIH_VERSION_1P21A
+#include "dsi_1_21a/mipi_dsih_local.h"
+#include "dsi_1_21a/mipi_dsih_dphy.h"
+#include "dsi_1_21a/mipi_dsih_hal.h"
+#include "dsi_1_21a/mipi_dsih_api.h"
+#else
+#include "dsi_1_10a/mipi_dsih_local.h"
+#include "dsi_1_10a/mipi_dsih_dphy.h"
+#include "dsi_1_10a/mipi_dsih_hal.h"
+#include "dsi_1_10a/mipi_dsih_api.h"
+#endif
+
+#define DSI_PHY_REF_CLOCK (26*1000)
+
+#define DSI_EDPI_CFG (0x6c)
+
+struct sprdfb_dsi_context {
+ struct clk *clk_dsi;
+ bool is_inited;
+ uint32_t status;/*0- normal, 1- uninit, 2-abnormal*/
+ struct sprdfb_device *dev;
+
+ dsih_ctrl_t dsi_inst;
+};
+
+static struct sprdfb_dsi_context dsi_ctx;
+#ifdef CONFIG_OF
+unsigned long g_dsi_base_addr = 0;
+EXPORT_SYMBOL(g_dsi_base_addr);
+#endif
+
+
+static int32_t sprdfb_dsi_set_lp_mode(void);
+static int32_t sprdfb_dsi_set_ulps_mode(void);
+
+static uint32_t dsi_core_read_function(unsigned long addr, uint32_t offset)
+{
+ return __raw_readl(addr + offset);
+}
+
+static void dsi_core_write_function(unsigned long addr, uint32_t offset, uint32_t data)
+{
+// __raw_writel(data, addr + offset);
+ __raw_writel(data, (addr + offset));
+}
+
+void dsi_core_or_function(unsigned long addr,unsigned int data)
+{
+ __raw_writel((__raw_readl(addr) | data), addr);
+}
+void dsi_core_and_function(unsigned long addr,unsigned int data)
+{
+ __raw_writel((__raw_readl(addr) & data), addr);
+}
+
+void dsi_irq_trick(void)
+{
+ /*enable ack_with_err_0 interrupt*/
+ DSI_INT_MASK0_SET(0, 0);
+}
+
+//static uint32_t sot_ever_happened = 0;
+static irqreturn_t dsi_isr0(int irq, void *data)
+{
+#ifdef FB_DSIH_VERSION_1P21A
+ uint32_t reg_val = dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_ST0);
+#else
+ uint32_t reg_val = dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_ST0);
+#endif
+
+ printk(KERN_ERR "sprdfb: [%s](0x%x)!\n", __FUNCTION__, reg_val);
+ /*
+ printk("Warning: sot_ever_happened:(0x%x)!\n",sot_ever_happened);
+ */
+ if(reg_val & 0x1) {
+/*
+ //sot_ever_happened = 1;
+ mask = dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_MSK0);
+ mask |= 0x1;
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_MSK0, mask);
+*/
+ DSI_INT_MASK0_SET(0, 1);
+ }
+
+ //dsi_irq_trick(0,reg_val);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t dsi_isr1(int irq, void *data)
+{
+#ifdef FB_DSIH_VERSION_1P21A
+ uint32_t reg_val = dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_ST1);
+#else
+ uint32_t reg_val = dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_ST1);
+#endif
+ uint32_t i = 0;
+ struct sprdfb_dsi_context *dsi_ctx = (struct sprdfb_dsi_context *)data;
+ struct sprdfb_device *dev = dsi_ctx->dev;
+ dsih_ctrl_t* dsi_instance = &(dsi_ctx->dsi_inst);
+ dphy_t *phy = &(dsi_instance->phy_instance);
+ struct panel_spec* panel = dev->panel;
+ struct info_mipi * mipi = panel->info.mipi;
+
+ printk(KERN_ERR "sprdfb: [%s](0x%x)!\n", __FUNCTION__, reg_val);
+
+ if(BIT(7) == (reg_val & BIT(7))){
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PWR_UP, 0);
+ /*need delay 1us*/
+ printk("sprdfb: reset dsi host!\n");
+ printk("sprdfb: mipi->lan_number:%d ,mipi->phy_feq:%d \n",mipi->lan_number,mipi->phy_feq);
+ if(NULL == phy){
+ printk("sprdfb: the phy is null \n");
+ //dsi_irq_trick(1,reg_val);
+ return IRQ_NONE;
+ }
+
+ mipi_dsih_dphy_configure(phy, mipi->lan_number, mipi->phy_feq);
+
+ {/*for debug*/
+ for(i=0;i<256;i+=16){
+ printk("sprdfb: %x: 0x%x, 0x%x, 0x%x, 0x%x\n", i, dsi_core_read_function(SPRD_MIPI_DSIC_BASE, i),
+ dsi_core_read_function(SPRD_MIPI_DSIC_BASE, i+4),
+ dsi_core_read_function(SPRD_MIPI_DSIC_BASE, i+8),
+ dsi_core_read_function(SPRD_MIPI_DSIC_BASE, i+12));
+ }
+ printk("**************************\n");
+ }
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PWR_UP, 1);
+ }
+ //dsi_irq_trick(1,reg_val);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t dsi_isr2(int irq, void *data)
+{
+ uint32_t reg_val = 0;
+ struct sprdfb_dsi_context *dsi_ctx = (struct sprdfb_dsi_context *)data;
+ struct sprdfb_device *dev = dsi_ctx->dev;
+
+ printk(KERN_ERR "sprdfb: [%s](0x%x)!\n", __FUNCTION__, reg_val);
+
+ if(MIPI_PLL_TYPE_1 == dev->capability.mipi_pll_type) /* for PikeL / Pike */
+ {
+ reg_val = dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_MIPI_PLL_INT_STS);
+ if(BIT(0) == (reg_val & BIT(0)))
+ {
+ dsi_core_or_function(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_MIPI_PLL_INT_CLR, BIT(0));
+ printk("sprdfb: [%s], mipi pll interrupt!\n",__FUNCTION__);
+ dsi_core_and_function(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_MIPI_PLL_INT_MSK, 0xFFFFFFFE);
+ }
+ }
+ else if(MIPI_PLL_TYPE_2 == dev->capability.mipi_pll_type) /* for Sharkl64 / SharklT8*/
+ {
+ dsi_core_or_function(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_MIPI_PLL_INT_CLR, BIT(0));
+ printk("sprdfb: [%s], mipi pll interrupt!\n",__FUNCTION__);
+ dsi_core_or_function(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_MIPI_PLL_INT_EN, BIT(0));
+ }
+ return IRQ_HANDLED;
+}
+
+static void dsi_reset(void)
+{
+ sci_glb_set(DSI_AHB_SOFT_RST, BIT_DSI_SOFT_RST);
+ udelay(10);
+ sci_glb_clr(DSI_AHB_SOFT_RST, BIT_DSI_SOFT_RST);
+}
+
+static int32_t dsi_edpi_setbuswidth(struct info_mipi * mipi)
+{
+ dsih_color_coding_t color_coding = 0;
+
+ switch(mipi->video_bus_width){
+ case 16:
+ color_coding = COLOR_CODE_16BIT_CONFIG1;
+ break;
+ case 18:
+ color_coding = COLOR_CODE_18BIT_CONFIG1;
+ break;
+ case 24:
+ color_coding = COLOR_CODE_24BIT;
+ break;
+ default:
+ printk(KERN_ERR "sprdfb: [%s] fail, invalid video_bus_width\n", __FUNCTION__);
+ return 0;
+ }
+
+#ifdef FB_DSIH_VERSION_1P21A
+ dsi_core_and_function((SPRD_MIPI_DSIC_BASE+R_DSI_HOST_DPI_COLOR_CODE),0xfffffff0);
+ dsi_core_or_function((SPRD_MIPI_DSIC_BASE+R_DSI_HOST_DPI_COLOR_CODE),color_coding);
+#else
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_DPI_CFG, ((uint32_t)color_coding<<2));
+#endif
+ return 0;
+}
+
+
+static int32_t dsi_edpi_init(void)
+{
+#ifdef FB_DSIH_VERSION_1P21A
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_EDPI_CMD_SIZE, 0x500);
+#else
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, DSI_EDPI_CFG, 0x10500);
+#endif
+ return 0;
+}
+
+int32_t dsi_dpi_init(struct sprdfb_device *dev)
+{
+ dsih_dpi_video_t dpi_param = {0};
+ dsih_error_t result;
+ struct panel_spec* panel = dev->panel;
+ struct info_mipi * mipi = panel->info.mipi;
+
+ dpi_param.no_of_lanes = mipi->lan_number;
+ dpi_param.byte_clock = mipi->phy_feq / 8;
+#ifndef CONFIG_SC_FPGA
+ dpi_param.pixel_clock = dev->dpi_clock/1000;
+#else
+ dpi_param.pixel_clock = 6500;
+#endif
+#ifdef FB_DSIH_VERSION_1P21A
+ dpi_param.max_hs_to_lp_cycles = 4;//110;
+ dpi_param.max_lp_to_hs_cycles = 15;//10;
+ dpi_param.max_clk_hs_to_lp_cycles = 4;//110;
+ dpi_param.max_clk_lp_to_hs_cycles = 15;//10;
+#endif
+
+ switch(mipi->video_bus_width){
+ case 16:
+ dpi_param.color_coding = COLOR_CODE_16BIT_CONFIG1;
+ break;
+ case 18:
+ dpi_param.color_coding = COLOR_CODE_18BIT_CONFIG1;
+ break;
+ case 24:
+ dpi_param.color_coding = COLOR_CODE_24BIT;
+ break;
+ default:
+ printk(KERN_ERR "sprdfb: [%s] fail, invalid video_bus_width\n", __FUNCTION__);
+ break;
+ }
+
+ if(SPRDFB_POLARITY_POS == mipi ->h_sync_pol){
+ dpi_param.h_polarity = 1;
+ }
+
+ if(SPRDFB_POLARITY_POS == mipi ->v_sync_pol){
+ dpi_param.v_polarity = 1;
+ }
+
+ if(SPRDFB_POLARITY_POS == mipi ->de_pol){
+ dpi_param.data_en_polarity = 1;
+ }
+
+ dpi_param.h_active_pixels = panel->width;
+ dpi_param.h_sync_pixels = mipi->timing->hsync;
+ dpi_param.h_back_porch_pixels = mipi->timing->hbp;
+ dpi_param.h_total_pixels = panel->width + mipi->timing->hsync + mipi->timing->hbp + mipi->timing->hfp;
+
+ dpi_param.v_active_lines = panel->height;
+ dpi_param.v_sync_lines = mipi->timing->vsync;
+ dpi_param.v_back_porch_lines = mipi->timing->vbp;
+ dpi_param.v_total_lines = panel->height + mipi->timing->vsync + mipi->timing->vbp + mipi->timing->vfp;
+
+ dpi_param.receive_ack_packets = 0;
+ dpi_param.video_mode = VIDEO_BURST_WITH_SYNC_PULSES;
+ dpi_param.virtual_channel = 0;
+#ifndef CONFIG_FB_LCD_ILI9486S1_MIPI
+ dpi_param.is_18_loosely = 0;
+#else
+ dpi_param.is_18_loosely = 1;
+#endif
+
+ result = mipi_dsih_dpi_video(&(dsi_ctx.dsi_inst), &dpi_param);
+ if(result != OK){
+ printk(KERN_ERR "sprdfb: [%s] mipi_dsih_dpi_video fail (%d)!\n", __FUNCTION__, result);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void dsi_log_error(const char * string)
+{
+ printk(string);
+}
+
+static int32_t dsi_module_init(struct sprdfb_device *dev)
+{
+ int ret = 0;
+ dsih_ctrl_t* dsi_instance = &(dsi_ctx.dsi_inst);
+ dphy_t *phy = &(dsi_instance->phy_instance);
+
+ struct info_mipi * mipi = dev->panel->info.mipi;
+
+ int irq_num_1, irq_num_2, irq_num_3;
+
+ pr_debug(KERN_INFO "sprdfb: [%s]\n", __FUNCTION__);
+
+ if(dsi_ctx.is_inited){
+ printk(KERN_INFO "sprdfb: dsi_module_init. is_inited==true!");
+ return 0;
+ }
+ else{
+ printk(KERN_INFO "sprdfb: dsi_module_init. call only once!");
+ }
+
+ phy->address = SPRD_MIPI_DSIC_BASE;
+ phy->core_read_function = dsi_core_read_function;
+ phy->core_write_function = dsi_core_write_function;
+ phy->log_error = dsi_log_error;
+ phy->log_info = NULL;
+ phy->reference_freq = DSI_PHY_REF_CLOCK;
+
+ dsi_instance->address = SPRD_MIPI_DSIC_BASE;
+ //dsi_instance->color_mode_polarity =mipi->color_mode_pol;
+ //dsi_instance->shut_down_polarity = mipi->shut_down_pol;
+ dsi_instance->core_read_function = dsi_core_read_function;
+ dsi_instance->core_write_function = dsi_core_write_function;
+ dsi_instance->log_error = dsi_log_error;
+ dsi_instance->log_info = NULL;
+ /*in our rtl implementation, this is max rd time, not bta time and use 15bits*/
+ dsi_instance->max_bta_cycles = 0x6000;//10;
+#ifndef FB_DSIH_VERSION_1P21A
+ dsi_instance->max_hs_to_lp_cycles = 4;//110;
+ dsi_instance->max_lp_to_hs_cycles = 15;//10;
+#endif
+ //dsi_instance->max_lanes = mipi->lan_number;
+#ifdef CONFIG_OF
+ irq_num_1 = irq_of_parse_and_map(dev->of_dev->of_node, 1);
+#else
+ irq_num_1 = IRQ_DSI_INTN0;
+#endif
+ printk("sprdfb: dsi irq_num_1 = %d\n", irq_num_1);
+
+// ret = request_irq(IRQ_DSI_INTN0, dsi_isr0, IRQF_DISABLED, "DSI_INT0", &dsi_ctx);
+ ret = request_irq(irq_num_1, dsi_isr0, IRQF_DISABLED, "DSI_INT0", &dsi_ctx);
+ if (ret) {
+ printk(KERN_ERR "sprdfb: dsi failed to request irq int0!\n");
+// clk_disable(dsi_ctx.clk_dsi);
+ }else{
+ printk(KERN_ERR "sprdfb: dsi request irq int0 OK!\n");
+ }
+
+#ifdef CONFIG_OF
+ irq_num_2 = irq_of_parse_and_map(dev->of_dev->of_node, 2);
+#else
+ irq_num_2 = IRQ_DSI_INTN1;
+#endif
+ printk("sprdfb: dsi irq_num_2 = %d\n", irq_num_2);
+
+// ret = request_irq(IRQ_DSI_INTN1, dsi_isr1, IRQF_DISABLED, "DSI_INT1", &dsi_ctx);
+ ret = request_irq(irq_num_2, dsi_isr1, IRQF_DISABLED, "DSI_INT1", &dsi_ctx);
+ if (ret) {
+ printk(KERN_ERR "sprdfb: dsi failed to request irq int1!\n");
+// clk_disable(dsi_ctx.clk_dsi);
+ }else{
+ printk(KERN_ERR "sprdfb: dsi request irq int1 OK!\n");
+ }
+
+ if((dev->capability.mipi_pll_type > MIPI_PLL_TYPE_NONE)
+ && (dev->capability.mipi_pll_type < MIPI_PLL_TYPE_LIMIT))
+ {
+#ifdef CONFIG_OF
+ irq_num_3 = irq_of_parse_and_map(dev->of_dev->of_node, 3);
+#else
+ irq_num_3 = IRQ_DSI_INTN2;
+#endif
+ printk("sprdfb: dsi irq_num_3 = %d\n", irq_num_3);
+
+ ret = request_irq(irq_num_3, dsi_isr2, IRQF_DISABLED, "DSI_INT2", &dsi_ctx);
+ if (ret) {
+ printk(KERN_ERR "sprdfb: dsi failed to request irq int2!\n");
+ }else{
+ printk(KERN_ERR "sprdfb: dsi request irq int2 OK!\n");
+ }
+
+ if(MIPI_PLL_TYPE_1 == dev->capability.mipi_pll_type) {
+ dsi_core_and_function(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_MIPI_PLL_INT_MSK, 0xFFFFFFFE);
+ } else if (MIPI_PLL_TYPE_2 == dev->capability.mipi_pll_type) {
+ dsi_core_and_function(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_MIPI_PLL_INT_MSK, 0xFFFFFFFE);
+ dsi_core_or_function(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_MIPI_PLL_INT_EN, BIT(0));
+ }
+ }
+
+ dsi_ctx.is_inited = true;
+
+ return 0;
+}
+
+#ifdef CONFIG_FB_DYNAMIC_FREQ_SCALING
+int sprdfb_dsi_chg_dphy_freq(struct sprdfb_device *fb_dev,
+ u32 dphy_freq)
+{
+ dsih_error_t result = OK;
+ dsih_ctrl_t *ctrl = &(dsi_ctx.dsi_inst);
+ struct info_mipi *mipi = fb_dev->panel->info.mipi;
+
+ if (ctrl->status == INITIALIZED) {
+ pr_info("Let's do update D-PHY frequency(%u)\n", dphy_freq);
+ ctrl->phy_instance.phy_keep_work = true;
+ result = mipi_dsih_dphy_configure(&ctrl->phy_instance,
+ mipi->lan_number, dphy_freq);
+ if (result != OK) {
+ pr_err("[%s]: mipi_dsih_dphy_configure fail (%d)\n",
+ __func__, result);
+ ctrl->phy_instance.phy_keep_work = false;
+ return -1;
+ }
+ ctrl->phy_instance.phy_keep_work = false;
+ }
+ mipi->phy_feq = dphy_freq;
+ return 0;
+}
+#else
+int sprdfb_dsi_chg_dphy_freq(struct sprdfb_device *fb_dev,
+ u32 dphy_freq)
+{
+ return -EINVAL;
+}
+#endif
+
+int32_t sprdfb_dsih_init(struct sprdfb_device *dev)
+{
+ dsih_error_t result = OK;
+ dsih_ctrl_t* dsi_instance = &(dsi_ctx.dsi_inst);
+ dphy_t *phy = &(dsi_instance->phy_instance);
+ struct info_mipi * mipi = dev->panel->info.mipi;
+ int wait_count = 0;
+#ifdef FB_DSIH_VERSION_1P21A
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_MSK0, 0x1fffff);
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_MSK1, 0x3ffff);
+#else
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_MSK0, 0x1fffff);
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_MSK1, 0x3ffff);
+#endif
+
+ if(SPRDFB_MIPI_MODE_CMD == mipi->work_mode){
+ dsi_edpi_init();
+ }/*else{
+ dsi_dpi_init(dev->panel);
+ }*/
+
+/*
+ result = mipi_dsih_unregister_all_events(dsi_instance);
+ if(OK != result){
+ printk(KERN_ERR "sprdfb: [%s]: mipi_dsih_unregister_all_events fail (%d)!\n", __FUNCTION__, result);
+ return -1;
+ }
+*/
+// dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_MSK0, 0x1fffff);
+// dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_MSK1, 0x3ffff);
+
+ dsi_instance->phy_feq = dev->panel->info.mipi->phy_feq;
+ dsi_instance->max_lanes = dev->panel->info.mipi->lan_number;
+ dsi_instance->color_mode_polarity =dev->panel->info.mipi->color_mode_pol;
+ dsi_instance->shut_down_polarity = dev->panel->info.mipi->shut_down_pol;
+
+ result = mipi_dsih_open(dsi_instance);
+ if(OK != result){
+ printk(KERN_ERR "sprdfb: [%s]: mipi_dsih_open fail (%d)!\n", __FUNCTION__, result);
+ dsi_ctx.status = 1;
+ return -1;
+ }
+
+ result = mipi_dsih_dphy_configure(phy, mipi->lan_number, mipi->phy_feq);
+ if(OK != result){
+ printk(KERN_ERR "sprdfb: [%s]: mipi_dsih_dphy_configure fail (%d)!\n", __FUNCTION__, result);
+ dsi_ctx.status = 1;
+ return -1;
+ }
+
+ while(5 != (dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PHY_STATUS) & 5) &&
+ (wait_count < 100000)){
+ udelay(3);
+ if(0x0 == ++wait_count%1000){
+ printk("sprdfb: [%s] warning: busy waiting!\n", __FUNCTION__);
+ }
+ }
+ if(wait_count >= 100000){
+ printk("sprdfb: [%s] Errior: dsi phy can't be locked!!!\n", __FUNCTION__);
+ }
+ if(wait_count >= 100000){
+ printk("sprdfb: [%s] Errior: dsi phy can't be locked!!!\n", __FUNCTION__);
+ }
+
+ if(SPRDFB_MIPI_MODE_CMD == mipi->work_mode){
+ dsi_edpi_setbuswidth(mipi);
+ }
+
+ result = mipi_dsih_enable_rx(dsi_instance, 1);
+ if(OK != result){
+ printk(KERN_ERR "sprdfb: [%s]: mipi_dsih_enable_rx fail (%d)!\n", __FUNCTION__, result);
+ dsi_ctx.status = 1;
+ return -1;
+ }
+
+ result = mipi_dsih_ecc_rx(dsi_instance, 1);
+ if(OK != result){
+ printk(KERN_ERR "sprdfb: [%s]: mipi_dsih_ecc_rx fail (%d)!\n", __FUNCTION__, result);
+ dsi_ctx.status = 1;
+ return -1;
+ }
+
+ result = mipi_dsih_eotp_rx(dsi_instance, 1);
+ if(OK != result){
+ printk(KERN_ERR "sprdfb: [%s]: mipi_dsih_eotp_rx fail (%d)!\n", __FUNCTION__, result);
+ dsi_ctx.status = 1;
+ return -1;
+ }
+
+ result = mipi_dsih_eotp_tx(dsi_instance, 1);
+ if(OK != result){
+ printk(KERN_ERR "sprdfb: [%s]: mipi_dsih_eotp_tx fail (%d)!\n", __FUNCTION__, result);
+ dsi_ctx.status = 1;
+ return -1;
+ }
+
+ if(SPRDFB_MIPI_MODE_VIDEO == mipi->work_mode){
+ dsi_dpi_init(dev);
+ }
+
+#ifdef FB_DSIH_VERSION_1P21A
+ mipi_dsih_dphy_enable_nc_clk(&(dsi_instance->phy_instance), false);
+#endif
+ dsi_ctx.status = 0;
+
+ return 0;
+}
+
+int32_t sprdfb_dsi_init(struct sprdfb_device *dev)
+{
+ dsih_error_t result = OK;
+ dsih_ctrl_t* dsi_instance = &(dsi_ctx.dsi_inst);
+#ifdef CONFIG_OF
+ struct resource r;
+#endif
+
+ dsi_ctx.dev = dev;
+
+#ifdef CONFIG_OF
+ if(0 == g_dsi_base_addr){
+ if(0 != of_address_to_resource(dev->of_dev->of_node, 1, &r)){
+ printk(KERN_ERR "sprdfb: sprdfb_dsi_init fail. (can't get register base address)\n");
+ return -1;
+ }
+ g_dsi_base_addr = (unsigned long)ioremap_nocache(r.start, resource_size(&r));
+ }
+ if (0 == g_dsi_base_addr){
+ printk("sprdfb: g_dsi_base_addr = 0!(0x%ul)\n", r.start);
+ return -ENOMEM;
+ }
+ printk("sprdfb: set g_dsi_base_addr = 0x%lx\n", g_dsi_base_addr);
+#endif
+
+
+ if(!dsi_ctx.is_inited){
+ //init
+ if(dev->panel_ready){
+ //panel ready
+ printk(KERN_INFO "sprdfb: [%s]: dsi has alread initialized\n", __FUNCTION__);
+ dsi_instance->status = INITIALIZED;
+ dsi_instance->phy_instance.status = INITIALIZED;
+ dsi_module_init(dev);
+#ifdef FB_DSIH_VERSION_1P21A
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_MSK0, 0x0);
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_MSK1, 0x800);
+#else
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_MSK0, 0x0);
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_MSK1, 0x800);
+#endif
+ }else{
+ //panel not ready
+ printk(KERN_INFO "sprdfb: [%s]: dsi is not initialized\n", __FUNCTION__);
+ dsi_enable();
+ dsi_reset();
+ dsi_module_init(dev);
+ result=sprdfb_dsih_init(dev);
+ }
+ }else{
+ //resume
+ printk(KERN_INFO "sprdfb: [%s]: resume\n", __FUNCTION__);
+ dsi_enable();
+ dsi_reset();
+ result=sprdfb_dsih_init(dev);
+ }
+
+ return result;
+}
+
+int32_t sprdfb_dsi_uninit(struct sprdfb_device *dev)
+{
+ dsih_error_t result;
+ dsih_ctrl_t* dsi_instance = &(dsi_ctx.dsi_inst);
+ printk(KERN_INFO "sprdfb: [%s], dev_id = %d\n",__FUNCTION__, dev->dev_id);
+#ifdef FB_DSIH_VERSION_1P21A
+ mipi_dsih_dphy_enable_hs_clk(&(dsi_instance->phy_instance), false);
+#else
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PHY_IF_CTRL, 0);
+#endif
+ result = mipi_dsih_close(&(dsi_ctx.dsi_inst));
+ dsi_instance->status = NOT_INITIALIZED;
+
+ dsi_ctx.status = 1;
+
+ if(OK != result){
+ printk(KERN_ERR "sprdfb: [%s]: sprdfb_dsi_uninit fail (%d)!\n", __FUNCTION__, result);
+ return -1;
+ }
+
+ msleep(10);
+ dsi_disable();
+ return 0;
+}
+
+int32_t sprdfb_dsi_suspend(struct sprdfb_device *dev)
+{
+ dsih_ctrl_t* dsi_instance = &(dsi_ctx.dsi_inst);
+ printk(KERN_INFO "sprdfb: [%s], dev_id = %d\n",__FUNCTION__, dev->dev_id);
+// sprdfb_dsi_uninit(dev);
+// mipi_dsih_dphy_close(&(dsi_instance->phy_instance));
+// mipi_dsih_dphy_shutdown(&(dsi_instance->phy_instance), 0);
+ mipi_dsih_hal_power(dsi_instance, 0);
+
+ return 0;
+}
+
+int32_t sprdfb_dsi_resume(struct sprdfb_device *dev)
+{
+ dsih_ctrl_t* dsi_instance = &(dsi_ctx.dsi_inst);
+#if 0
+ dsih_error_t result = OK;
+ dphy_t *phy = &(dsi_instance->phy_instance);
+ struct info_mipi * mipi = dev->panel->info.mipi;
+#endif
+ printk(KERN_INFO "sprdfb: [%s], dev_id = %d\n",__FUNCTION__, dev->dev_id);
+
+#if 0
+ result = mipi_dsih_dphy_open(&(dsi_instance->phy_instance));
+ if(0 != result){
+ printk("Jessica: mipi_dsih_dphy_open fail!(%d)\n",result);
+ }
+ udelay(100);
+#endif
+// mipi_dsih_dphy_shutdown(&(dsi_instance->phy_instance), 1);
+ mipi_dsih_hal_power(dsi_instance, 1);
+
+#if 0
+ result = mipi_dsih_dphy_configure(phy, mipi->lan_number, mipi->phy_feq);
+ if(OK != result){
+ printk(KERN_ERR "sprdfb: [%s]: mipi_dsih_dphy_configure fail (%d)!\n", __FUNCTION__, result);
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+int32_t sprdfb_dsi_ready(struct sprdfb_device *dev)
+{
+ struct info_mipi * mipi = dev->panel->info.mipi;
+
+ if(SPRDFB_MIPI_MODE_CMD == mipi->work_mode){
+ mipi_dsih_cmd_mode(&(dsi_ctx.dsi_inst), 1);
+#ifdef FB_DSIH_VERSION_1P21A
+ mipi_dsih_dphy_enable_hs_clk(&(dsi_ctx.dsi_inst.phy_instance), true);
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_CMD_MODE_CFG, 0x0);
+#else
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_CMD_MODE_CFG, 0x1);
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PHY_IF_CTRL, 0x1);
+#endif
+ }else{
+#ifdef FB_DSIH_VERSION_1P21A
+ mipi_dsih_dphy_enable_hs_clk(&(dsi_ctx.dsi_inst.phy_instance), true);
+#else
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PHY_IF_CTRL, 0x1);
+#endif
+ mipi_dsih_video_mode(&(dsi_ctx.dsi_inst), 1);
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PWR_UP, 0);
+ udelay(100);
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PWR_UP, 1);
+ usleep_range(3000, 3500);
+#ifdef FB_DSIH_VERSION_1P21A
+ dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_ST0);
+ dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_ST1);
+#else
+ dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_ST0);
+ dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_ST1);
+#endif
+ }
+
+#ifdef FB_DSIH_VERSION_1P21A
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_MSK0, 0x0);
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_INT_MSK1, 0x800);
+#else
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_MSK0, 0x0);
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_ERROR_MSK1, 0x800);
+#endif
+ return 0;
+}
+
+int32_t sprdfb_dsi_before_panel_reset(struct sprdfb_device *dev)
+{
+ sprdfb_dsi_set_lp_mode();
+ return 0;
+}
+
+int32_t sprdfb_dsi_enter_ulps(struct sprdfb_device *dev)
+{
+ sprdfb_dsi_set_ulps_mode();
+ return 0;
+}
+
+uint32_t sprdfb_dsi_get_status(struct sprdfb_device *dev)
+{
+ return dsi_ctx.status;
+}
+
+static int32_t sprdfb_dsi_set_cmd_mode(void)
+{
+ mipi_dsih_cmd_mode(&(dsi_ctx.dsi_inst), 1);
+ return 0;
+}
+
+static int32_t sprdfb_dsi_set_video_mode(void)
+{
+ mipi_dsih_video_mode(&(dsi_ctx.dsi_inst), 1);
+ return 0;
+}
+
+static int32_t sprdfb_dsi_set_lp_mode(void)
+{
+#ifndef FB_DSIH_VERSION_1P21A
+ uint32_t reg_val;
+#endif
+ pr_debug(KERN_INFO "sprdfb: [%s]\n",__FUNCTION__);
+
+ mipi_dsih_cmd_mode(&(dsi_ctx.dsi_inst), 1);
+#ifdef FB_DSIH_VERSION_1P21A
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_CMD_MODE_CFG, 0x01ffff00);
+ mipi_dsih_dphy_enable_hs_clk(&(dsi_ctx.dsi_inst.phy_instance), false);
+#else
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_CMD_MODE_CFG, 0x1fff);
+ reg_val = dsi_core_read_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PHY_IF_CTRL);
+ reg_val = reg_val & (~(BIT(0)));
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PHY_IF_CTRL, reg_val);
+#endif
+ return 0;
+}
+
+static int32_t sprdfb_dsi_set_hs_mode(void)
+{
+ pr_debug(KERN_INFO "sprdfb: [%s]\n",__FUNCTION__);
+
+ mipi_dsih_cmd_mode(&(dsi_ctx.dsi_inst), 1);
+#ifdef FB_DSIH_VERSION_1P21A
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_CMD_MODE_CFG, 0x0);
+ mipi_dsih_dphy_enable_hs_clk(&(dsi_ctx.dsi_inst.phy_instance), true);
+#else
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_CMD_MODE_CFG, 0x1);
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_PHY_IF_CTRL, 0x1);
+#endif
+ return 0;
+}
+
+static int32_t sprdfb_dsi_set_ulps_mode(void)
+{
+ mipi_dsih_ulps_mode(&(dsi_ctx.dsi_inst), 1);
+ return 0;
+}
+
+static int32_t sprdfb_dsi_set_data_lp_mode(void)
+{
+// pr_debug(KERN_INFO "sprdfb: [%s]\n",__FUNCTION__);
+
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_CMD_MODE_CFG, 0x1fff);
+
+ return 0;
+}
+
+static int32_t sprdfb_dsi_set_data_hs_mode(void)
+{
+ int active_mode = mipi_dsih_active_mode(&(dsi_ctx.dsi_inst));
+// pr_debug(KERN_INFO "sprdfb: [%s]\n",__FUNCTION__);
+
+// printk("aoke sprdfb: set data hs mode active_mode=%d\n",active_mode);
+ if(1==active_mode){
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_CMD_MODE_CFG, 0x1);
+ }else{
+ dsi_core_write_function(SPRD_MIPI_DSIC_BASE, R_DSI_HOST_CMD_MODE_CFG, 0x0);
+ }
+ return 0;
+}
+
+static int32_t sprdfb_dsi_gen_write(uint8_t *param, uint16_t param_length)
+{
+ dsih_error_t result;
+
+ result = mipi_dsih_gen_wr_cmd(&(dsi_ctx.dsi_inst), 0, param, param_length);
+ if(OK != result){
+ printk(KERN_ERR "sprdfb: [%s] error (%d)\n", __FUNCTION__, result);
+ return -1;
+ }
+ return 0;
+}
+
+#define LCM_SEND(len) ((1 << 24)| len)
+#define LCM_TAG_MASK ((1 << 24) -1)
+
+static unsigned char set_bl_seq[] = {
+#ifndef CONFIG_MACH_TSHARK2TABE
+ 0x51, 0xFF
+#else
+ 0xF5, 0x8B
+#endif
+};
+
+void backlight_control(int brigtness)
+{
+ set_bl_seq[1] = brigtness;
+ sprdfb_dsi_gen_write(set_bl_seq, LCM_SEND(2) & LCM_TAG_MASK);
+}
+EXPORT_SYMBOL(backlight_control);
+
+
+static int32_t sprdfb_dsi_gen_read(uint8_t *param, uint16_t param_length, uint8_t bytes_to_read, uint8_t *read_buffer)
+{
+ uint16_t result;
+ uint32_t reg_val, reg_val_1, reg_val_2;
+ result = mipi_dsih_gen_rd_cmd(&(dsi_ctx.dsi_inst), 0, param, param_length, bytes_to_read, read_buffer);
+
+ reg_val = dispc_glb_read(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_PHY_STATUS);
+#ifdef FB_DSIH_VERSION_1P21A
+ reg_val_1 = dispc_glb_read(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_INT_ST0);
+ reg_val_2 = dispc_glb_read(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_INT_ST1);
+#else
+ reg_val_1 = dispc_glb_read(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_ERROR_ST0);
+ reg_val_2 = dispc_glb_read(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_ERROR_ST1);
+#endif
+ if(0 != (reg_val & 0x2)){
+ printk("sprdfb: [%s] mipi read hang (0x%x)!\n", __FUNCTION__, reg_val);
+ dsi_ctx.status = 2;
+ result = 0;
+ }
+
+ if(0 != (reg_val_1 & 0x701)){
+ printk("sprdfb: [%s] mipi read status error!(0x%x, 0x%x)\n", __FUNCTION__, reg_val_1, reg_val_2);
+ result = 0;
+ }
+
+ if(0 == result){
+ printk(KERN_ERR "sprdfb: [%s] return error (%d)\n", __FUNCTION__, result);
+ return -1;
+ }
+ return 0;
+}
+
+static int32_t sprdfb_dsi_dcs_write(uint8_t *param, uint16_t param_length)
+{
+ dsih_error_t result;
+ result = mipi_dsih_dcs_wr_cmd(&(dsi_ctx.dsi_inst), 0, param, param_length);
+ if(OK != result){
+ printk(KERN_ERR "sprdfb: [%s] error (%d)\n", __FUNCTION__, result);
+ return -1;
+ }
+ return 0;
+}
+
+static int32_t sprdfb_dsi_dcs_read(uint8_t command, uint8_t bytes_to_read, uint8_t *read_buffer)
+{
+ uint16_t result;
+ uint32_t reg_val, reg_val_1, reg_val_2;
+
+ result = mipi_dsih_dcs_rd_cmd(&(dsi_ctx.dsi_inst), 0, command, bytes_to_read, read_buffer);
+ reg_val = dispc_glb_read(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_PHY_STATUS);
+#ifdef FB_DSIH_VERSION_1P21A
+ reg_val_1 = dispc_glb_read(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_INT_ST0);
+ reg_val_2 = dispc_glb_read(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_INT_ST1);
+#else
+ reg_val_1 = dispc_glb_read(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_ERROR_ST0);
+ reg_val_2 = dispc_glb_read(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_ERROR_ST1);
+#endif
+ if(0 != (reg_val & 0x2)){
+ printk("sprdfb: [%s] mipi read hang (0x%x)!\n", __FUNCTION__, reg_val);
+ dsi_ctx.status = 2;
+ result = 0;
+ }
+
+ if(0 != (reg_val_1 & 0x701)){
+ printk("sprdfb: [%s] mipi read status error!(0x%x, 0x%x)\n", __FUNCTION__, reg_val_1, reg_val_2);
+ result = 0;
+ }
+
+ if(0 == result){
+ printk(KERN_ERR "sprdfb: [%s] return error (%d)\n", __FUNCTION__, result);
+ return -1;
+ }
+ return 0;
+}
+
+static int32_t sprd_dsi_force_write(uint8_t data_type, uint8_t *p_params, uint16_t param_length)
+{
+ int32_t iRtn = 0;
+
+ iRtn = mipi_dsih_gen_wr_packet(&(dsi_ctx.dsi_inst), 0, data_type, p_params, param_length);
+
+ return iRtn;
+}
+
+static int32_t sprd_dsi_force_read(uint8_t command, uint8_t bytes_to_read, uint8_t * read_buffer)
+{
+ int32_t iRtn = 0;
+ uint32_t reg_val, reg_val_1, reg_val_2;
+
+ iRtn = mipi_dsih_gen_rd_packet(&(dsi_ctx.dsi_inst), 0, 6, 0, command, bytes_to_read, read_buffer);
+
+ reg_val = dispc_glb_read(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_PHY_STATUS);
+#ifdef FB_DSIH_VERSION_1P21A
+ reg_val_1 = dispc_glb_read(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_INT_ST0);
+ reg_val_2 = dispc_glb_read(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_INT_ST1);
+#else
+ reg_val_1 = dispc_glb_read(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_ERROR_ST0);
+ reg_val_2 = dispc_glb_read(SPRD_MIPI_DSIC_BASE + R_DSI_HOST_ERROR_ST1);
+#endif
+ if(0 != (reg_val & 0x2)){
+ printk("sprdfb: [%s] mipi read hang (0x%x)!\n", __FUNCTION__, reg_val);
+ dsi_ctx.status = 2;
+ iRtn = 0;
+ }
+
+ if(0 != (reg_val_1 & 0x701)){
+ printk("sprdfb: [%s] mipi read status error!(0x%x, 0x%x)\n", __FUNCTION__, reg_val_1, reg_val_2);
+ iRtn = 0;
+ }
+
+
+ if(0 == iRtn){
+ printk(KERN_ERR "sprdfb: [%s] return error (%d)\n", __FUNCTION__, iRtn);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int32_t sprd_dsi_eotp_set(uint8_t rx_en, uint8_t tx_en)
+{
+ dsih_ctrl_t *curInstancePtr = &(dsi_ctx.dsi_inst);
+ if(0 == rx_en)
+ mipi_dsih_eotp_rx(curInstancePtr, 0);
+ else if(1 == rx_en)
+ mipi_dsih_eotp_rx(curInstancePtr, 1);
+ if(0 == tx_en)
+ mipi_dsih_eotp_tx(curInstancePtr, 0);
+ else if(1 == tx_en)
+ mipi_dsih_eotp_tx(curInstancePtr, 1);
+ return 0;
+}
+
+struct ops_mipi sprdfb_mipi_ops = {
+ .mipi_set_cmd_mode = sprdfb_dsi_set_cmd_mode,
+ .mipi_set_video_mode = sprdfb_dsi_set_video_mode,
+ .mipi_set_lp_mode = sprdfb_dsi_set_lp_mode,
+ .mipi_set_hs_mode = sprdfb_dsi_set_hs_mode,
+ .mipi_set_data_lp_mode = sprdfb_dsi_set_data_lp_mode,
+ .mipi_set_data_hs_mode = sprdfb_dsi_set_data_hs_mode,
+ .mipi_gen_write = sprdfb_dsi_gen_write,
+ .mipi_gen_read = sprdfb_dsi_gen_read,
+ .mipi_dcs_write = sprdfb_dsi_dcs_write,
+ .mipi_dcs_read = sprdfb_dsi_dcs_read,
+ .mipi_force_write = sprd_dsi_force_write,
+ .mipi_force_read = sprd_dsi_force_read,
+ .mipi_eotp_set = sprd_dsi_eotp_set,
+};
+
+
+