lvds: add rk319x lvds

This commit is contained in:
ZHW
2013-12-26 20:56:00 +08:00
committed by yxj
parent b992ababc8
commit 46f66629d7
4 changed files with 280 additions and 0 deletions

View 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

View 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

View File

@@ -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);

View File

@@ -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,
};