From 4c9e1d535cc0074da7f39ea5e0f9d27d3d449c9d Mon Sep 17 00:00:00 2001
From: yzq <yzq@rockchips.com>
Date: Mon, 23 Jul 2012 17:47:06 +0800
Subject: [PATCH] rk2928 lvds support

---
 drivers/video/rockchip/Kconfig             |  1 +
 drivers/video/rockchip/Makefile            |  1 +
 drivers/video/rockchip/chips/rk2928_lcdc.c | 12 ++-
 drivers/video/rockchip/lvds/Kconfig        |  2 +
 drivers/video/rockchip/lvds/Makefile       |  6 ++
 drivers/video/rockchip/lvds/rk_lvds.c      | 58 ++++++++++++++
 drivers/video/rockchip/lvds/rk_lvds.h      | 93 ++++++++++++++++++++++
 7 files changed, 172 insertions(+), 1 deletion(-)
 create mode 100755 drivers/video/rockchip/lvds/Kconfig
 create mode 100755 drivers/video/rockchip/lvds/Makefile
 create mode 100644 drivers/video/rockchip/lvds/rk_lvds.c
 create mode 100644 drivers/video/rockchip/lvds/rk_lvds.h

diff --git a/drivers/video/rockchip/Kconfig b/drivers/video/rockchip/Kconfig
index 04ba7263c5ac..267b5b5a222e 100755
--- a/drivers/video/rockchip/Kconfig
+++ b/drivers/video/rockchip/Kconfig
@@ -75,3 +75,4 @@ config THREE_FB_BUFFER
 	   select y if android support three buffer,like Jelly Bean
 source "drivers/video/rockchip/hdmi/Kconfig"
 source "drivers/video/rockchip/rga/Kconfig"
+source "drivers/video/rockchip/lvds/Kconfig"
diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile
index 68967a49fc80..0f1a3880879e 100755
--- a/drivers/video/rockchip/Makefile
+++ b/drivers/video/rockchip/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_LCDC_RK2928) += chips/rk2928_lcdc.o
 obj-$(CONFIG_LCDC_RK31) += chips/rk31_lcdc.o 
 obj-$(CONFIG_RGA_RK30) += rga/
 obj-$(CONFIG_RK_HDMI) += hdmi/
+obj-$(CONFIG_RK_LVDS) += lvds/
diff --git a/drivers/video/rockchip/chips/rk2928_lcdc.c b/drivers/video/rockchip/chips/rk2928_lcdc.c
index 5298a8e98291..71146072f545 100755
--- a/drivers/video/rockchip/chips/rk2928_lcdc.c
+++ b/drivers/video/rockchip/chips/rk2928_lcdc.c
@@ -31,7 +31,7 @@
 #include <asm/div64.h>
 #include <asm/uaccess.h>
 #include "rk2928_lcdc.h"
-
+#include "../lvds/rk_lvds.h"
 
 
 
@@ -68,6 +68,10 @@ static int init_rk2928_lcdc(struct rk_lcdc_device_driver *dev_drv)
     	{
        		printk(KERN_ERR "failed to get lcdc%d clk source\n",lcdc_dev->id);
    	}
+#ifdef CONFIG_RK_LVDS
+	rk_lvds_register(lcdc_dev->screen);
+#endif
+
 	clk_enable(lcdc_dev->pd);
 	clk_enable(lcdc_dev->hclk);  //enable aclk and hclk for register config
 	clk_enable(lcdc_dev->aclk);  
