lvds: add rk319x lvds
authorZHW <zhw@rock-chips.com>
Thu, 26 Dec 2013 12:56:00 +0000 (20:56 +0800)
committeryxj <yxj@rock-chips.com>
Thu, 13 Mar 2014 03:27:51 +0000 (11:27 +0800)
drivers/video/rockchip/transmitter/Kconfig
drivers/video/rockchip/transmitter/Makefile
drivers/video/rockchip/transmitter/rk319x_lvds.c [new file with mode: 0755]
drivers/video/rockchip/transmitter/rk319x_lvds.h [new file with mode: 0755]

index 2c3cd8e8d8e4565563e590cbca96700c8274260f..23f5f07a471c36de849f4b996acc2fc2dd47cb7e 100644 (file)
@@ -12,6 +12,10 @@ config RK3026_LVDS
        bool "RK3026/RK3028A lvds transmitter support"
        default y       
 
+config RK319x_LVDS
+       bool "RK319x lvds transmitter support"
+       depends on ARCH_RK319X && RK_TRSM
+
 config RK610_LVDS
        bool "RK610(Jetta) lvds transmitter support"
        depends on MFD_RK610 && RK_TRSM 
index c098ef3ecf3d490618634d61ed3b4e8cb1755caa..63b085a726931f6c7cae2fc0051b4932ac3e7f34 100644 (file)
@@ -5,6 +5,7 @@ obj-$(CONFIG_RK2928_LVDS)       += rk2928_lvds.o
 obj-$(CONFIG_RK3026_LVDS)       += rk3026_lvds.o
 obj-$(CONFIG_RK610_LVDS)       += rk610_lcd.o
 obj-$(CONFIG_RK616_LVDS)        += rk616_lvds.o
+obj-$(CONFIG_RK319x_LVDS)       += rk319x_lvds.o
 obj-$(CONFIG_DP_ANX6345)        += dp_anx6345.o
 obj-$(CONFIG_DP501)            += dp501.o
 obj-$(CONFIG_RK32_DP)          += rk32_dp.o rk32_dp_reg.o
