From 46f66629d7db9336a95e56bb2007107174392b3a Mon Sep 17 00:00:00 2001 From: ZHW Date: Thu, 26 Dec 2013 20:56:00 +0800 Subject: [PATCH] lvds: add rk319x lvds --- drivers/video/rockchip/transmitter/Kconfig | 4 + drivers/video/rockchip/transmitter/Makefile | 1 + .../video/rockchip/transmitter/rk319x_lvds.c | 247 ++++++++++++++++++ .../video/rockchip/transmitter/rk319x_lvds.h | 28 ++ 4 files changed, 280 insertions(+) create mode 100755 drivers/video/rockchip/transmitter/rk319x_lvds.c create mode 100755 drivers/video/rockchip/transmitter/rk319x_lvds.h diff --git a/drivers/video/rockchip/transmitter/Kconfig b/drivers/video/rockchip/transmitter/Kconfig index 2c3cd8e8d8e4..23f5f07a471c 100644 --- a/drivers/video/rockchip/transmitter/Kconfig +++ b/drivers/video/rockchip/transmitter/Kconfig @@ -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 diff --git a/drivers/video/rockchip/transmitter/Makefile b/drivers/video/rockchip/transmitter/Makefile index c098ef3ecf3d..63b085a72693 100644 --- a/drivers/video/rockchip/transmitter/Makefile +++ b/drivers/video/rockchip/transmitter/Makefile @@ -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 index 000000000000..c1b82bc5c9c0 --- /dev/null +++ b/drivers/video/rockchip/transmitter/rk319x_lvds.c @@ -0,0 +1,247 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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 index 000000000000..a1bf3afac085 --- /dev/null +++ b/drivers/video/rockchip/transmitter/rk319x_lvds.h @@ -0,0 +1,28 @@ +#include + +#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, +}; + -- 2.34.1