@@ -685,6 +689,9 @@ int rk2928_lcdc_early_suspend(struct rk_lcdc_device_driver *dev_drv)
 {
 	struct rk2928_lcdc_device *lcdc_dev = container_of(dev_drv,struct rk2928_lcdc_device,driver);
 	
+	if(lcdc_dev->screen->sscreen_set != NULL)
+		lcdc_dev->screen->sscreen_set(lcdc_dev->screen , 0);
+
 	spin_lock(&lcdc_dev->reg_lock);
 	if(likely(lcdc_dev->clk_on))
 	{
@@ -733,6 +740,9 @@ int rk2928_lcdc_early_resume(struct rk_lcdc_device_driver *dev_drv)
 	lcdc_dev->clk_on = 1;
 	spin_unlock(&lcdc_dev->reg_lock);
 	
+	if(lcdc_dev->screen->sscreen_set != NULL)
+		lcdc_dev->screen->sscreen_set(lcdc_dev->screen , 1);
+
     	return 0;
 }
 static irqreturn_t rk2928_lcdc_isr(int irq, void *dev_id)
diff --git a/drivers/video/rockchip/lvds/Kconfig b/drivers/video/rockchip/lvds/Kconfig
new file mode 100755
index 000000000000..1577242cb924
--- /dev/null
+++ b/drivers/video/rockchip/lvds/Kconfig
@@ -0,0 +1,2 @@
+config RK_LVDS
+       bool "RK_LVDS support"
diff --git a/drivers/video/rockchip/lvds/Makefile b/drivers/video/rockchip/lvds/Makefile
new file mode 100755
index 000000000000..f410fda78ee1
--- /dev/null
+++ b/drivers/video/rockchip/lvds/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for LVDS linux kernel module.
+#
+
+
+obj-$(CONFIG_RK_LVDS) += rk_lvds.o 
diff --git a/drivers/video/rockchip/lvds/rk_lvds.c b/drivers/video/rockchip/lvds/rk_lvds.c
new file mode 100644
index 000000000000..0fd1656120cb
--- /dev/null
+++ b/drivers/video/rockchip/lvds/rk_lvds.c
@@ -0,0 +1,58 @@
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <asm/io.h>
+#include <mach/io.h>
+#include <linux/rk_screen.h>
+#include "rk_lvds.h"
+
+static void rk_output_lvds(rk_screen *screen)
+{
+	LVDSWrReg(m_PD_PLL(1)|m_PD_PLL(0)|m_PDN(1)|m_OEN(0) 	\
+					|m_DS(DS_10PF)|m_MSBSEL(DATA_D0_MSB) 	\
+					|m_OUT_FORMAT(screen->hw_format) 		\
+					|m_LCDC_SEL(FROM_LCDC0));
+}
+
+static void rk_output_lvttl(rk_screen *screen)
+{
+	LVDSWrReg(m_PD_PLL(0)|m_PD_PLL(1)|m_PDN(0)|m_OEN(1) 	\
+					|m_DS(DS_10PF)|m_MSBSEL(DATA_D0_MSB) 	\
+					|m_OUT_FORMAT(screen->hw_format) 		\
+					|m_LCDC_SEL(FROM_LCDC0));
+}
+
+static void rk_output_disable(void)
+{
+	LVDSWrReg(m_PD_PLL(0)|m_PD_PLL(0)|m_PDN(0)|m_OEN(0));
+}
+
+static int rk_lvds_set_param(rk_screen *screen,bool enable )
+{
+	if(OUT_ENABLE == enable){
+		switch(screen->type){
+			case SCREEN_LVDS:
+					rk_output_lvds(screen);
+					break;
+			case SCREEN_RGB:
+					rk_output_lvttl(screen);
+					break;
+			default:
+				printk("%s>>>>LVDS not support this screen type %d,power down LVDS\n",__func__,screen->type);
+					rk_output_disable();
+					break;
+		}
+	}else{
+		rk_output_disable();
+	}
+	return 0;
+}
+
+int rk_lvds_register(rk_screen *screen)
+{
+	if(screen->sscreen_set == NULL)
+		screen->sscreen_set = rk_lvds_set_param;
+
+	rk_lvds_set_param(screen , OUT_ENABLE);
+
+	return 0;
+}
diff --git a/drivers/video/rockchip/lvds/rk_lvds.h b/drivers/video/rockchip/lvds/rk_lvds.h
new file mode 100644
index 000000000000..3916fad54a90
--- /dev/null
+++ b/drivers/video/rockchip/lvds/rk_lvds.h
@@ -0,0 +1,93 @@
+#ifndef RK_LVDS_H_
+#define RK_LVDS_H
+
+#define LVDS_CON0_OFFSET 	0x150
+#define LVDS_CON0_REG 		(RK2928_GRF_PHYS + LVDS_CON0_OFFSET) 
+
+#define LVDSRdReg()					__raw_readl(LVDS_CON0_REG)
+#define LVDSWrReg(val)       	__raw_writel( val ,LVDS_CON0_REG)
+
+#define m_value(x,offset,mask)      \
+			((mask<<(offset+8)) | (x&mask)<<offset)
+
+#define OEN 				(1<<9)
+#define m_OEN(x)   			m_value(x,9,1)
+#define PD_PLL 				(1<<8)
+#define m_PD_PLL(x) 		m_value(x,8,1)
+#define PDN_CBG 			(1<<7)
+#define m_PDN_CBG(x)		m_value(x,7,1)
+#define PDN 				(1<<6)
+#define m_PDN(x) 			m_value(x,6,1)
+#define DS 					(3<<4)
+#define m_DS(x) 			m_value(x,4,3)
+#define MSBSEL				(1<<3)
+#define m_MSBSEL(x)			m_value(x,3,1)
+#define OUT_FORMAT			(3<<1)
+#define m_OUT_FORMAT(x) 	m_value(x,1,3)
+#define LCDC_SEL			(1<<0)
+#define m_LCDC_SEL(x)		m_value(x,0,1)
+
+enum{
+	OUT_DISABLE=0,
+	OUT_ENABLE,
+};
+
+//DS
+#define DS_3PF 			0
+#define DS_7PF 			0
+#define DS_5PF 			0
+#define DS_10PF			0
+
+//LVDS lane input format
+#define DATA_D0_MSB    	0
+#define DATA_D7_MSB    	1
+//LVDS input source
+#define FROM_LCDC0     	0
+#define FROM_LCDC1 		1
+
+
+#define LVDS_8BIT_1     0x00
+#define LVDS_8BIT_2     0x01
+#define LVDS_8BIT_3     0x10
+#define LVDS_6BIT       0x11
+/*      				LVDS config         
+ *                  LVDS 外部连线接法                       
+ *          LVDS_8BIT_1    LVDS_8BIT_2     LVDS_8BIT_3     LVDS_6BIT
+----------------------------------------------------------------------
+    TX0     R0              R2              R2              R0
+    TX1     R1              R3              R3              R1
+    TX2     R2              R4              R4              R2
+Y   TX3     R3              R5              R5              R3
+0   TX4     R4              R6              R6              R4
+    TX6     R5              R7              R7              R5
+    TX7     G0              G2              G2              G0
+----------------------------------------------------------------------
+    TX8     G1              G3              G3              G1
+    TX9     G2              G4              G4              G2
+Y   TX12    G3              G5              G5              G3
+1   TX13    G4              G6              G6              G4
+    TX14    G5              G7              G7              G5
+    TX15    B0              B2              B2              B0
+    TX18    B1              B3              B3              B1
+----------------------------------------------------------------------
+    TX19    B2              B4              B4              B2
+    TX20    B3              B5              B5              B3
+    TX21    B4              B6              B6              B4
+Y   TX22    B5              B7              B7              B5
+2   TX24    HSYNC           HSYNC           HSYNC           HSYNC
+    TX25    VSYNC           VSYNC           VSYNC           VSYNC
+    TX26    ENABLE          ENABLE          ENABLE          ENABLE
+----------------------------------------------------------------------    
+    TX27    R6              R0              GND             GND
+    TX5     R7              R1              GND             GND
+    TX10    G6              G0              GND             GND
+Y   TX11    G7              G1              GND             GND
+3   TX16    B6              B0              GND             GND
+    TX17    B7              B1              GND             GND
+    TX23    RSVD            RSVD            RSVD            RSVD
+----------------------------------------------------------------------
+*/
+
+
+extern int rk_lvds_register(rk_screen *screen);
+#endif
-- 
2.34.1