diff --git a/drivers/video/rockchip/transmitter/rk319x_lvds.c b/drivers/video/rockchip/transmitter/rk319x_lvds.c
new file mode 100755 (executable)
index 0000000..c1b82bc
--- /dev/null
@@ -0,0 +1,247 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/rk_fb.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#include <mach/board.h>
+#include <mach/hardware.h>
+#include <mach/io.h>
+#include <mach/gpio.h>
+#include <mach/iomux.h>
+#include <linux/earlysuspend.h>
+
+#include "rk319x_lvds.h"
+
+#define grf_readl(offset)      readl_relaxed(RK30_GRF_BASE + offset)
+#define grf_writel(v,offset)   do{ writel_relaxed(v, RK30_GRF_BASE + offset);dsb();} while (0)
+
+#define lvds_readl(addr)       readl_relaxed(addr)
+#define lvds_writel(v,addr)    do{ writel_relaxed(v, addr);dsb();} while (0)
+
+static struct early_suspend early_suspend;
+static char *virt_reg_addr;
+
+void rk_dump_clock_info(void);
+void  rk30_clk_dump_regs(void);
+
+
+static void rk319x_output_lvds(rk_screen *screen)
+{
+       u32 val =0;
+
+       /*reset lvds*/
+       //lvds_writel(0x0,virt_reg_addr+MIPIPHY_REGE0);
+       //msleep(500);
+
+       val = 0;
+       val |= LVDS_MODE(1); /*enable lvds mode*/
+       val |= LVDS_SEL_LCDC(screen->lcdc_id); /* configure lvds source*/
+       val |= LVDS_OUTPUT_FORMAT(screen->lvds_format); /*configure lvds_format*/
+       val |= LVDS_MSBSEL(1);//LSB mode        
+       grf_writel(val,GRF_SOC_CON4);   
+
+
+       lvds_writel(0x7c,virt_reg_addr+MIPIPHY_REG0);//enable lvds lane
+       lvds_writel(0x2,virt_reg_addr+MIPIPHY_REG3);//set lvds pll prediv fbdiv[8]
+       lvds_writel(0x1c,virt_reg_addr+MIPIPHY_REG4);//set lvds pll fbdiv[7:0]
+       lvds_writel(0x25,virt_reg_addr+MIPIPHY_REGE0);//lvds mode
+       lvds_writel(0xa0,virt_reg_addr+MIPIPHY_REGE2);//timing
+       lvds_writel(0xfc,virt_reg_addr+MIPIPHY_REGE7);//phase
+       lvds_writel(0xf8,virt_reg_addr+MIPIPHY_REGEA);//power up lvds_pllpd
+
+       /* enable lvds*/
+       val = 0;
+       val |= LVDS_ENABLE(1);
+       grf_writel(val,GRF_SOC_CON8);
+       
+       return;
+}
+
+static void rk319x_output_lvttl(rk_screen *screen)
+{
+       return;                 
+}
+
+static void rk319x_output_disable(void)
+{      
+       u32 val =0;
+
+       val = 0;
+       val |= LVDS_MODE(0); 
+       grf_writel(val,GRF_SOC_CON4);
+
+       val = 0;        
+       val |= LVDS_ENABLE(0);
+       grf_writel(val,GRF_SOC_CON8);   
+
+       return;
+}
+
+
+static int rk319x_lvds_set_param(rk_screen *screen,bool enable)
+{
+
+       if(OUT_ENABLE == enable){
+               switch(screen->type){
+                       case SCREEN_LVDS:
+                               printk("%s>>>>LVDS Enable %d,power down LVDS\n",__func__,screen->type);
+                               rk319x_output_lvds(screen);                                       
+                               break;
+                       case SCREEN_RGB:
+                               rk319x_output_lvttl(screen);
+                               break;
+                       default:
+                               printk("%s>>>>LVDS not support this screen type %d,power down LVDS\n",__func__,screen->type);
+                               rk319x_output_disable();
+                               break;
+               }
+       }else{
+                               printk("%s>>>>LVDS  %d,power down LVDS\n",__func__,screen->type);
+               rk319x_output_disable();
+       }
+       return 0;
+}
+
+static void lvds_early_suspend(struct early_suspend *handler)
+{
+       rk_screen *screen = NULL;
+       screen = rk_fb_get_prmry_screen();
+       if(!screen)
+       {
+               printk(KERN_ERR,"the fb prmry screen is null!\n");
+               return -ENODEV;
+       }
+       
+       rk319x_lvds_set_param(screen,OUT_DISABLE);
+
+        return;
+
+}
+static void lvds_late_resume(struct early_suspend *handler)
+{
+       rk_screen *screen = NULL;
+       screen = rk_fb_get_prmry_screen();
+       if(!screen)
+       {
+               printk(KERN_ERR,"the fb prmry screen is null!\n");
+               return -ENODEV;
+       }
+       
+       rk319x_lvds_set_param(screen,OUT_ENABLE);
+
+return;
+}
+
+static int init_clk()
+{
+       int ret = 0;
+       struct clk *refclk,*dsi_pclk,*dsi_pd,*mipiphy_dsi;
+
+       refclk = clk_get(NULL, "mipi_ref");
+        if (unlikely(IS_ERR(refclk))) {
+                ret = PTR_ERR(refclk);
+               printk("%s %d \n",__func__,__LINE__);
+               return -1;
+        }
+
+       dsi_pclk = clk_get(NULL, "pclk_mipi_dsi");
+        if (unlikely(IS_ERR(dsi_pclk))) {
+                ret = PTR_ERR(dsi_pclk);
+               printk("%s %d \n",__func__,__LINE__);
+               return -1;
+        }
+
+       mipiphy_dsi = clk_get(NULL, "pclk_mipiphy_dsi");
+       if (unlikely(IS_ERR(mipiphy_dsi))) {
+                ret = PTR_ERR(mipiphy_dsi);
+               printk("%s %d \n",__func__,__LINE__);
+               return -1;
+        }
+       
+        dsi_pd = clk_get(NULL, "pd_mipi_dsi");
+        if (unlikely(IS_ERR(dsi_pd))) {
+                ret = PTR_ERR(dsi_pd);
+               printk("%s %d \n",__func__,__LINE__);
+               return -1;
+        }
+
+        clk_enable(dsi_pd);
+        clk_enable(dsi_pclk);
+       clk_enable(mipiphy_dsi);
+       clk_enable(refclk);
+
+       return 0;       
+}
+
+
+static int rk319x_lvds_probe(struct platform_device *pdev)
+{
+       int ret = 0;
+       rk_screen *screen = NULL;
+       
+       screen = rk_fb_get_prmry_screen();
+       if(!screen)
+       {
+               dev_err(&pdev->dev,"the fb prmry screen is null!\n");
+               return -ENODEV;
+       }
+
+       ret = init_clk();
+       if(ret < 0)
+               return -1;
+
+       virt_reg_addr = ioremap(RK319X_MIPI_DSI_PHY_PHYS,RK319X_MIPI_DSI_PHY_SIZE);
+       if(virt_reg_addr == NULL)
+               return -1;      
+
+
+       rk319x_lvds_set_param(screen,OUT_ENABLE);
+
+       early_suspend.suspend = lvds_early_suspend,
+       early_suspend.resume = lvds_late_resume,
+       early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 20,
+       register_early_suspend(&early_suspend);
+
+       return 0;
+       
+}
+
+static int rk319x_lvds_remove(struct platform_device *pdev)
+{      
+       return 0;
+}
+
+static void rk319x_lvds_shutdown(struct platform_device *pdev)
+{
+       return;
+}
+
+static struct platform_driver rk319x_lvds_driver = {
+       .driver         = {
+               .name   = "rk319x-lvds",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = rk319x_lvds_probe,
+       .remove         = rk319x_lvds_remove,
+       .shutdown       = rk319x_lvds_shutdown,
+};
+
+static int __init rk319x_lvds_init(void)
+{
+       return platform_driver_register(&rk319x_lvds_driver);
+}
+fs_initcall(rk319x_lvds_init);
+static void __exit rk319x_lvds_exit(void)
+{
+       platform_driver_unregister(&rk319x_lvds_driver);
+}
+module_exit(rk319x_lvds_exit);
+
+
+
diff --git a/drivers/video/rockchip/transmitter/rk319x_lvds.h b/drivers/video/rockchip/transmitter/rk319x_lvds.h
new file mode 100755 (executable)
index 0000000..a1bf3af
--- /dev/null
@@ -0,0 +1,28 @@
+#include<linux/rk_screen.h>
+
+#define ENABLE 16
+
+#define GRF_SOC_CON4                   0x0070
+#define LVDS_SEL_LCDC(x)       ((((x)&1)<<2)|(1<<(2+ENABLE)))
+#define LVDS_MODE(x)           ((((x)&1)<<3)|(1<<(3+ENABLE)))
+#define LVDS_OUTPUT_FORMAT(x)   ((((x)&3)<<4)|(3<<(4+ENABLE)))
+#define LVDS_MSBSEL(x)         ((((x)&1)<<6)|(1<<(6+ENABLE)))
+
+#define GRF_SOC_CON8           0x013c
+#define LVDS_ENABLE(x)                 ((((x)&1)<<7)|(1<<(7+ENABLE)))
+
+#define MIPIPHY_REG0           0x0000
+#define MIPIPHY_REG3           0x000c
+#define MIPIPHY_REG4           0x0010
+#define MIPIPHY_REGE0          0x0380
+#define MIPIPHY_REGEA          0x03A8
+#define MIPIPHY_REGE2          0x0388
+#define MIPIPHY_REGE7          0x039C
+
+
+
+enum{
+       OUT_DISABLE=0,
+       OUT_ENABLE,
+};
+