rk2928 hdmi support
authoryzq <yzq@rockchips.com>
Fri, 20 Jul 2012 09:04:55 +0000 (17:04 +0800)
committeryzq <yzq@rockchips.com>
Fri, 20 Jul 2012 09:05:38 +0000 (17:05 +0800)
44 files changed:
arch/arm/mach-rk2928/devices.c
drivers/video/Kconfig
drivers/video/rockchip/Makefile
drivers/video/rockchip/hdmi/Kconfig
drivers/video/rockchip/hdmi/Makefile
drivers/video/rockchip/hdmi/chips/Kconfig [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/Makefile [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk2928/Kconfig [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk2928/Makefile [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk2928/hdcp/Kconfig [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk2928/hdcp/Makefile [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdcp.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdmi_hdcp.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdmi_hdcp.h [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi.h [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hw.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hw.h [new file with mode: 0644]
drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hw.hbak [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk30/Kconfig [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk30/Makefile [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk30/hdcp/Kconfig [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk30/hdcp/Makefile [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk30/hdcp/rk30_hdcp.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk30/hdcp/rk30_hdmi_hdcp.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk30/hdcp/rk30_hdmi_hdcp.h [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi.h [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi_hw.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi_hw.h [new file with mode: 0755]
drivers/video/rockchip/hdmi/rk30_hdmi.c [deleted file]
drivers/video/rockchip/hdmi/rk30_hdmi.h [deleted file]
drivers/video/rockchip/hdmi/rk30_hdmi_edid.c [deleted file]
drivers/video/rockchip/hdmi/rk30_hdmi_hw.c [deleted file]
drivers/video/rockchip/hdmi/rk30_hdmi_hw.h [deleted file]
drivers/video/rockchip/hdmi/rk30_hdmi_lcdc.c [deleted file]
drivers/video/rockchip/hdmi/rk30_hdmi_sysfs.c [deleted file]
drivers/video/rockchip/hdmi/rk30_hdmi_task.c [deleted file]
drivers/video/rockchip/hdmi/rk_hdmi.h
drivers/video/rockchip/hdmi/rk_hdmi_core.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/rk_hdmi_edid.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/rk_hdmi_task.c [new file with mode: 0755]

index d90a8055eec804f6681e5b508c5cb58191312066..21e24335a532bb034266543afacf54d6200df8e2 100755 (executable)
@@ -522,6 +522,28 @@ static void __init rk2928_init_spim(void)
        platform_device_register(&rk29xx_device_spi0m);
 #endif
 }
+
+#ifdef CONFIG_HDMI_RK2928
+static struct resource resource_hdmi[] = {
+       [0] = {
+               .start = RK2928_HDMI_PHYS,
+               .end   = RK2928_HDMI_PHYS + RK2928_HDMI_SIZE - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_HDMI,
+               .end   = IRQ_HDMI,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device device_hdmi = {
+       .name                           = "rk2928-hdmi",
+       .id                                     = -1,
+       .num_resources          = ARRAY_SIZE(resource_hdmi),
+       .resource                       = resource_hdmi,
+};
+#endif
 #ifdef CONFIG_RGA_RK30
 static struct resource resource_rga[] = {
        [0] = {
index b4117f636264afd75ab26e5d77a0da99db5c9201..47d5735793ba4f11a391c2205ef5817772f274a0 100755 (executable)
@@ -2438,7 +2438,11 @@ source "drivers/video/omap2/Kconfig"
 
 source "drivers/video/backlight/Kconfig"
 source "drivers/video/display/Kconfig"
+
+if !LCDC_RK30 && !LCDC_RK2928
 source "drivers/video/hdmi/Kconfig"
+endif
+
 source "drivers/video/rockchip/Kconfig"
 
 if VT
index ed778bb77b99687947d2338de75b580e590fa5b1..68967a49fc80e9afc2dd727e9eaf09e11ace69ce 100755 (executable)
@@ -4,4 +4,4 @@ obj-$(CONFIG_LCDC_RK30) += chips/rk30_lcdc.o
 obj-$(CONFIG_LCDC_RK2928) += chips/rk2928_lcdc.o
 obj-$(CONFIG_LCDC_RK31) += chips/rk31_lcdc.o 
 obj-$(CONFIG_RGA_RK30) += rga/
-obj-$(CONFIG_HDMI_RK30) += hdmi/
+obj-$(CONFIG_RK_HDMI) += hdmi/
index 654bfa0e67dbea656b7e2381a27eaaacbbcd13a5..e3700bbd817d45c7525b7d150ac9529a83fa3147 100755 (executable)
@@ -1,23 +1,9 @@
-menuconfig HDMI_RK30
-        bool "RK30 HDMI support"
-        depends on LCDC_RK30
-        select FB_MODE_HELPERS
-        help
-           Support rk30 hdmi if you say y here
+menu "RK_HDMI"
+config RK_HDMI
+       bool "RK_HDMI support"
+       
+if RK_HDMI
+source "drivers/video/rockchip/hdmi/chips/Kconfig"
+endif
 
-config HDMI_RK30_CTL_CODEC
-               bool "Mute Codec When HDMI Actived"
-               depends on HDMI_RK30
-               default n
-               help
-                       If you say y heres, Codec will be mute when hdmi inserted,
-                       and unmute when removed. 
-
-config HDMI_RK30_DEBUG
-               bool "RK30 HDMI Debugging"
-        depends on HDMI_RK30 && LCDC_RK30
-        default n
-               help
-                 Enableds verbose debugging the the HDMI drivers
-
-source "drivers/video/rockchip/hdmi/hdcp/Kconfig"
\ No newline at end of file
+endmenu
index 4692311dbd9a8725e8f81658415570d206ac2853..ed00a162460d8f4bb42023778bd372f4ad288d52 100755 (executable)
@@ -2,7 +2,7 @@
 # Makefile for HDMI linux kernel module.
 #
 
-ccflags-$(CONFIG_HDMI_RK30_DEBUG) = -DDEBUG -DHDMI_DEBUG
+ccflags-$(CONFIG_RK_HDMI_DEBUG) = -DDEBUG -DHDMI_DEBUG
 
-obj-$(CONFIG_HDMI_RK30) += rk30_hdmi_hw.o rk30_hdmi_edid.o rk30_hdmi_lcdc.o rk30_hdmi_task.o rk30_hdmi_sysfs.o rk30_hdmi.o
-obj-$(CONFIG_HDCP_RK30) += hdcp/
+obj-$(CONFIG_RK_HDMI) += rk_hdmi_edid.o rk_hdmi_lcdc.o rk_hdmi_task.o rk_hdmi_sysfs.o
+obj-$(CONFIG_RK_HDMI) += chips/
diff --git a/drivers/video/rockchip/hdmi/chips/Kconfig b/drivers/video/rockchip/hdmi/chips/Kconfig
new file mode 100755 (executable)
index 0000000..e0c1c27
--- /dev/null
@@ -0,0 +1,23 @@
+choice
+       prompt "HDMI chips select"
+config  HDMI_RK30
+        bool "RK30 HDMI support"
+        depends on LCDC_RK30
+        select FB_MODE_HELPERS
+        help
+           Support rk30 hdmi if you say y here
+config  HDMI_RK2928
+        bool "RK2928 HDMI support"
+        depends on LCDC_RK2928
+        select FB_MODE_HELPERS
+        help
+           Support rk2928 hdmi if you say y here
+endchoice
+
+if HDMI_RK30
+source "drivers/video/rockchip/hdmi/chips/rk30/Kconfig"
+endif
+
+if HDMI_RK2928
+source "drivers/video/rockchip/hdmi/chips/rk2928/Kconfig"
+endif
diff --git a/drivers/video/rockchip/hdmi/chips/Makefile b/drivers/video/rockchip/hdmi/chips/Makefile
new file mode 100755 (executable)
index 0000000..a43ac06
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for HDMI linux kernel module.
+#
+
+ccflags-$(CONFIG_HDMI_RK30_DEBUG) = -DDEBUG -DHDMI_DEBUG
+
+obj-$(CONFIG_HDMI_RK30) += rk30/
+obj-$(CONFIG_HDMI_RK2928) += rk2928/
diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/Kconfig b/drivers/video/rockchip/hdmi/chips/rk2928/Kconfig
new file mode 100755 (executable)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/Makefile b/drivers/video/rockchip/hdmi/chips/rk2928/Makefile
new file mode 100755 (executable)
index 0000000..d3227c7
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for HDMI linux kernel module.
+#
+
+ccflags-$(CONFIG_HDMI_RK30_DEBUG) = -DDEBUG -DHDMI_DEBUG
+
+obj-y += rk2928_hdmi_hw.o rk2928_hdmi.o
+obj-$(CONFIG_HDCP_RK2928) += hdcp/
diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/Kconfig b/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/Kconfig
new file mode 100755 (executable)
index 0000000..1bb3c3a
--- /dev/null
@@ -0,0 +1,14 @@
+config HDCP_RK30
+       bool "RK30 HDCP support"
+        depends on LCDC_RK30 && HDMI_RK30
+        default n
+       help
+         HDCP Interface. This adds the High Definition Content Protection Interface.
+         See http://www.digital-cp.com/ for HDCP specification.
+
+config HDCP_RK30_DEBUG
+       bool "RK30 HDCP Debugging"
+        depends on HDCP_RK30
+        default n
+       help
+         Enableds verbose debugging the the HDCP drivers
diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/Makefile b/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/Makefile
new file mode 100755 (executable)
index 0000000..108b67c
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for HDCP linux kernel module.
+#
+
+ccflags-$(CONFIG_HDCP_RK30_DEBUG) = -DDEBUG -DHDCP_DEBUG
+
+obj-$(CONFIG_HDCP_RK30) += hdcp.o
+hdcp-y := rk30_hdcp.o rk30_hdmi_hdcp.o
diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdcp.c b/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdcp.c
new file mode 100755 (executable)
index 0000000..68d0ac8
--- /dev/null
@@ -0,0 +1,570 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/miscdevice.h>
+#include <linux/workqueue.h>
+#include <linux/firmware.h>
+#include "../rk30_hdmi.h"
+#include "../rk30_hdmi_hw.h"
+#include "rk30_hdmi_hdcp.h"
+
+struct hdcp *hdcp = NULL;
+
+static void hdcp_work_queue(struct work_struct *work);
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_submit_work
+ *-----------------------------------------------------------------------------
+ */
+static struct delayed_work *hdcp_submit_work(int event, int delay)
+{
+       struct hdcp_delayed_work *work;
+
+       DBG("%s event %04x delay %d", __FUNCTION__, event, delay);
+       
+       work = kmalloc(sizeof(struct hdcp_delayed_work), GFP_ATOMIC);
+
+       if (work) {
+               INIT_DELAYED_WORK(&work->work, hdcp_work_queue);
+               work->event = event;
+               queue_delayed_work(hdcp->workqueue,
+                                  &work->work,
+                                  msecs_to_jiffies(delay));
+       } else {
+               printk(KERN_WARNING "HDCP: Cannot allocate memory to "
+                                   "create work\n");
+               return 0;
+       }
+
+       return &work->work;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_cancel_work
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_cancel_work(struct delayed_work **work)
+{
+       int ret = 0;
+
+       if (*work) {
+               ret = cancel_delayed_work(*work);
+               if (ret != 1) {
+                       ret = cancel_work_sync(&((*work)->work));
+                       printk(KERN_INFO "Canceling work failed - "
+                                        "cancel_work_sync done %d\n", ret);
+               }
+               kfree(*work);
+               *work = 0;
+       }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_authentication_failure
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_authentication_failure(void)
+{
+       if (hdcp->hdmi_state == HDMI_STOPPED) {
+               return;
+       }
+
+       rk30_hdcp_disable();
+       rk30_hdmi_control_output(false);
+       
+       hdcp_cancel_work(&hdcp->pending_wq_event);
+
+       if (hdcp->retry_cnt && (hdcp->hdmi_state != HDMI_STOPPED)) {
+               if (hdcp->retry_cnt < HDCP_INFINITE_REAUTH) {
+                       hdcp->retry_cnt--;
+                       printk(KERN_INFO "HDCP: authentication failed - "
+                                        "retrying, attempts=%d\n",
+                                                       hdcp->retry_cnt);
+               } else
+                       printk(KERN_INFO "HDCP: authentication failed - "
+                                        "retrying\n");
+
+               hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
+
+               hdcp->pending_wq_event = hdcp_submit_work(HDCP_AUTH_REATT_EVENT,
+                                                        HDCP_REAUTH_DELAY);
+       } else {
+               printk(KERN_INFO "HDCP: authentication failed - "
+                                "HDCP disabled\n");
+               hdcp->hdcp_state = HDCP_ENABLE_PENDING;
+       }
+
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_start_authentication
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_start_authentication(void)
+{
+       int status = HDCP_OK;
+
+       hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
+
+       DBG("HDCP: authentication start");
+
+       status = rk30_hdcp_start_authentication();
+
+       if (status != HDCP_OK) {
+               DBG("HDCP: authentication failed");
+               hdcp_wq_authentication_failure();
+       } else {
+               hdcp->hdcp_state = HDCP_WAIT_KSV_LIST;
+       }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_check_bksv
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_check_bksv(void)
+{
+       int status = HDCP_OK;
+
+       DBG("Check BKSV start");
+       
+       status = rk30_hdcp_check_bksv();
+
+       if (status != HDCP_OK) {
+               printk(KERN_INFO "HDCP: Check BKSV failed");
+               hdcp->retry_cnt = 0;
+               hdcp_wq_authentication_failure();
+       }
+       else {
+               DBG("HDCP: Check BKSV successful");
+
+               hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
+
+               /* Restore retry counter */
+               if(hdcp->retry_times == 0)
+                       hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
+               else
+                       hdcp->retry_cnt = hdcp->retry_times;
+       }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_authentication_sucess
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_authentication_sucess(void)
+{
+       printk(KERN_INFO "HDCP: authentication pass");
+       rk30_hdmi_control_output(true);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_disable
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_disable(int event)
+{
+       printk(KERN_INFO "HDCP: disabled");
+
+       hdcp_cancel_work(&hdcp->pending_wq_event);
+       rk30_hdcp_disable();
+       if(event == HDCP_DISABLE_CTL) {
+               hdcp->hdcp_state = HDCP_DISABLED;
+               if(hdcp->hdmi_state == HDMI_STARTED)
+                       rk30_hdmi_control_output(true);                 
+       }
+       else if(event == HDCP_STOP_FRAME_EVENT)
+               hdcp->hdcp_state = HDCP_ENABLE_PENDING;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_work_queue
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_work_queue(struct work_struct *work)
+{
+       struct hdcp_delayed_work *hdcp_w =
+               container_of(work, struct hdcp_delayed_work, work.work);
+       int event = hdcp_w->event;
+
+       mutex_lock(&hdcp->lock);
+       
+       DBG("hdcp_work_queue() - START - %u hdmi=%d hdcp=%d evt= %x %d",
+               jiffies_to_msecs(jiffies),
+               hdcp->hdmi_state,
+               hdcp->hdcp_state,
+               (event & 0xFF00) >> 8,
+               event & 0xFF);
+       
+       if(event == HDCP_STOP_FRAME_EVENT) {
+               hdcp->hdmi_state = HDMI_STOPPED;
+       }
+       
+       if (event == HDCP_DISABLE_CTL || event == HDCP_STOP_FRAME_EVENT) {
+               hdcp_wq_disable(event);
+       }
+       
+       if (event & HDCP_WORKQUEUE_SRC)
+               hdcp->pending_wq_event = 0;
+       
+       /* First handle HDMI state */
+       if (event == HDCP_START_FRAME_EVENT) {
+               hdcp->pending_start = 0;
+               hdcp->hdmi_state = HDMI_STARTED;
+       }
+       
+       /**********************/
+       /* HDCP state machine */
+       /**********************/
+       switch (hdcp->hdcp_state) {
+               case HDCP_DISABLED:
+                       /* HDCP enable control or re-authentication event */
+                       if (event == HDCP_ENABLE_CTL) {
+                               if(hdcp->retry_times == 0)
+                                       hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
+                               else
+                                       hdcp->retry_cnt = hdcp->retry_times;
+                               if (hdcp->hdmi_state == HDMI_STARTED)
+                                       hdcp_wq_start_authentication();
+                               else
+                                       hdcp->hdcp_state = HDCP_ENABLE_PENDING;
+                       }
+                       break;
+               
+               case HDCP_ENABLE_PENDING:
+                       /* HDMI start frame event */
+                       if (event == HDCP_START_FRAME_EVENT)
+                               hdcp_wq_start_authentication();
+
+                       break;
+               
+               case HDCP_AUTHENTICATION_START:
+                       /* Re-authentication */
+                       if (event == HDCP_AUTH_REATT_EVENT)
+                               hdcp_wq_start_authentication();
+       
+                       break;
+               
+               case HDCP_WAIT_KSV_LIST:
+                       /* KSV failure */
+                       if (event == HDCP_FAIL_EVENT) {
+                               printk(KERN_INFO "HDCP: KSV switch failure\n");
+       
+                               hdcp_wq_authentication_failure();
+                       }
+                       /* KSV list ready event */
+                       else if (event == HDCP_KSV_LIST_RDY_EVENT)
+                               hdcp_wq_check_bksv();
+                       break;
+               
+               case HDCP_LINK_INTEGRITY_CHECK:
+                       /* Ri failure */
+                       if (event == HDCP_FAIL_EVENT) {
+                               printk(KERN_INFO "HDCP: Ri check failure\n");
+                               hdcp_wq_authentication_failure();
+                       }
+                       else if(event == HDCP_AUTH_PASS_EVENT)
+                               hdcp_wq_authentication_sucess();
+                       break;
+       
+               default:
+                       printk(KERN_WARNING "HDCP: error - unknow HDCP state\n");
+                       break;
+       }
+       
+       kfree(hdcp_w);
+       if(event == HDCP_STOP_FRAME_EVENT)
+               complete(&hdcp->complete);
+               
+       mutex_unlock(&hdcp->lock);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_start_frame_cb
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_start_frame_cb(void)
+{
+       DBG("hdcp_start_frame_cb()");
+
+       /* Cancel any pending work */
+       if (hdcp->pending_start)
+               hdcp_cancel_work(&hdcp->pending_start);
+       if (hdcp->pending_wq_event)
+               hdcp_cancel_work(&hdcp->pending_wq_event);
+
+       hdcp->pending_start = hdcp_submit_work(HDCP_START_FRAME_EVENT,
+                                                       HDCP_ENABLE_DELAY);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_irq_cb
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_irq_cb(int interrupt)
+{
+       int value;
+       DBG("%s 0x%x", __FUNCTION__, interrupt);
+       if(interrupt & m_INT_HDCP_ERR)
+       {
+               value = HDMIRdReg(HDCP_ERROR);
+               HDMIWrReg(HDCP_ERROR, value);
+               printk(KERN_INFO "HDCP: Error 0x%02x\n", value);
+               
+               if( (hdcp->hdcp_state != HDCP_DISABLED) &&
+                       (hdcp->hdcp_state != HDCP_ENABLE_PENDING) )
+               {       
+                       hdcp_submit_work(HDCP_FAIL_EVENT, 0);
+               }
+       }
+       else if(interrupt & (m_INT_BKSV_RPRDY | m_INT_BKSV_RCRDY))
+               hdcp_submit_work(HDCP_KSV_LIST_RDY_EVENT, 0);
+       else if(interrupt & m_INT_AUTH_DONE)
+               hdcp_submit_work(HDCP_AUTH_PASS_EVENT, 0);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_power_on_cb
+ *-----------------------------------------------------------------------------
+ */
+static int hdcp_power_on_cb(void)
+{
+       DBG("%s", __FUNCTION__);
+       return rk30_hdcp_load_key2mem(hdcp->keys);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_power_off_cb
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_power_off_cb(void)
+{
+       DBG("%s", __FUNCTION__);
+       if(!hdcp->enable)
+               return;
+       
+       hdcp_cancel_work(&hdcp->pending_start);
+       hdcp_cancel_work(&hdcp->pending_wq_event);
+       init_completion(&hdcp->complete);
+       /* Post event to workqueue */
+       if (hdcp_submit_work(HDCP_STOP_FRAME_EVENT, 0)) 
+               wait_for_completion_interruptible_timeout(&hdcp->complete,
+                                                       msecs_to_jiffies(2000));
+}
+
+// Load HDCP key to external HDCP memory
+static void hdcp_load_keys_cb(const struct firmware *fw, void *context)
+{
+       if (!fw) {
+               pr_err("HDCP: failed to load keys\n");
+               return;
+       }
+       
+       if(fw->size < HDCP_KEY_SIZE) {
+               pr_err("HDCP: firmware wrong size %d\n", fw->size);
+               return;
+       }
+       
+       hdcp->keys =  kmalloc(HDCP_KEY_SIZE, GFP_KERNEL);
+       if(hdcp->keys == NULL) {
+               pr_err("HDCP: can't allocated space for keys\n");
+               return;
+       }
+       
+       memcpy(hdcp->keys, fw->data, HDCP_KEY_SIZE);
+       
+       rk30_hdcp_load_key2mem(hdcp->keys);
+       printk(KERN_INFO "HDCP: loaded hdcp key success\n");
+
+       if(fw->size > HDCP_KEY_SIZE) {
+               DBG("%s invalid key size %d", __FUNCTION__, fw->size - HDCP_KEY_SIZE);
+               if((fw->size - HDCP_KEY_SIZE) % 5) {
+                       pr_err("HDCP: failed to load invalid keys\n");
+                       return;
+               }
+               hdcp->invalidkeys = kmalloc(fw->size - HDCP_KEY_SIZE, GFP_KERNEL);
+               if(hdcp->invalidkeys == NULL) {
+                       pr_err("HDCP: can't allocated space for invalid keys\n");
+                       return;
+               }
+               memcpy(hdcp->invalidkeys, fw->data + HDCP_KEY_SIZE, fw->size - HDCP_KEY_SIZE);
+               hdcp->invalidkey = (fw->size - HDCP_KEY_SIZE)/5;
+               printk(KERN_INFO "HDCP: loaded hdcp invalid key success\n");
+       }
+}
+
+static ssize_t hdcp_enable_read(struct device *device,
+                           struct device_attribute *attr, char *buf)
+{
+       int enable = 0;
+       
+       if(hdcp)
+               enable = hdcp->enable;
+               
+       return snprintf(buf, PAGE_SIZE, "%d\n", enable);
+}
+
+static ssize_t hdcp_enable_write(struct device *device,
+                          struct device_attribute *attr, const char *buf, size_t count)
+{
+       int enable;
+
+       if(hdcp == NULL)
+               return -EINVAL;
+       
+       sscanf(buf, "%d", &enable);
+       if(hdcp->enable != enable)
+       {
+               /* Post event to workqueue */
+               if(enable) {
+                       if (hdcp_submit_work(HDCP_ENABLE_CTL, 0) == 0)
+                               return -EFAULT;
+               }
+               else {
+                       hdcp_cancel_work(&hdcp->pending_start);
+                       hdcp_cancel_work(&hdcp->pending_wq_event);
+               
+                       /* Post event to workqueue */
+                       if (hdcp_submit_work(HDCP_DISABLE_CTL, 0) == 0)
+                               return -EFAULT;
+               }
+               hdcp->enable =  enable;
+       }
+       return count;
+}
+
+static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR, hdcp_enable_read, hdcp_enable_write);
+
+static ssize_t hdcp_trytimes_read(struct device *device,
+                           struct device_attribute *attr, char *buf)
+{
+       int trytimes = 0;
+       
+       if(hdcp)
+               trytimes = hdcp->retry_times;
+               
+       return snprintf(buf, PAGE_SIZE, "%d\n", trytimes);
+}
+
+static ssize_t hdcp_trytimes_wrtie(struct device *device,
+                          struct device_attribute *attr, const char *buf, size_t count)
+{
+       int trytimes;
+
+       if(hdcp == NULL)
+               return -EINVAL;
+       
+       sscanf(buf, "%d", &trytimes);
+       if(hdcp->retry_times != trytimes)
+               hdcp->retry_times = trytimes;
+       
+       return count;
+}
+
+
+static DEVICE_ATTR(trytimes, S_IRUGO|S_IWUSR, hdcp_trytimes_read, hdcp_trytimes_wrtie);
+
+
+static struct miscdevice mdev;
+
+static int __init rk30_hdcp_init(void)
+{
+       int ret;
+       
+       DBG("[%s] %u", __FUNCTION__, jiffies_to_msecs(jiffies));
+       
+       hdcp = kmalloc(sizeof(struct hdcp), GFP_KERNEL);
+       if(!hdcp)
+       {
+       printk(KERN_ERR ">>HDCP: kmalloc fail!");
+       ret = -ENOMEM;
+       goto error0; 
+       }
+       memset(hdcp, 0, sizeof(struct hdcp));
+       mutex_init(&hdcp->lock);
+       
+       mdev.minor = MISC_DYNAMIC_MINOR;
+       mdev.name = "hdcp";
+       mdev.mode = 0666;
+       if (misc_register(&mdev)) {
+               printk(KERN_ERR "HDCP: Could not add character driver\n");
+               ret = HDMI_ERROR_FALSE;
+               goto error1;
+       }
+       ret = device_create_file(mdev.this_device, &dev_attr_enable);
+    if(ret)
+    {
+        printk(KERN_ERR "HDCP: Could not add sys file enable\n");
+        ret = -EINVAL;
+        goto error2;
+    }
+    
+    ret = device_create_file(mdev.this_device, &dev_attr_trytimes);
+    if(ret)
+    {
+        printk(KERN_ERR "HDCP: Could not add sys file trytimes\n");
+        ret = -EINVAL;
+        goto error3;
+    }
+    
+    hdcp->workqueue = create_singlethread_workqueue("hdcp");
+       if (hdcp->workqueue == NULL) {
+               printk(KERN_ERR "HDCP,: create workqueue failed.\n");
+               goto error4;
+       }
+    
+    
+    ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
+                             "hdcp.keys", mdev.this_device, GFP_KERNEL,
+                             hdcp, hdcp_load_keys_cb);
+       if (ret < 0) {
+               printk(KERN_ERR "HDCP: request_firmware_nowait failed: %d\n", ret);
+               goto error5;
+       }
+       
+       rk30_hdmi_register_hdcp_callbacks(      hdcp_start_frame_cb,
+                                                                               hdcp_irq_cb,
+                                                                               hdcp_power_on_cb,
+                                                                               hdcp_power_off_cb);
+                                                                               
+       DBG("%s success %u", __FUNCTION__, jiffies_to_msecs(jiffies));
+       return 0;
+       
+error5:
+       destroy_workqueue(hdcp->workqueue);
+error4:
+       device_remove_file(mdev.this_device, &dev_attr_trytimes);
+error3:
+       device_remove_file(mdev.this_device, &dev_attr_enable);
+error2:
+       misc_deregister(&mdev);
+error1:
+       if(hdcp->keys)
+               kfree(hdcp->keys);
+       if(hdcp->invalidkeys)
+               kfree(hdcp->invalidkeys);
+       kfree(hdcp);
+error0:
+       return ret;
+}
+
+static void __exit rk30_hdcp_exit(void)
+{
+       if(hdcp) {
+               mutex_lock(&hdcp->lock);
+               rk30_hdmi_register_hdcp_callbacks(0, 0, 0, 0);
+               device_remove_file(mdev.this_device, &dev_attr_enable);
+               misc_deregister(&mdev);
+               destroy_workqueue(hdcp->workqueue);
+               if(hdcp->keys)
+                       kfree(hdcp->keys);
+               if(hdcp->invalidkeys)
+                       kfree(hdcp->invalidkeys);
+               mutex_unlock(&hdcp->lock);
+               kfree(hdcp);
+       }
+}
+
+module_init(rk30_hdcp_init);
+module_exit(rk30_hdcp_exit);
\ No newline at end of file
diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdmi_hdcp.c b/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdmi_hdcp.c
new file mode 100755 (executable)
index 0000000..1184989
--- /dev/null
@@ -0,0 +1,157 @@
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <mach/io.h>
+#include "../rk30_hdmi.h"
+#include "../rk30_hdmi_hw.h"
+#include "rk30_hdmi_hdcp.h"
+
+static void rk30_hdcp_write_mem(int addr_8, char value)
+{
+       int temp;
+       int addr_32 = addr_8 - addr_8%4;
+       int shift = (addr_8%4) * 8;
+       
+       temp = HDMIRdReg(addr_32);
+       temp &= ~(0xff << shift);
+       temp |= value << shift;
+//     printk("temp is %08x\n", temp);
+       HDMIWrReg(addr_32, temp);
+}
+
+int rk30_hdcp_load_key2mem(struct hdcp_keys *key)
+{
+       int i;
+       
+       if(key == NULL) return  HDMI_ERROR_FALSE;
+       
+       HDMIWrReg(0x800, HDMI_INTERANL_CLK_DIV);
+       
+       for(i = 0; i < 7; i++)
+               rk30_hdcp_write_mem(HDCP_RAM_KEY_KSV1 + i, key->KSV[i]);
+       for(i = 0; i < 7; i++)
+               rk30_hdcp_write_mem(HDCP_RAM_KEY_KSV2 + i, key->KSV[i]);
+       for(i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++)
+               rk30_hdcp_write_mem(HDCP_RAM_KEY_PRIVATE + i, key->DeviceKey[i]);
+       for(i = 0; i < HDCP_KEY_SHA_SIZE; i++)
+               rk30_hdcp_write_mem(HDCP_RAM_KEY_PRIVATE + HDCP_PRIVATE_KEY_SIZE + i, key->sha1[i]);
+       
+       HDMIWrReg(0x800, HDMI_INTERANL_CLK_DIV | 0x20);
+       return HDCP_OK;
+}
+
+void rk30_hdcp_disable(void)
+{
+       int temp;
+       // Diable HDCP Interrupt
+       HDMIWrReg(INTR_MASK2, 0x00);
+       // Stop and Reset HDCP
+       HDMIMskReg(temp, HDCP_CTRL, m_HDCP_FRAMED_ENCRYPED | m_HDCP_AUTH_STOP | m_HDCP_RESET, 
+               v_HDCP_FRAMED_ENCRYPED(0) | v_HDCP_AUTH_STOP(1) | v_HDCP_RESET(1) );
+}
+
+static int rk30_hdcp_load_key(void)
+{
+       int value, temp = 0;
+       
+       if(hdcp->keys == NULL) {
+               pr_err("[%s] HDCP key not loaded.\n", __FUNCTION__);
+               return HDCP_KEY_ERR;
+       }
+       
+       value = HDMIRdReg(HDCP_KEY_MEM_CTRL);
+       //Check HDCP key loaded from external HDCP memory
+       while((value & (m_KSV_VALID | m_KEY_VALID | m_KEY_READY)) != (m_KSV_VALID | m_KEY_VALID | m_KEY_READY)) {
+               if(temp > 10) {
+                       pr_err("[%s] loaded hdcp key is incorrectable %02x\n", __FUNCTION__, value & 0xFF);
+                       return HDCP_KEY_ERR;
+               }
+               //Load HDCP Key from external HDCP memory
+               HDMIWrReg(HDCP_KEY_ACCESS_CTRL2, m_LOAD_HDCP_KEY);
+               msleep(1);
+               value = HDMIRdReg(HDCP_KEY_MEM_CTRL);
+               temp++;
+       }
+       
+       return HDCP_OK;
+}
+
+
+int rk30_hdcp_start_authentication(void)
+{
+       int rc, temp;
+       
+       rc = rk30_hdcp_load_key();
+       if(rc != HDCP_OK)
+               return rc;
+       
+       // Set 100ms & 5 sec timer
+       switch(hdmi->vic)
+       {
+               case HDMI_720x576p_50Hz_4_3:
+               case HDMI_720x576p_50Hz_16_9:
+               case HDMI_1280x720p_50Hz:
+               case HDMI_1920x1080i_50Hz:
+               case HDMI_720x576i_50Hz_4_3:
+               case HDMI_720x576i_50Hz_16_9:
+               case HDMI_1920x1080p_50Hz:
+                       HDMIWrReg(HDCP_TIMER_100MS, 5);
+                       HDMIWrReg(HDCP_TIMER_5S, 250);
+                       break;
+               
+               default:
+                       HDMIWrReg(HDCP_TIMER_100MS, 0x26);
+                       HDMIWrReg(HDCP_TIMER_5S, 0x2c);
+                       break;
+       }
+       // Config DDC Clock
+       temp = (hdmi->tmdsclk/HDCP_DDC_CLK)/4;
+       HDMIWrReg(DDC_BUS_FREQ_L, temp & 0xFF);
+       HDMIWrReg(DDC_BUS_FREQ_H, (temp >> 8) & 0xFF);
+       // Enable HDCP Interrupt
+       HDMIWrReg(INTR_MASK2, m_INT_HDCP_ERR | m_INT_BKSV_RPRDY | m_INT_BKSV_RCRDY | m_INT_AUTH_DONE | m_INT_AUTH_READY);
+       // Start HDCP
+       HDMIMskReg(temp, HDCP_CTRL, m_HDCP_AUTH_START | m_HDCP_FRAMED_ENCRYPED, v_HDCP_AUTH_START(1) | v_HDCP_FRAMED_ENCRYPED(0));
+       
+       return HDCP_OK;
+}
+
+int rk30_hdcp_check_bksv(void)
+{
+       int i, temp;
+       char bksv[5];
+       char *invalidkey;
+       
+       temp = HDMIRdReg(HDCP_BCAPS);
+       DBG("Receiver capacity is 0x%02x", temp);
+       
+#ifdef DEBUG   
+       if(temp & m_HDMI_RECEIVED)
+               DBG("Receiver support HDMI");
+       if(temp & m_REPEATER)
+               DBG("Receiver is a repeater");
+       if(temp & m_DDC_FAST)
+               DBG("Receiver support 400K DDC");
+       if(temp & m_1_1_FEATURE)
+               DBG("Receiver support 1.1 features, such as advanced cipher, EESS.");
+       if(temp & m_FAST_REAUTHENTICATION)
+               DBG("Receiver support fast reauthentication.");
+#endif
+               
+       for(i = 0; i < 5; i++) {
+               bksv[i] = HDMIRdReg(HDCP_KSV_BYTE0 + (4 - i)*4) & 0xFF;
+       }
+       
+       DBG("bksv is 0x%02x%02x%02x%02x%02x", bksv[0], bksv[1], bksv[2], bksv[3], bksv[4]);
+       
+       for(i = 0; i < hdcp->invalidkey; i++)
+       {
+               invalidkey = hdcp->invalidkeys + i *5;
+               if(memcmp(bksv, invalidkey, 5) == 0) {
+                       printk(KERN_ERR "HDCP: BKSV was revocated!!!\n");
+                       HDMIMskReg(temp, HDCP_CTRL, m_HDCP_BKSV_FAILED | m_HDCP_FRAMED_ENCRYPED, v_HDCP_BKSV_FAILED(1) | v_HDCP_FRAMED_ENCRYPED(0));
+                       return HDCP_KSV_ERR;
+               }
+       }
+       HDMIMskReg(temp, HDCP_CTRL, m_HDCP_BKSV_PASS | m_HDCP_FRAMED_ENCRYPED, v_HDCP_BKSV_PASS(1) | v_HDCP_FRAMED_ENCRYPED(1));
+       return HDCP_OK;
+}
diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdmi_hdcp.h b/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdmi_hdcp.h
new file mode 100755 (executable)
index 0000000..0224d88
--- /dev/null
@@ -0,0 +1,99 @@
+#ifndef __RK30_HDMI_HDCP_H__
+#define __RK30_HDMI_HDCP_H__
+
+/***************************/
+/* Definitions             */
+/***************************/
+
+/* Status / error codes */
+#define HDCP_OK                        0
+#define HDCP_KEY_ERR   1
+#define HDCP_KSV_ERR   2
+
+/* Delays */
+#define HDCP_ENABLE_DELAY      300
+#define HDCP_REAUTH_DELAY      100
+
+/* Event source */
+#define HDCP_SRC_SHIFT         8
+#define HDCP_IOCTL_SRC         (0x1 << HDCP_SRC_SHIFT)
+#define HDCP_HDMI_SRC          (0x2 << HDCP_SRC_SHIFT)
+#define HDCP_IRQ_SRC           (0x4 << HDCP_SRC_SHIFT)
+#define HDCP_WORKQUEUE_SRC     (0x8 << HDCP_SRC_SHIFT)
+
+/* Event */
+#define HDCP_ENABLE_CTL                        (HDCP_IOCTL_SRC         | 0)
+#define HDCP_DISABLE_CTL               (HDCP_IOCTL_SRC         | 1)
+#define HDCP_START_FRAME_EVENT (HDCP_HDMI_SRC          | 2)
+#define HDCP_STOP_FRAME_EVENT  (HDCP_HDMI_SRC          | 3)
+#define HDCP_KSV_LIST_RDY_EVENT        (HDCP_IRQ_SRC           | 4)
+#define HDCP_FAIL_EVENT                        (HDCP_IRQ_SRC           | 5)
+#define HDCP_AUTH_PASS_EVENT   (HDCP_IRQ_SRC           | 6)
+#define HDCP_AUTH_REATT_EVENT  (HDCP_WORKQUEUE_SRC     | 7)
+
+/* Key size */
+#define HDCP_KEY_SIZE                  308     
+
+/* Authentication retry times */
+#define HDCP_INFINITE_REAUTH   0x100
+
+enum hdcp_states {
+       HDCP_DISABLED,
+       HDCP_ENABLE_PENDING,
+       HDCP_AUTHENTICATION_START,
+       HDCP_WAIT_KSV_LIST,
+       HDCP_LINK_INTEGRITY_CHECK,
+};
+
+enum hdmi_states {
+       HDMI_STOPPED,
+       HDMI_STARTED
+};
+
+#define HDCP_PRIVATE_KEY_SIZE  280
+#define HDCP_KEY_SHA_SIZE              20
+#define HDCP_DDC_CLK                   100000
+
+struct hdcp_keys{
+       u8 KSV[8];
+       u8 DeviceKey[HDCP_PRIVATE_KEY_SIZE];
+       u8 sha1[HDCP_KEY_SHA_SIZE];
+};
+
+struct hdcp_delayed_work {
+       struct delayed_work work;
+       int event;
+};
+
+struct hdcp {
+       int     enable;
+       int retry_times;
+       struct hdcp_keys *keys;
+       int invalidkey;
+       char *invalidkeys;      
+       struct mutex lock;
+       struct completion       complete;
+       struct workqueue_struct *workqueue;
+       
+       enum hdmi_states hdmi_state;
+       enum hdcp_states hdcp_state;
+       
+       struct delayed_work *pending_start;
+       struct delayed_work *pending_wq_event;
+       int retry_cnt;
+};
+
+extern struct hdcp *hdcp;
+
+#ifdef HDCP_DEBUG
+#define DBG(format, ...) \
+               printk(KERN_INFO "HDCP: " format "\n", ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+extern void rk30_hdcp_disable(void);
+extern int     rk30_hdcp_start_authentication(void);
+extern int     rk30_hdcp_check_bksv(void);
+extern int     rk30_hdcp_load_key2mem(struct hdcp_keys *key);
+#endif /* __RK30_HDMI_HDCP_H__ */
\ No newline at end of file
diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi.c b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi.c
new file mode 100755 (executable)
index 0000000..1ef1418
--- /dev/null
@@ -0,0 +1,299 @@
+#include <linux/module.h>\r
+#include <linux/kernel.h>\r
+#include <linux/errno.h>\r
+#include <linux/string.h>\r
+#include <linux/mm.h>\r
+#include <linux/slab.h>\r
+#include <linux/delay.h>\r
+#include <linux/device.h>\r
+#include <linux/init.h>\r
+#include <linux/dma-mapping.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/clk.h>\r
+\r
+#include <mach/board.h>\r
+#include <mach/io.h>\r
+#include <mach/gpio.h>\r
+#include <mach/iomux.h>\r
+#include "rk2928_hdmi.h"\r
+#include "rk2928_hdmi_hw.h"\r
+\r
+struct hdmi *hdmi = NULL;\r
+\r
+extern irqreturn_t hdmi_irq(int irq, void *priv);\r
+extern void hdmi_work(struct work_struct *work);\r
+extern struct rk_lcdc_device_driver * rk_get_lcdc_drv(char *name);\r
+extern void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent);\r
+extern void hdmi_unregister_display_sysfs(struct hdmi *hdmi);\r
+\r
+int rk2928_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),\r
+                                        void (*hdcp_irq_cb)(int status),\r
+                                        int (*hdcp_power_on_cb)(void),\r
+                                        void (*hdcp_power_off_cb)(void))\r
+{\r
+       if(hdmi == NULL)\r
+               return HDMI_ERROR_FALSE;\r
+\r
+       hdmi->hdcp_cb = hdcp_cb;\r
+       hdmi->hdcp_irq_cb = hdcp_irq_cb;\r
+       hdmi->hdcp_power_on_cb = hdcp_power_on_cb;\r
+       hdmi->hdcp_power_off_cb = hdcp_power_off_cb;\r
+       \r
+       return HDMI_ERROR_SUCESS;\r
+}\r
+\r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+static void hdmi_early_suspend(struct early_suspend *h)\r
+{\r
+       hdmi_dbg(hdmi->dev, "hdmi enter early suspend pwr %d state %d\n", hdmi->pwr_mode, hdmi->state);\r
+       flush_delayed_work(&hdmi->delay_work);  \r
+       mutex_lock(&hdmi->enable_mutex);\r
+       hdmi->suspend = 1;\r
+       if(!hdmi->enable) {\r
+               mutex_unlock(&hdmi->enable_mutex);\r
+               return;\r
+       }\r
+       disable_irq(hdmi->irq);\r
+       mutex_unlock(&hdmi->enable_mutex);\r
+       hdmi->command = HDMI_CONFIG_ENABLE;\r
+       init_completion(&hdmi->complete);\r
+       hdmi->wait = 1;\r
+       queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);\r
+       wait_for_completion_interruptible_timeout(&hdmi->complete,\r
+                                                       msecs_to_jiffies(5000));\r
+       flush_delayed_work(&hdmi->delay_work);\r
+       // When HDMI 1.1V and 2.5V power off, DDC channel will be pull down, current is produced\r
+       // from VCC_IO which is pull up outside soc. We need to switch DDC IO to GPIO.\r
+//     rk2928_mux_api_set(GPIO0A7_I2C3_SDA_HDMI_DDCSDA_NAME, GPIO0A_GPIO0A7);\r
+//     rk2928_mux_api_set(GPIO0A6_I2C3_SCL_HDMI_DDCSCL_NAME, GPIO0A_GPIO0A6);\r
+       return;\r
+}\r
+\r
+static void hdmi_early_resume(struct early_suspend *h)\r
+{\r
+       hdmi_dbg(hdmi->dev, "hdmi exit early resume\n");\r
+       mutex_lock(&hdmi->enable_mutex);\r
+       \r
+//     rk2928_mux_api_set(GPIO0A7_I2C3_SDA_HDMI_DDCSDA_NAME, GPIO0A_HDMI_DDCSDA);\r
+//     rk2928_mux_api_set(GPIO0A6_I2C3_SCL_HDMI_DDCSCL_NAME, GPIO0A_HDMI_DDCSCL);\r
+       \r
+       hdmi->suspend = 0;\r
+       rk2928_hdmi_initial();\r
+       if(hdmi->enable) {\r
+               enable_irq(hdmi->irq);\r
+       }\r
+       mutex_unlock(&hdmi->enable_mutex);\r
+       return;\r
+}\r
+#endif\r
+\r
+static inline void hdmi_io_remap(void)\r
+{\r
+       unsigned int value;\r
+       \r
+       // Remap HDMI IO Pin\r
+//     rk2928_mux_api_set(GPIO0A7_I2C3_SDA_HDMI_DDCSDA_NAME, GPIO0A_HDMI_DDCSDA);\r
+//     rk2928_mux_api_set(GPIO0A6_I2C3_SCL_HDMI_DDCSCL_NAME, GPIO0A_HDMI_DDCSCL);\r
+//     rk2928_mux_api_set(GPIO0B7_HDMI_HOTPLUGIN_NAME, GPIO0B_HDMI_HOTPLUGIN);\r
+               \r
+       // Select LCDC0 as video source and enabled.\r
+//     value = (HDMI_SOURCE_DEFAULT << 14) | (1 << 30);\r
+//     writel(value, GRF_SOC_CON0 + rk2928_GRF_BASE);\r
+}\r
+\r
+static int __devinit rk2928_hdmi_probe (struct platform_device *pdev)\r
+{\r
+       int ret;\r
+       struct resource *res;\r
+       struct resource *mem;\r
+       \r
+       hdmi = kmalloc(sizeof(struct hdmi), GFP_KERNEL);\r
+       if(!hdmi)\r
+       {\r
+       dev_err(&pdev->dev, ">>rk30 hdmi kmalloc fail!");\r
+       return -ENOMEM;\r
+       }\r
+       memset(hdmi, 0, sizeof(struct hdmi));\r
+       hdmi->dev = &pdev->dev;\r
+       platform_set_drvdata(pdev, hdmi);\r
+\r
+       if(HDMI_SOURCE_DEFAULT == HDMI_SOURCE_LCDC0)\r
+               hdmi->lcdc = rk_get_lcdc_drv("lcdc0");\r
+       else\r
+               hdmi->lcdc = rk_get_lcdc_drv("lcdc1");\r
+       if(hdmi->lcdc == NULL)\r
+       {\r
+               dev_err(hdmi->dev, "can not connect to video source lcdc\n");\r
+               ret = -ENXIO;\r
+               goto err0;\r
+       }\r
+       hdmi->xscale = 95;\r
+       hdmi->yscale = 95;\r
+       \r
+       hdmi->hclk = clk_get(NULL,"hclk_hdmi");\r
+       if(IS_ERR(hdmi->hclk))\r
+       {\r
+               dev_err(hdmi->dev, "Unable to get hdmi hclk\n");\r
+               ret = -ENXIO;\r
+               goto err0;\r
+       }\r
+       clk_enable(hdmi->hclk);\r
+       \r
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
+       if (!res) {\r
+               dev_err(hdmi->dev, "Unable to get register resource\n");\r
+               ret = -ENXIO;\r
+               goto err0;\r
+       }\r
+       hdmi->regbase_phy = res->start;\r
+       hdmi->regsize_phy = (res->end - res->start) + 1;\r
+       mem = request_mem_region(res->start, (res->end - res->start) + 1, pdev->name);\r
+       if (!mem)\r
+       {\r
+       dev_err(hdmi->dev, "failed to request mem region for hdmi\n");\r
+       ret = -ENOENT;\r
+       goto err0;\r
+       }\r
+\r
+       \r
+       hdmi->regbase = (int)ioremap(res->start, (res->end - res->start) + 1);\r
+       if (!hdmi->regbase) {\r
+               dev_err(hdmi->dev, "cannot ioremap registers\n");\r
+               ret = -ENXIO;\r
+               goto err1;\r
+       }\r
+       \r
+       ret = rk2928_hdmi_initial();\r
+       if(ret != HDMI_ERROR_SUCESS)\r
+               goto err1;\r
+               \r
+       hdmi_io_remap();\r
+       hdmi_sys_init();\r
+       \r
+       hdmi->workqueue = create_singlethread_workqueue("hdmi");\r
+       INIT_DELAYED_WORK(&(hdmi->delay_work), hdmi_work);\r
+\r
+       #ifdef CONFIG_HAS_EARLYSUSPEND\r
+       hdmi->early_suspend.suspend = hdmi_early_suspend;\r
+       hdmi->early_suspend.resume = hdmi_early_resume;\r
+       hdmi->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 10;\r
+       register_early_suspend(&hdmi->early_suspend);\r
+       #endif\r
+               \r
+       hdmi_register_display_sysfs(hdmi, NULL);\r
+       #ifdef CONFIG_SWITCH\r
+       hdmi->switch_hdmi.name="hdmi";\r
+       switch_dev_register(&(hdmi->switch_hdmi));\r
+       #endif\r
+               \r
+       spin_lock_init(&hdmi->irq_lock);\r
+       mutex_init(&hdmi->enable_mutex);\r
+       \r
+       /* get the IRQ */\r
+       hdmi->irq = platform_get_irq(pdev, 0);\r
+       if(hdmi->irq <= 0) {\r
+               dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);\r
+               ret = -ENXIO;\r
+               goto err2;\r
+       }\r
+\r
+       /* request the IRQ */\r
+       ret = request_irq(hdmi->irq, hdmi_irq, 0, dev_name(&pdev->dev), hdmi);\r
+       if (ret)\r
+       {\r
+               dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);\r
+               goto err2;\r
+       }\r
+\r
+       hdmi_dbg(hdmi->dev, "rk30 hdmi probe sucess.\n");\r
+       return 0;\r
+err2:\r
+       #ifdef CONFIG_SWITCH\r
+       switch_dev_unregister(&(hdmi->switch_hdmi));\r
+       #endif\r
+       hdmi_unregister_display_sysfs(hdmi);\r
+       #ifdef CONFIG_HAS_EARLYSUSPEND\r
+       unregister_early_suspend(&hdmi->early_suspend);\r
+       #endif\r
+       iounmap((void*)hdmi->regbase);\r
+err1:\r
+       release_mem_region(res->start,(res->end - res->start) + 1);\r
+       clk_disable(hdmi->hclk);\r
+err0:\r
+       hdmi_dbg(hdmi->dev, "rk30 hdmi probe error.\n");\r
+       kfree(hdmi);\r
+       hdmi = NULL;\r
+       return ret;\r
+}\r
+\r
+static int __devexit rk2928_hdmi_remove(struct platform_device *pdev)\r
+{\r
+       if(hdmi) {\r
+               mutex_lock(&hdmi->enable_mutex);\r
+               if(!hdmi->suspend && hdmi->enable)\r
+                       disable_irq(hdmi->irq);\r
+               mutex_unlock(&hdmi->enable_mutex);\r
+               free_irq(hdmi->irq, NULL);\r
+               flush_workqueue(hdmi->workqueue);\r
+               destroy_workqueue(hdmi->workqueue);\r
+               #ifdef CONFIG_SWITCH\r
+               switch_dev_unregister(&(hdmi->switch_hdmi));\r
+               #endif\r
+               hdmi_unregister_display_sysfs(hdmi);\r
+               #ifdef CONFIG_HAS_EARLYSUSPEND\r
+               unregister_early_suspend(&hdmi->early_suspend);\r
+               #endif\r
+               iounmap((void*)hdmi->regbase);\r
+               release_mem_region(hdmi->regbase_phy, hdmi->regsize_phy);\r
+               clk_disable(hdmi->hclk);\r
+               fb_destroy_modelist(&hdmi->edid.modelist);\r
+               if(hdmi->edid.audio)\r
+                       kfree(hdmi->edid.audio);\r
+               if(hdmi->edid.specs)\r
+               {\r
+                       if(hdmi->edid.specs->modedb)\r
+                               kfree(hdmi->edid.specs->modedb);\r
+                       kfree(hdmi->edid.specs);\r
+               }\r
+               kfree(hdmi);\r
+               hdmi = NULL;\r
+       }\r
+       printk(KERN_INFO "rk30 hdmi removed.\n");\r
+       return 0;\r
+}\r
+\r
+static void rk2928_hdmi_shutdown(struct platform_device *pdev)\r
+{\r
+       if(hdmi) {\r
+               #ifdef CONFIG_HAS_EARLYSUSPEND\r
+               unregister_early_suspend(&hdmi->early_suspend);\r
+               #endif\r
+       }\r
+       printk(KERN_INFO "rk30 hdmi shut down.\n");\r
+}\r
+\r
+static struct platform_driver rk2928_hdmi_driver = {\r
+       .probe          = rk2928_hdmi_probe,\r
+       .remove         = __devexit_p(rk2928_hdmi_remove),\r
+       .driver         = {\r
+               .name   = "rk30-hdmi",\r
+               .owner  = THIS_MODULE,\r
+       },\r
+       .shutdown   = rk2928_hdmi_shutdown,\r
+};\r
+\r
+static int __init rk2928_hdmi_init(void)\r
+{\r
+    return platform_driver_register(&rk2928_hdmi_driver);\r
+}\r
+\r
+static void __exit rk2928_hdmi_exit(void)\r
+{\r
+    platform_driver_unregister(&rk2928_hdmi_driver);\r
+}\r
+\r
+\r
+//fs_initcall(rk2928_hdmi_init);\r
+module_init(rk2928_hdmi_init);\r
+module_exit(rk2928_hdmi_exit);\r
diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi.h b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi.h
new file mode 100755 (executable)
index 0000000..4695086
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __RK30_HDMI_H__
+#define __RK30_HDMI_H__
+
+#include "../../rk_hdmi.h"
+
+
+extern int rk30_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
+                                        void (*hdcp_irq_cb)(int status),
+                                        int  (*hdcp_power_on_cb)(void),
+                                        void (*hdcp_power_off_cb)(void));
+#endif /* __RK30_HDMI_H__ */
diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hw.c b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hw.c
new file mode 100755 (executable)
index 0000000..4f6e636
--- /dev/null
@@ -0,0 +1,456 @@
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <mach/io.h>
+#include "rk2928_hdmi.h"
+#include "rk2928_hdmi_hw.h"
+
+static char edid_result = 0;
+static bool analog_sync = 0;
+
+static inline void delay100us(void)
+{
+       msleep(1);
+}
+
+
+static void rk2928_hdmi_av_mute(bool enable)
+{
+       HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(enable) | v_VIDEO_MUTE(enable));
+}
+
+static void rk2928_hdmi_sys_power_up(void)
+{
+    hdmi_dbg(hdmi->dev,"%s \n",__FUNCTION__);
+       HDMIWrReg(SYS_CTRL, v_REG_CLK_SOURCE_IIS | v_PWR_ON | v_INT_POL_HIGH);
+}
+static void rk2928_hdmi_sys_power_down(void)
+{
+    hdmi_dbg(hdmi->dev,"%s \n",__FUNCTION__);
+       HDMIWrReg(SYS_CTRL, v_REG_CLK_SOURCE_IIS | v_PWR_OFF | v_INT_POL_HIGH);
+}
+
+
+
+static void rk2928_hdmi_set_pwr_mode(int mode)
+{
+       hdmi_dbg(hdmi->dev,"%s \n",__FUNCTION__);
+       if(hdmi->pwr_mode == mode)
+               return;
+    switch(mode){
+     case NORMAL:
+               rk2928_hdmi_sys_power_down();
+           HDMIWrReg(0xe3, 0x82);
+           HDMIWrReg(0xe5, 0x00);
+           HDMIWrReg(0xe4, 0x00);
+           HDMIWrReg(0xe7, 0x00);
+               HDMIWrReg(0xe1, 0x8e);
+               HDMIWrReg(0xce, 0x00);
+               HDMIWrReg(0xce, 0x01);
+               rk2928_hdmi_av_mute(1);
+               rk2928_hdmi_sys_power_up();
+               analog_sync = 1;
+               break;
+       case LOWER_PWR:
+               rk2928_hdmi_av_mute(0);
+               rk2928_hdmi_sys_power_down();
+           HDMIWrReg(0xe3, 0x02);
+           HDMIWrReg(0xe5, 0x1c);
+           HDMIWrReg(0xe1, 0x8c);
+           HDMIWrReg(0xe7, 0x04);
+           HDMIWrReg(0xe4, 0x03);
+               break;
+       default:
+           hdmi_dbg(hdmi->dev,"unkown rk2928 hdmi pwr mode %d\n",mode);
+    }
+       hdmi->pwr_mode = mode;
+}
+
+
+int rk2928_hdmi_detect_hotplug(void)
+{
+       int value =     HDMIRdReg(HDMI_STATUS);
+       
+       hdmi_dbg(hdmi->dev, "[%s] value %02x\n", __FUNCTION__, value);
+       value &= m_HOTPLUG;
+       if(value == m_HOTPLUG)
+               return HDMI_HPD_ACTIVED;
+       else if(value)
+               return HDMI_HPD_INSERT;
+       else
+               return HDMI_HPD_REMOVED;
+}
+
+#define HDMI_SYS_FREG_CLK        11289600
+#define HDMI_SCL_RATE            (100*1000)
+#define HDMI_DDC_CONFIG          (HDMI_SYS_FREG_CLK>>2)/HDMI_SCL_RATE
+#define DDC_BUS_FREQ_L                         0x4b
+#define DDC_BUS_FREQ_H                         0x4c
+
+int rk2928_hdmi_read_edid(int block, unsigned char *buff)
+{
+       int value, ret = -1, ddc_bus_freq = 0;
+       char interrupt = 0, trytime = 2;
+       unsigned long flags;
+       
+       hdmi_dbg(hdmi->dev, "[%s] block %d\n", __FUNCTION__, block);
+       spin_lock_irqsave(&hdmi->irq_lock, flags);
+       edid_result = 0;
+       spin_unlock_irqrestore(&hdmi->irq_lock, flags);
+       //Before Phy parameter was set, DDC_CLK is equal to PLLA freq which is 30MHz.
+       //Set DDC I2C CLK which devided from DDC_CLK to 100KHz.
+
+       ddc_bus_freq = HDMI_DDC_CONFIG; 
+       HDMIWrReg(DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
+       HDMIWrReg(DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
+       
+       // Enable edid interrupt
+       HDMIWrReg(INTERRUPT_MASK1, m_INT_HOTPLUG | m_INT_EDID_READY);
+       
+       while(trytime--) {
+               // Config EDID block and segment addr
+               HDMIWrReg(EDID_WORD_ADDR, (block%2) * 0x80);
+               HDMIWrReg(EDID_SEGMENT_POINTER, block/2);       
+       
+               value = 10;
+               while(value--)
+               {
+                       spin_lock_irqsave(&hdmi->irq_lock, flags);
+                       interrupt = edid_result;
+                       edid_result = 0;
+                       spin_unlock_irqrestore(&hdmi->irq_lock, flags);
+                       if(interrupt & (m_INT_EDID_READY))
+                               break;
+                       msleep(10);
+               }
+               hdmi_dbg(hdmi->dev, "[%s] edid read value %d\n", __FUNCTION__, value);
+               if(interrupt & m_INT_EDID_READY)
+               {
+                       for(value = 0; value < HDMI_EDID_BLOCK_SIZE; value++) 
+                               buff[value] = HDMIRdReg(EDID_FIFO_ADDR);
+                       ret = 0;
+                       
+                       hdmi_dbg(hdmi->dev, "[%s] edid read sucess\n", __FUNCTION__);
+#ifdef HDMI_DEBUG
+                       for(value = 0; value < 128; value++) {
+                               printk("%02x ,", buff[value]);
+                               if( (value + 1) % 16 == 0)
+                                       printk("\n");
+                       }
+#endif
+                       break;
+               }else
+                       hdmi_err(hdmi->dev, "[%s] edid read error\n", __FUNCTION__);
+
+       }
+       // Disable edid interrupt
+       HDMIWrReg(INTERRUPT_MASK1, m_INT_HOTPLUG);
+//     msleep(100);
+       return ret;
+}
+
+static void rk2928_hdmi_config_avi(unsigned char vic, unsigned char output_color)
+{
+       int i;
+       char info[SIZE_AVI_INFOFRAME];
+       
+       memset(info, 0, SIZE_AVI_INFOFRAME);
+       HDMIWrReg(CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
+       info[0] = 0x82;
+       info[1] = 0x02;
+       info[2] = 0x0D; 
+       info[3] = info[0] + info[1] + info[2];
+       info[4] = (AVI_COLOR_MODE_RGB << 5);
+       info[5] = (AVI_COLORIMETRY_NO_DATA << 6) | (AVI_CODED_FRAME_ASPECT_NO_DATA << 4) | ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME;
+       info[6] = 0;
+       info[7] = vic;
+       info[8] = 0;
+
+       // Calculate AVI InfoFrame ChecKsum
+       for (i = 4; i < SIZE_AVI_INFOFRAME; i++)
+       {
+       info[3] += info[i];
+       }
+       info[3] = 0x100 - info[3];
+       
+       for(i = 0; i < SIZE_AVI_INFOFRAME; i++)
+               HDMIWrReg(CONTROL_PACKET_ADDR + i, info[i]);
+}
+
+static int rk2928_hdmi_config_video(struct hdmi_video_para *vpara)
+{
+       int value;
+       struct fb_videomode *mode;
+       
+       hdmi_dbg(hdmi->dev, "[%s]\n", __FUNCTION__);
+       if(vpara == NULL) {
+               hdmi_err(hdmi->dev, "[%s] input parameter error\n", __FUNCTION__);
+               return -1;
+       }
+       
+       if(hdmi->hdcp_power_off_cb)
+               hdmi->hdcp_power_off_cb();
+               // Diable video and audio output
+       HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
+       
+       // Input video mode is SDR RGB24bit, Data enable signal from external
+       HDMIWrReg(VIDEO_CONTRL1, v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444) | v_DE_EXTERNAL);
+       HDMIWrReg(VIDEO_CONTRL2, v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) | (vpara->output_color & 0xFF));
+
+       // Set HDMI Mode
+       HDMIWrReg(HDCP_CTRL, v_HDMI_DVI(vpara->output_mode));
+
+       // Enable or disalbe color space convert
+       if(vpara->input_color != vpara->output_color) {
+               value = v_SOF_DISABLE | v_CSC_ENABLE;
+       }
+       else
+               value = v_SOF_DISABLE;
+       HDMIWrReg(VIDEO_CONTRL3, value);
+
+       // Set ext video
+#if 1
+       HDMIWrReg(VIDEO_TIMING_CTL, 0);
+       mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
+       if(mode == NULL)
+       {
+               hdmi_err(hdmi->dev, "[%s] not found vic %d\n", __FUNCTION__, vpara->vic);
+               return -ENOENT;
+       }
+       hdmi->tmdsclk = mode->pixclock;
+#else
+       value = v_EXTERANL_VIDEO(1) | v_INETLACE(mode->vmode);
+       if(mode->sync & FB_SYNC_HOR_HIGH_ACT)
+               value |= v_HSYNC_POLARITY(1);
+       if(mode->sync & FB_SYNC_VERT_HIGH_ACT)
+               value |= v_VSYNC_POLARITY(1);
+       HDMIWrReg(VIDEO_TIMING_CTL, value);
+       
+       value = mode->left_margin + mode->xres + mode->right_margin + mode->hsync_len;
+       HDMIWrReg(VIDEO_EXT_HTOTAL_L, value & 0xFF);
+       HDMIWrReg(VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
+       
+       value = mode->left_margin + mode->right_margin + mode->hsync_len;
+       HDMIWrReg(VIDEO_EXT_HBLANK_L, value & 0xFF);
+       HDMIWrReg(VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
+       
+       value = mode->left_margin + mode->hsync_len;
+       HDMIWrReg(VIDEO_EXT_HDELAY_L, value & 0xFF);
+       HDMIWrReg(VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
+       
+       value = mode->hsync_len;
+       HDMIWrReg(VIDEO_EXT_HDURATION_L, value & 0xFF);
+       HDMIWrReg(VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
+       
+       value = mode->upper_margin + mode->yres + mode->lower_margin + mode->vsync_len;
+       HDMIWrReg(VIDEO_EXT_VTOTAL_L, value & 0xFF);
+       HDMIWrReg(VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
+       
+       value = mode->upper_margin + mode->vsync_len + mode->lower_margin;
+       HDMIWrReg(VIDEO_EXT_VBLANK, value & 0xFF);
+
+       if(vpara->vic == HDMI_720x480p_60Hz_4_3 || vpara->vic == HDMI_720x480p_60Hz_16_9)
+               value = 42;
+       else
+               value = mode->upper_margin + mode->vsync_len;
+
+       HDMIWrReg(VIDEO_EXT_VDELAY, value & 0xFF);
+       
+       value = mode->vsync_len;
+       HDMIWrReg(VIDEO_EXT_VDURATION, value & 0xFF);
+#endif
+       
+       if(vpara->output_mode == OUTPUT_HDMI) {
+               rk2928_hdmi_config_avi(vpara->vic, vpara->output_color);
+               hdmi_dbg(hdmi->dev, "[%s] sucess output HDMI.\n", __FUNCTION__);
+       }
+       else {
+               hdmi_dbg(hdmi->dev, "[%s] sucess output DVI.\n", __FUNCTION__); 
+       }
+       // Power on TMDS
+       HDMIWrReg(PHY_PRE_EMPHASIS, v_PRE_EMPHASIS(0) | v_TMDS_PWRDOWN(0)); // TMDS power on
+       
+       // Enable TMDS
+       value = HDMIRdReg(PHY_DRIVER);
+       value |= v_TX_ENABLE(1);
+       HDMIWrReg(PHY_DRIVER, value);
+
+       return 0;
+}
+
+static void rk2928_hdmi_config_aai(void)
+{
+       int i;
+       char info[SIZE_AUDIO_INFOFRAME];
+       
+       memset(info, 0, SIZE_AUDIO_INFOFRAME);
+       
+       info[0] = 0x84;
+       info[1] = 0x01;
+       info[2] = 0x0A;
+       
+       info[3] = info[0] + info[1] + info[2];  
+       for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)
+       info[3] += info[i];
+       
+       info[3] = 0x100 - info[3];
+       
+       HDMIWrReg(CONTROL_PACKET_BUF_INDEX, INFOFRAME_AAI);
+       for(i = 0; i < SIZE_AUDIO_INFOFRAME; i++)
+               HDMIWrReg(CONTROL_PACKET_ADDR + i, info[i]);
+}
+
+static int rk2928_hdmi_config_audio(struct hdmi_audio *audio)
+{
+       int rate, N, channel, mclk_fs;
+       
+       if(audio->channel < 3)
+               channel = I2S_CHANNEL_1_2;
+       else if(audio->channel < 5)
+               channel = I2S_CHANNEL_3_4;
+       else if(audio->channel < 7)
+               channel = I2S_CHANNEL_5_6;
+       else
+               channel = I2S_CHANNEL_7_8;
+               
+       switch(audio->rate)
+       {
+               case HDMI_AUDIO_FS_32000:
+                       rate = AUDIO_32K;
+                       N = N_32K;
+                       mclk_fs = MCLK_384FS;
+                       break;
+               case HDMI_AUDIO_FS_44100:
+                       rate = AUDIO_441K;
+                       N = N_441K;
+                       mclk_fs = MCLK_256FS;
+                       break;
+               case HDMI_AUDIO_FS_48000:
+                       rate = AUDIO_48K;
+                       N = N_48K;
+                       mclk_fs = MCLK_256FS;
+                       break;
+               case HDMI_AUDIO_FS_88200:
+                       rate = AUDIO_882K;
+                       N = N_882K;
+                       mclk_fs = MCLK_128FS;
+                       break;
+               case HDMI_AUDIO_FS_96000:
+                       rate = AUDIO_96K;
+                       N = N_96K;
+                       mclk_fs = MCLK_128FS;
+                       break;
+               case HDMI_AUDIO_FS_176400:
+                       rate = AUDIO_1764K;
+                       N = N_1764K;
+                       mclk_fs = MCLK_128FS;
+                       break;
+               case HDMI_AUDIO_FS_192000:
+                       rate = AUDIO_192K;
+                       N = N_192K;
+                       mclk_fs = MCLK_128FS;
+                       break;
+               default:
+                       dev_err(hdmi->dev, "[%s] not support such sample rate %d\n", __FUNCTION__, audio->rate);
+                       return -ENOENT;
+       }
+
+       //set_audio source I2S
+       HDMIWrReg(AUDIO_CTRL1, 0x00); //internal CTS, disable down sample, i2s input, disable MCLK
+       HDMIWrReg(AUDIO_SAMPLE_RATE, rate);
+       HDMIWrReg(AUDIO_I2S_MODE, v_I2S_MODE(I2S_STANDARD) | v_I2S_CHANNEL(channel) );  
+       HDMIWrReg(AUDIO_I2S_MAP, 0x00); 
+       HDMIWrReg(AUDIO_I2S_SWAPS_SPDIF, 0); // no swap 
+               
+    //Set N value
+    HDMIWrReg(AUDIO_N_H, (N >> 16) & 0x0F);
+    HDMIWrReg(AUDIO_N_M, (N >> 8) & 0xFF); 
+       HDMIWrReg(AUDIO_N_L, N & 0xFF);    
+    rk2928_hdmi_config_aai();
+    
+    return 0;
+}
+
+static void rk2928_hdmi_control_output(int enable)
+{
+       char mutestatus = 0;
+       
+       if(enable) {
+               mutestatus = HDMIRdReg(AV_MUTE);
+               if(mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) {
+                       HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
+               rk2928_hdmi_sys_power_up();
+               rk2928_hdmi_sys_power_down();
+               rk2928_hdmi_sys_power_up();
+                       if(analog_sync){
+                               HDMIWrReg(0xce, 0x00);
+                               delay100us();
+                               HDMIWrReg(0xce, 0x01);
+                               analog_sync = 0;
+                       }
+               }
+       }
+       else {
+               HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
+       }
+}
+
+int rk2928_hdmi_removed(void)
+{
+
+       dev_printk(KERN_INFO , hdmi->dev , "Removed.\n");
+       rk2928_hdmi_set_pwr_mode(LOWER_PWR);
+
+       return HDMI_ERROR_SUCESS;
+}
+
+
+irqreturn_t hdmi_irq(int irq, void *priv)
+{              
+       char interrupt1 = 0;
+       unsigned long flags;
+       spin_lock_irqsave(&hdmi->irq_lock,flags);
+       interrupt1 = HDMIRdReg(INTERRUPT_STATUS1);
+       HDMIWrReg(INTERRUPT_STATUS1, interrupt1);
+#if 1
+               hdmi_dbg(hdmi->dev, "[%s] interrupt1 %02x interrupt2 %02x \n",\
+                        __FUNCTION__, interrupt1, interrupt2);
+#endif
+       if(interrupt1 & m_INT_HOTPLUG ){
+               if(hdmi->state == HDMI_SLEEP)
+                       hdmi->state = WAIT_HOTPLUG;
+               if(hdmi->pwr_mode == LOWER_PWR)
+                       rk2928_hdmi_set_pwr_mode(NORMAL);
+               queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));   
+       }else if(interrupt1 & m_INT_EDID_READY) {
+               edid_result = interrupt1;
+       }else if(hdmi->state == HDMI_SLEEP) {
+               hdmi_dbg(hdmi->dev, "hdmi return to sleep mode\n");
+               rk2928_hdmi_set_pwr_mode(LOWER_PWR);
+       }
+#if 0
+       if(hdmi->hdcp_irq_cb)
+               hdmi->hdcp_irq_cb(interrupt2);
+#endif
+       spin_unlock_irqrestore(&hdmi->irq_lock,flags);
+       return IRQ_HANDLED;
+}
+
+int rk2928_hdmi_initial(void)
+{
+       int rc = HDMI_ERROR_SUCESS;
+
+       hdmi->pwr_mode = NORMAL;
+       hdmi->hdmi_removed = rk2928_hdmi_removed ;
+       hdmi->control_output = rk2928_hdmi_control_output;
+       hdmi->config_video = rk2928_hdmi_config_video;
+       hdmi->config_audio = rk2928_hdmi_config_audio;
+       hdmi->detect_hotplug = rk2928_hdmi_detect_hotplug;
+       hdmi->read_edid = rk2928_hdmi_read_edid;
+       // internal hclk = hdmi_hclk/20
+       //HDMIWrReg(0x800, HDMI_INTERANL_CLK_DIV);
+       
+       if(hdmi->hdcp_power_on_cb)
+               rc = hdmi->hdcp_power_on_cb();
+
+       return rc;
+}
diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hw.h b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hw.h
new file mode 100644 (file)
index 0000000..6fd0f95
--- /dev/null
@@ -0,0 +1,248 @@
+#ifndef _RK2928_HDMI_HW_H
+#define _RK2928_HDMI_HW_H
+
+enum PWR_MODE{
+    NORMAL,
+    LOWER_PWR,
+};
+enum {
+               OUTPUT_DVI = 0,
+               OUTPUT_HDMI
+       };
+#define SYS_CTRL                                       0x00
+       #define m_INT_POL                               (1 << 0)
+       #define m_POWER                                 (1 << 1)
+       #define m_REG_CLK_SOURCE                (1 << 2)
+       #define v_INT_POL_HIGH                  1
+       #define v_INT_POL_LOW                   0
+       #define v_PWR_ON                                (0 << 1)
+       #define v_PWR_OFF                               (1 << 1)
+       #define v_REG_CLK_SOURCE_TMDS   (0 << 2)
+       #define v_REG_CLK_SOURCE_IIS    (1 << 2)
+#define VIDEO_CONTRL1                          0x01
+       #define m_VIDEO_INPUT_FORMAT    (7 << 1)
+       #define m_DE_SOURCE                             (1 << 0)
+       enum {
+               VIDEO_INPUT_SDR_RGB444 = 0,
+               VIDEO_INPUT_DDR_RGB444 = 5,
+               VIDEO_INPUT_DDR_YCBCR422 = 6                    
+       };
+       #define v_VIDEO_INPUT_FORMAT(n) (n << 1)
+       #define v_DE_EXTERNAL                   1
+       #define v_DE_INTERANL                   0
+       
+#define VIDEO_CONTRL2                          0x02
+       #define m_VIDEO_OUTPUT_FORMAT   (3 << 6)
+       #define m_VIDEO_INPUT_BITS              (3 << 4)
+       #define v_VIDEO_OUTPUT_FORMAT(n)(n << 6)
+       #define v_VIDEO_INPUT_BITS(n)   (n << 4)
+       enum{
+               VIDEO_INPUT_12BITS = 0,
+               VIDEO_INPUT_10BITS,
+               VIDEO_INPUT_8BITS
+       };
+#define VIDEO_CONTRL3                          0x04
+       #define m_SOF                                   (1 << 3)
+       #define m_CSC                                   (1 << 0)
+       #define v_SOF_ENABLE                    (0 << 3)
+       #define v_SOF_DISABLE                   (1 << 3)
+       #define v_CSC_ENABLE                    1
+       #define v_CSC_DISABLE                   0
+       
+#define AV_MUTE                                                0x05
+       #define m_AVMUTE_CLEAR                  (1 << 7)
+       #define m_AVMUTE_ENABLE                 (1 << 6)
+       #define m_AUDIO_MUTE                    (1 << 1)
+       #define m_VIDEO_BLACK                   (1 << 0)
+       #define v_AUDIO_MUTE(n)                 (n << 1)
+       #define v_VIDEO_MUTE(n)                 (n << 0)
+       
+#define VIDEO_TIMING_CTL                       0x08
+       #define v_HSYNC_POLARITY(n)             (n << 3)
+       #define v_VSYNC_POLARITY(n)             (n << 2)
+       #define v_INETLACE(n)                   (n << 1)
+       #define v_EXTERANL_VIDEO(n)             (n << 0)
+       
+#define VIDEO_EXT_HTOTAL_L                     0x09
+#define VIDEO_EXT_HTOTAL_H                     0x0a
+#define VIDEO_EXT_HBLANK_L                     0x0b
+#define VIDEO_EXT_HBLANK_H                     0x0c
+#define VIDEO_EXT_HDELAY_L                     0x0d
+#define VIDEO_EXT_HDELAY_H                     0x0e
+#define VIDEO_EXT_HDURATION_L          0x0f
+#define VIDEO_EXT_HDURATION_H          0x10
+#define VIDEO_EXT_VTOTAL_L                     0x11
+#define VIDEO_EXT_VTOTAL_H                     0x12
+#define VIDEO_EXT_VBLANK                       0x13
+#define VIDEO_EXT_VDELAY                       0x14
+#define VIDEO_EXT_VDURATION                    0x15
+
+#define AUDIO_CTRL1                                    0x35
+       enum {
+               CTS_SOURCE_INTERNAL = 0,
+               CTS_SOURCE_EXTERNAL
+       };
+       #define v_CTS_SOURCE(n)                 (n << 7)
+       enum {
+               DOWNSAMPLE_DISABLE = 0,
+               DOWNSAMPLE_1_2,
+               DOWNSAMPLE_1_4
+       };
+       #define v_DOWN_SAMPLE(n)                (n << 5)
+       enum {
+               AUDIO_SOURCE_IIS = 0,
+               AUDIO_SOURCE_SPDIF
+       };
+       #define v_AUDIO_SOURCE(n)               (n << 3)
+       #define v_MCLK_ENABLE(n)                (n << 2)
+       enum {
+               MCLK_128FS = 0,
+               MCLK_256FS,
+               MCLK_384FS,
+               MCLK_512FS
+       };
+       #define v_MCLK_RATIO(n)                 (n)
+       
+#define AUDIO_SAMPLE_RATE                      0x37
+       enum {
+               AUDIO_32K       = 0x3,
+               AUDIO_441K      = 0x0,
+               AUDIO_48K       = 0x2,
+               AUDIO_882K      = 0x8,
+               AUDIO_96K       = 0xa,
+               AUDIO_1764K     = 0xc,
+               AUDIO_192K      = 0xe,
+       };
+
+#define AUDIO_I2S_MODE                         0x38
+       enum {
+               I2S_CHANNEL_1_2 = 1,
+               I2S_CHANNEL_3_4 = 3,
+               I2S_CHANNEL_5_6 = 7,
+               I2S_CHANNEL_7_8 = 0xf
+       };
+       #define v_I2S_CHANNEL(n)                ((n) << 2)
+       enum {
+               I2S_STANDARD = 0,
+               I2S_LEFT_JUSTIFIED,
+               I2S_RIGHT_JUSTIFIED
+       };
+       #define v_I2S_MODE(n)                           (n)
+
+#define AUDIO_I2S_MAP                          0x39
+#define AUDIO_I2S_SWAPS_SPDIF          0x3a
+       #define v_SPIDF_FREQ(n)                 (n)     
+
+#define N_32K          0x1000
+#define N_441K                 0x1880
+#define N_882K                 0x3100
+#define N_1764K        0x6200
+#define N_48K          0x1800
+#define N_96K          0x3000
+#define N_192K                 0x6000
+
+#define AUDIO_N_H                                      0x3f
+#define AUDIO_N_M                                      0x40
+#define AUDIO_N_L                                      0x41
+
+#define AUDIO_CTS_H                                    0x45
+#define AUDIO_CTS_M                                    0x46
+#define AUDIO_CTS_L                                    0x47
+
+
+#define DDC_CLK_L                                      0x4b
+#define DDC_CLK_H                                      0x4c
+
+#define EDID_SEGMENT_POINTER   0x4d
+#define EDID_WORD_ADDR                 0x4e
+#define EDID_FIFO_OFFSET               0x4f
+#define EDID_FIFO_ADDR                 0x50
+
+/* CONTROL_PACKET_BUF_INDEX */
+#define CONTROL_PACKET_BUF_INDEX       0x9f
+enum {
+       INFOFRAME_AVI = 0x06,
+       INFOFRAME_AAI = 0x08
+};
+#define CONTROL_PACKET_ADDR                    0xa0
+
+
+#define SIZE_AVI_INFOFRAME                     0x11    // 14 bytes
+#define SIZE_AUDIO_INFOFRAME           0x0F    // 15 bytes
+enum {
+       AVI_COLOR_MODE_RGB = 0,
+       AVI_COLOR_MODE_YCBCR422,
+       AVI_COLOR_MODE_YCBCR444
+};
+enum {
+       AVI_COLORIMETRY_NO_DATA = 0,
+       AVI_COLORIMETRY_SMPTE_170M,
+       AVI_COLORIMETRY_ITU709,
+       AVI_COLORIMETRY_EXTENDED
+};
+enum {
+       AVI_CODED_FRAME_ASPECT_NO_DATA,
+       AVI_CODED_FRAME_ASPECT_4_3,
+       AVI_CODED_FRAME_ASPECT_16_9
+};
+enum {
+       ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME = 0x08,
+       ACTIVE_ASPECT_RATE_4_3,
+       ACTIVE_ASPECT_RATE_16_9,
+       ACTIVE_ASPECT_RATE_14_9
+};
+
+#define HDCP_CTRL                              0x52
+       #define m_HDMI_DVI                      (1 << 1)
+       #define v_HDMI_DVI(n)           (n << 1)
+
+#define INTERRUPT_MASK1                        0xc0
+#define INTERRUPT_STATUS1              0xc1
+       #define m_INT_HOTPLUG           (1 << 7)
+       #define m_INT_ACTIVE_VSYNC      (1 << 6)
+       #define m_INT_EDID_READY        (1 << 2)
+       
+#define INTERRUPT_MASK2                        0xc2
+#define INTERRUPT_STATUS2              0xc3
+       #define m_INT_HDCP_ERR          (1 << 7)
+       #define m_INT_BKSV_FLAG         (1 << 6)
+       #define m_INT_HDCP_OK           (1 << 4)
+
+#define HDMI_STATUS                            0xc8
+       #define m_HOTPLUG       (1 << 7)
+       #define m_DDC_SDA       (1 << 5)
+       #define m_DDC_SDC       (1 << 4)
+
+#define PHY_SYNC                               0xce            //sync phy parameter                            
+
+#define PHY_DRIVER                             0xe1
+       #define v_MAIN_DRIVER(n)        (n << 4)
+       #define v_PRE_DRIVER(n)         (n << 2)
+       #define v_TX_ENABLE(n)          (n << 1)
+       
+#define PHY_PRE_EMPHASIS               0xe2
+       #define v_PRE_EMPHASIS(n)       (n << 4)
+       #define v_TMDS_PWRDOWN(n)       (n)
+       
+#define PHY_PLL_TEST                   0xe3
+#define PHY_BANDGAP_PWR                        0xe4
+       #define v_BANDGAP_PWR_DOWN      0x03
+       #define v_BANDGAP_PWR_UP        0
+       
+#define PHY_PLL_CTRL                   0xe5
+       #define v_PLL_DISABLE(n)        (n << 4)
+       #define v_PLL_RESET(n)          (n << 3)
+       #define v_TMDS_RESET(n)         (n << 2)
+                       
+#define PHY_PLL_LDO_PWR                        0xe7
+       #define v_LDO_PWR_DOWN(n)       (n << 2)
+
+#define HDMIRdReg(addr)                                                __raw_readl(hdmi->regbase + addr)
+#define HDMIWrReg(addr, val)                   __raw_writel((val), hdmi->regbase + addr);
+#define HDMIMskReg(temp, addr, msk, val)       \
+       temp = __raw_readl(hdmi->regbase + addr) & (0xFF - (msk)) ; \
+       __raw_writel(temp | ( (val) & (msk) ),  hdmi->regbase + addr); 
+       
+extern int rk2928_hdmi_initial(void);
+
+#endif
diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hw.hbak b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hw.hbak
new file mode 100755 (executable)
index 0000000..fe06fe0
--- /dev/null
@@ -0,0 +1,497 @@
+#ifndef __RK2928_HDMI_HW_H__
+#define __RK2928_HDMI_HW_H__
+
+
+//0x00
+#define INT_POL       1
+#define SYS_PWR_ON    0
+#define SYS_PWR_OFF   1
+#define PHY_CLK       0
+#define SYS_CLK       1
+
+#define MCLK_FS       0x01    //256fs
+//0x01
+// INPUT_VIDEO_FORMAT
+#define RGB_YUV444          0x00
+#define DDR_RGB444_YUV444   0x05
+#define DDR_YUV422          0x06
+
+//0x02
+//video output format
+#define RGB444              0x00
+#define YUV444              0x01
+#define YUV422              0x02
+
+//DATA WIDTH
+#define DATA_12BIT          0X00
+#define DATA_10BIT          0X01
+#define DATA_8BIT           0X03
+
+//0X04
+//1:after 0:not After 1st sof for external DE sample
+#define DE_AFTER_SOF        0
+#define DE_NOAFTER_SOF      1
+
+#define CSC_ENABLE          0
+#define CSC_DISABLE         1
+
+//0X05
+#define CLEAR_AVMUTE(x)        (x)<<7
+#define SET_AVMUTE(x)          (x)<<6
+#define AUDIO_MUTE(x)          (x)<<1
+#define VIDEO_BLACK(x)         (x)<<0    //1:black 0:normal
+
+//0x08
+#define VSYNC_POL(x)            (x)<<3   //0:Negative 1:Positive
+#define HSYNC_POL(x)            (x)<<2      //0:Negative 1:Positive
+#define INTER_PROGRESSIVE(x)    (x)<<1  //0: progressive 1:interlace
+#define VIDEO_SET_ENABLE(x)     (x)<<0  //0:disable 1: enable
+
+/*          0xe1        */  
+//Main-driver strength :0000~1111: the strength from low to high
+#define M_DRIVER_STR(x)         (((x)&0xf)<<4)
+//Pre-driver strength  :00~11: the strength from low to high
+#define P_DRIVER_STR(x)         (((x)&3)<<2)
+//TX driver enable  1: enable   0: disable
+#define TX_DRIVER_EN(x)         (((x)&1)<<1)
+/*          0xe2        */ 
+//Pre-emphasis strength 00~11: the strength from 0 to high
+#define P_EMPHASIS_STR(x)       (((x)&3)<<4)
+//Power down TMDS driver      1: power down. 0: not
+#define PWR_DOWN_TMDS(x)        (((x)&1)<<0)
+/*          0xe3        */ 
+//PLL out enable.   Just for test. need set to 1’b0
+#define PLL_OUT_EN(x)           (((x)&1)<<7)
+/*          0xe4        */
+// Band-Gap power down  11: power down  00: not
+#define BAND_PWR(x)             (((x)&3)<<0)
+/*          0xe5        */ 
+//PLL disable   1: disable  0: enable
+#define PLL_PWR(x)              (((x)&1)<<4)
+//  PLL reset   1: reset    0: not
+#define PLL_RST(x)              (((x)&1)<<3)
+//PHY TMDS channels reset   1: reset    0: not
+#define TMDS_RST(x)             (((x)&1)<<2)
+/*          0xe7        */ 
+// PLL LDO power down   1: power down   0: not
+#define PLL_LDO_PWR(x)      (((x)&1)<<2) 
+
+enum PWR_MODE{
+    NORMAL,
+    LOWER_PWR,
+};
+
+#if 0
+/* HDMI_SYS_CONTROL */
+#define SYS_CTRL       0x0
+
+enum {
+       PWR_SAVE_MODE_A = 1,
+       PWR_SAVE_MODE_B = 2,
+       PWR_SAVE_MODE_D = 4,
+       PWR_SAVE_MODE_E = 8
+};
+#define m_PWR_SAVE_MODE                0xF0
+#define v_PWR_SAVE_MODE(n)     (n << 4)
+#define PLL_B_RESET                    (1 << 3)
+
+#define N_32K          0x1000
+#define N_441K                 0x1880
+#define N_882K                 0x3100
+#define N_1764K        0x6200
+#define N_48K          0x1800
+#define N_96K          0x3000
+#define N_192K                 0x6000
+
+#define LR_SWAP_N3                     0x04
+#define N_2                                    0x08
+#define N_1                                    0x0c
+
+#define AUDIO_CTRL1                    0x28
+#define AUDIO_CTRL2            0x2c
+#define I2S_AUDIO_CTRL         0x30
+enum {
+       I2S_MODE_STANDARD = 0,
+       I2S_MODE_RIGHT_JUSTIFIED,
+       I2S_MODE_LEFT_JUSTIFIED
+};
+#define v_I2S_MODE(n)          n
+enum {
+       I2S_CHANNEL_1_2 = 1,
+       I2S_CHANNEL_3_4 = 3,
+       I2S_CHANNEL_5_6 = 7,
+       I2S_CHANNEL_7_8 = 0xf
+};
+#define v_I2S_CHANNEL(n)       ( (n) << 2 )
+
+#define I2S_INPUT_SWAP         0x40
+
+#define SRC_NUM_AUDIO_LEN      0x50
+
+/* HDMI_AV_CTRL1*/
+#define AV_CTRL1       0x54
+enum {
+       AUDIO_32K       = 0x3,
+       AUDIO_441K      = 0x0,
+       AUDIO_48K       = 0x2,
+       AUDIO_882K      = 0x8,
+       AUDIO_96K       = 0xa,
+       AUDIO_1764K     = 0xc,
+       AUDIO_192K      = 0xe,
+};
+#define m_AUDIO_SAMPLE_RATE            0xF0
+#define v_AUDIO_SAMPLE_RATE(n) (n << 4)
+#define m_INPUT_VIDEO_MODE                     (7 << 1)
+#define v_INPUT_VIDEO_MODE(n)          (n << 1)
+enum {
+       INTERNAL_DE = 0,
+       EXTERNAL_DE
+};
+#define m_DE_SIGNAL_SELECT                     (1 << 0)
+
+/* HDMI_AV_CTRL2 */
+#define AV_CTRL2       0xec
+#define m_CSC_ENABLE                           (1 << 0)
+#define v_CSC_ENABLE(n)                                (n)
+
+/* HDMI_VIDEO_CTRL1 */
+#define VIDEO_CTRL1    0x58
+
+#define m_VIDEO_OUTPUT_MODE            (0x3 << 6)
+#define v_VIDEO_OUTPUT_MODE(n) (n << 6)
+enum {
+       VIDEO_INPUT_DEPTH_12BIT = 0,
+       VIDEO_INPUT_DEPTH_10BIT = 0x1,
+       VIDEO_INPUT_DEPTH_8BIT = 0x3
+};
+#define m_VIDEO_INPUT_DEPTH            (3 << 4)
+#define v_VIDEO_INPUT_DEPTH(n) (n << 4)
+enum {
+       VIDEO_EMBEDDED_SYNC_LOCATION_0 = 0,
+       VIDEO_EMBEDDED_SYNC_LOCATION_1,
+       VIDEO_EMBEDDED_SYNC_LOCATION_2
+};
+#define m_VIDEO_EMBEDDED_SYNC_LOCATION         (3 << 2)
+#define VIDEO_EMBEDDED_SYNC_LOCATION(n)                (n << 2)
+#define m_VIDEO_INPUT_COLOR_MODE                       (1 << 0)
+
+/* DEEP_COLOR_MODE */
+#define DEEP_COLOR_MODE        0x5c
+enum{
+       TMDS_CLOCK_MODE_8BIT = 0,
+       TMDS_CLOKK_MODE_10BIT,
+       TMDS_CLOKK_MODE_12BIT
+};
+#define TMDS_CLOCK_MODE_MASK   0x3 << 6
+#define TMDS_CLOCK_MODE(n)             (n) << 6
+
+/* VIDEO_CTRL2 */
+#define VIDEO_SETTING2 0x114
+#define m_UNMUTE                                       (1 << 7)
+#define m_MUTE                                         (1 << 6)
+#define m_AUDIO_RESET                          (1 << 2)
+#define m_NOT_SEND_AUDIO                       (1 << 1)
+#define m_NOT_SEND_VIDEO                       (1 << 0)
+#define AV_UNMUTE                                      (1 << 7)                // Unmute video and audio, send normal video and audio data
+#define AV_MUTE                                                (1 << 6)                // Mute video and audio, send black video data and silent audio data
+#define AUDIO_CAPTURE_RESET                    (1 << 2)                // Reset audio process logic, only available in pwr_e mode.
+#define NOT_SEND_AUDIO                         (1 << 1)                // Send silent audio data
+#define NOT_SEND_VIDEO                         (1 << 0)                // Send black video data
+
+/* Color Space Convertion Parameter*/
+#define CSC_PARA_C0_H  0x60
+#define CSC_PARA_C0_L  0x64
+#define CSC_PARA_C1_H  0x68
+#define CSC_PARA_C1_L  0x6c
+#define CSC_PARA_C2_H  0x70
+#define CSC_PARA_C2_L  0x74
+#define CSC_PARA_C3_H  0x78
+#define CSC_PARA_C3_L  0x7c
+#define CSC_PARA_C4_H  0x80
+#define CSC_PARA_C4_L  0x84
+#define CSC_PARA_C5_H  0x88
+#define CSC_PARA_C5_L  0x8c
+#define CSC_PARA_C6_H  0x90
+#define CSC_PARA_C6_L  0x94
+#define CSC_PARA_C7_H  0x98
+#define CSC_PARA_C7_L  0x9c
+#define CSC_PARA_C8_H  0xa0
+#define CSC_PARA_C8_L  0xa4
+#define CSC_PARA_C9_H  0xa8
+#define CSC_PARA_C9_L  0xac
+#define CSC_PARA_C10_H 0xac
+#define CSC_PARA_C10_L 0xb4
+#define CSC_PARA_C11_H 0xb8
+#define CSC_PARA_C11_L 0xbc
+
+#define CSC_CONFIG1            0x34c
+#define m_CSC_MODE                     (1 << 7)
+#define m_CSC_COEF_MODE        (0xF << 3)      //Only used in auto csc mode
+#define m_CSC_STATUS           (1 << 2)
+#define m_CSC_VID_SELECT       (1 << 1)
+#define m_CSC_BRSWAP_DIABLE    (1)
+
+enum {
+       CSC_MODE_MANUAL = 0,
+       CSC_MODE_AUTO
+};
+#define v_CSC_MODE(n)                  (n << 7)
+enum {
+       COE_SDTV_LIMITED_RANGE = 0x08,
+       COE_SDTV_FULL_RANGE = 0x04,
+       COE_HDTV_60Hz = 0x2,
+       COE_HDTV_50Hz = 0x1
+};
+#define v_CSC_COE_MODE(n)              (n << 3)
+enum {
+       CSC_INPUT_VID_5_19 = 0,
+       CSC_INPUT_VID_28_29
+};
+#define v_CSC_VID_SELECT(n)            (n << 1)
+#define v_CSC_BRSWAP_DIABLE(n) (n)
+#endif
+/* CONTROL_PACKET_BUF_INDEX */
+#define CONTROL_PACKET_BUF_INDEX       0x17c
+enum {
+       INFOFRAME_AVI = 0x06,
+       INFOFRAME_AAI = 0x08
+};
+#define CONTROL_PACKET_HB0                     0x180
+#define CONTROL_PACKET_HB1                     0x184
+#define CONTROL_PACKET_HB2                     0x188
+#define CONTROL_PACKET_PB_ADDR         0x18c
+#define SIZE_AVI_INFOFRAME                     0x11    // 17 bytes
+#define SIZE_AUDIO_INFOFRAME           0x0F    // 15 bytes
+enum {
+       AVI_COLOR_MODE_RGB = 0,
+       AVI_COLOR_MODE_YCBCR422,
+       AVI_COLOR_MODE_YCBCR444
+};
+enum {
+       AVI_COLORIMETRY_NO_DATA = 0,
+       AVI_COLORIMETRY_SMPTE_170M,
+       AVI_COLORIMETRY_ITU709,
+       AVI_COLORIMETRY_EXTENDED
+};
+enum {
+       AVI_CODED_FRAME_ASPECT_NO_DATA,
+       AVI_CODED_FRAME_ASPECT_4_3,
+       AVI_CODED_FRAME_ASPECT_16_9
+};
+enum {
+       ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME = 0x08,
+       ACTIVE_ASPECT_RATE_4_3,
+       ACTIVE_ASPECT_RATE_16_9,
+       ACTIVE_ASPECT_RATE_14_9
+};
+#if 0
+/* External Video Parameter Setting*/
+#define EXT_VIDEO_PARA                 0xC0
+#define m_VSYNC_OFFSET                 (0xF << 4)
+#define m_VSYNC_POLARITY               (1 << 3)
+#define m_HSYNC_POLARITY               (1 << 2)
+#define m_INTERLACE                            (1 << 1)
+#define m_EXT_VIDEO_ENABLE             (1 << 0)
+
+#define v_VSYNC_OFFSET(n)              (n << 4)
+#define v_VSYNC_POLARITY(n)            (n << 3)
+#define v_HSYNC_POLARITY(n)            (n << 2)
+#define v_INTERLACE(n)                 (n << 1)
+#define v_EXT_VIDEO_ENABLE(n)  (n << 0) 
+
+#define EXT_VIDEO_PARA_HTOTAL_L                0xC4
+#define EXT_VIDEO_PARA_HTOTAL_H                0xC8
+#define EXT_VIDEO_PARA_HBLANK_L                0xCC
+#define EXT_VIDEO_PARA_HBLANK_H                0xD0
+#define EXT_VIDEO_PARA_HDELAY_L                0xD4
+#define EXT_VIDEO_PARA_HDELAY_H                0xD8
+#define EXT_VIDEO_PARA_HSYNCWIDTH_L    0xDC
+#define EXT_VIDEO_PARA_HSYNCWIDTH_H    0xE0
+
+#define EXT_VIDEO_PARA_VTOTAL_L                0xE4
+#define EXT_VIDEO_PARA_VTOTAL_H                0xE8
+#define EXT_VIDEO_PARA_VBLANK_L                0xF4
+#define EXT_VIDEO_PARA_VDELAY          0xF8
+#define EXT_VIDEO_PARA_VSYNCWIDTH      0xFC
+
+#define PHY_PLL_SPEED                          0x158
+       #define v_TEST_EN(n)                    (n << 6)
+       #define v_PLLA_BYPASS(n)                (n << 4)
+       #define v_PLLB_SPEED(n)                 (n << 2)
+       #define v_PLLA_SPEED(n)                 (n)
+       enum {
+               PLL_SPEED_LOWEST = 0,
+               PLL_SPEED_MIDLOW,
+               PLL_SPEED_MIDHIGH,
+               PLL_SPEED_HIGHEST
+       };
+
+#define PHY_PLL_17                                     0x15c           // PLL A & B config bit 17
+       #define v_PLLA_BIT17(n)                 (n << 2)
+       #define v_PLLB_BIT17(n)                 (n << 1)
+       
+#define PHY_BGR                                                0x160
+       #define v_BGR_DISCONNECT(n)             (n << 7)
+       #define v_BGR_V_OFFSET(n)               (n << 4)
+       #define v_BGR_I_OFFSET(n)               (n)
+
+#define PHY_PLLA_1                                     0x164
+#define PHY_PLLA_2                                     0x168
+#define PHY_PLLB_1                                     0x16c
+#define PHY_PLLB_2                                     0x170
+
+#define PHY_DRIVER_PREEMPHASIS         0x174
+       #define v_TMDS_SWING(n)                 (n << 4)
+       #define v_PRE_EMPHASIS(n)               (n)
+       
+#define PHY_PLL_16_AML                         0x178           // PLL A & B config bit 16 and AML control
+       #define v_PLLA_BIT16(n)                 (n << 5)
+       #define v_PLLB_BIT16(n)                 (n << 4)
+       #define v_AML(n)                                (n)
+#endif
+/* Interrupt Setting */
+#define INTR_MASK1                                     0xc0
+#define INTR_STATUS1                           0xc1
+       #define m_INT_HOTPLUG                           (1 << 7)
+       #define m_INT_VSYNC                                     (1 << 5)
+       #define m_INT_EDID_READY                        (1 << 2)
+
+#define INTR_MASK2                                     0xc2
+#define INTR_STATUS2                           0xc3
+       #define m_INT_HDCP_ERR                          (1 << 7)        // HDCP error detected
+       #define m_INT_BKSV_RPRDY                        (1 << 6)        // BKSV list ready from repeater
+       #define m_INT_AUTH_DONE                         (1 << 4)        // HDCP authentication done
+
+#if 0
+#define DDC_READ_FIFO_ADDR                     0x200
+#define DDC_BUS_FREQ_L                         0x204
+#define DDC_BUS_FREQ_H                         0x208
+#define DDC_BUS_CTRL                           0x2dc
+#define DDC_I2C_LEN                                    0x278
+#define DDC_I2C_OFFSET                         0x280
+#define DDC_I2C_CTRL                           0x284
+#define DDC_I2C_READ_BUF0                      0x288
+#define DDC_I2C_READ_BUF1                      0x28c
+#define DDC_I2C_READ_BUF2                      0x290
+#define DDC_I2C_READ_BUF3                      0x294
+#define DDC_I2C_WRITE_BUF0                     0x298
+#define DDC_I2C_WRITE_BUF1                     0x29c
+#define DDC_I2C_WRITE_BUF2                     0x2a0
+#define DDC_I2C_WRITE_BUF3                     0x2a4
+#define DDC_I2C_WRITE_BUF4                     0x2ac
+#define DDC_I2C_WRITE_BUF5                     0x2b0
+#define DDC_I2C_WRITE_BUF6                     0x2b4
+
+#endif
+#define EDID_SEGMENT_POINTER           0x4d
+#define EDID_WORD_ADDR                         0x4e
+#define EDID_FIFO_ADDR                         0x4f
+
+#define PIN_STATUS                             0xc8
+#define m_HOTPLUG_STATUS                       (1 << 7)
+#define m_DDCSDA_STATUS                (1 << 5)
+#define m_DDCSCL_STATUS                (1 << 4)
+#if 0
+/* HDCP_CTRL */
+#define HDCP_CTRL              0x2bc
+       enum {
+               OUTPUT_DVI = 0,
+               OUTPUT_HDMI
+       };
+       #define m_HDCP_AUTH_START                       (1 << 7)        // start hdcp
+       #define m_HDCP_BKSV_PASS                        (1 << 6)        // bksv valid
+       #define m_HDCP_BKSV_FAILED                      (1 << 5)        // bksv invalid
+       #define m_HDCP_FRAMED_ENCRYPED          (1 << 4)
+       #define m_HDCP_AUTH_STOP                        (1 << 3)        // stop hdcp
+       #define m_HDCP_ADV_CIPHER                       (1 << 2)        // advanced cipher mode
+       #define m_HDMI_DVI                                      (1 << 1)
+       #define m_HDCP_RESET                            (1 << 0)        // reset hdcp
+       #define v_HDCP_AUTH_START(n)            (n << 7)
+       #define v_HDCP_BKSV_PASS(n)                     (n << 6)
+       #define v_HDCP_BKSV_FAILED(n)           (n << 5)
+       #define v_HDCP_FRAMED_ENCRYPED(n)       (n << 4)
+       #define v_HDCP_AUTH_STOP(n)                     (n << 3)
+       #define v_HDCP_ADV_CIPHER(n)            (n << 2)
+       #define v_HDMI_DVI(n)                           (n << 1)
+       #define v_HDCP_RESET(n)                         (n << 0)
+#define HDCP_CTRL2             0x340
+
+/* HDCP Key Memory Access Control */
+#define HDCP_KEY_ACCESS_CTRL1  0x338
+#define HDCP_KEY_ACCESS_CTRL2  0x33c
+       #define m_LOAD_FACSIMILE_HDCP_KEY       (1 << 1)
+       #define m_LOAD_HDCP_KEY                         (1 << 0)
+/* HDCP Key Memory Control */
+#define HDCP_KEY_MEM_CTRL      0x348
+       #define m_USE_KEY1              (1 << 6)
+       #define m_USE_KEY2              (1 << 5)
+       #define m_LOAD_AKSV             (1 << 4)
+       #define m_KSV_SELECTED  (1 << 3)
+       #define m_KSV_VALID             (1 << 2)
+       #define m_KEY_VALID             (1 << 1)
+       #define m_KEY_READY             (1 << 0)
+       #define v_USE_KEY1(n)   (n << 6)
+       #define v_USE_KEY2(n)   (n << 5)
+       #define v_LOAD_AKSV(n)  (n << 4)
+
+/* HDCP B device capacity */
+#define HDCP_BCAPS                             0x2f8
+       #define m_HDMI_RECEIVED                 (1 << 7) //If HDCP receiver support HDMI, this bit must be 1.
+       #define m_REPEATER                              (1 << 6)
+       #define m_KSV_FIFO_READY                (1 << 5)
+       #define m_DDC_FAST                              (1 << 4)
+       #define m_1_1_FEATURE                   (1 << 1)
+       #define m_FAST_REAUTHENTICATION (1 << 0) //For HDMI, this function is supported whether this bit is enabled or not.
+
+/* HDCP KSV Value */
+#define HDCP_KSV_BYTE0                 0x2fc
+#define HDCP_KSV_BYTE1                 0x300
+#define HDCP_KSV_BYTE2                 0x304
+#define HDCP_KSV_BYTE3                 0x308
+#define HDCP_KSV_BYTE4                 0x30c
+
+/* HDCP error status */
+#define HDCP_ERROR                             0x320
+
+/* HDCP 100 ms timer */
+#define HDCP_TIMER_100MS               0x324
+/* HDCP 5s timer */
+#define HDCP_TIMER_5S                  0x328
+
+/* HDCP Key ram address */
+#define HDCP_RAM_KEY_KSV1              0x400
+#define HDCP_RAM_KEY_KSV2              0x407
+#define HDCP_RAM_KEY_PRIVATE   0x40e
+#define HDCP_KEY_LENGTH                        0x13C
+
+
+#define HDCP_ENABLE_HW_AUTH            // Enable hardware authentication mode  
+#define HDMI_INTERANL_CLK_DIV  0x19
+
+#define HDMIRdReg(addr)                                                __raw_readl(hdmi->regbase + addr)
+#define HDMIWrReg(addr, val)                   __raw_writel((val), hdmi->regbase + addr);
+#define HDMIMskReg(temp, addr, msk, val)       \
+       temp = __raw_readl(hdmi->regbase + addr) & (0xFF - (msk)) ; \
+       __raw_writel(temp | ( (val) & (msk) ),  hdmi->regbase + addr); 
+
+
+
+/* Color Space Convertion Mode */
+enum {
+       CSC_RGB_0_255_TO_ITU601_16_235 = 0,     //RGB 0-255 input to YCbCr 16-235 output according BT601
+       CSC_RGB_0_255_TO_ITU709_16_235,         //RGB 0-255 input to YCbCr 16-235 output accroding BT709
+       CSC_ITU601_16_235_TO_RGB_16_235,        //YCbCr 16-235 input to RGB 16-235 output according BT601
+       CSC_ITU709_16_235_TO_RGB_16_235,        //YCbCr 16-235 input to RGB 16-235 output according BT709
+       CSC_ITU601_16_235_TO_RGB_0_255,         //YCbCr 16-235 input to RGB 0-255 output according BT601
+       CSC_ITU709_16_235_TO_RGB_0_255          //YCbCr 16-235 input to RGB 0-255 output according BT709
+};
+#endif
+extern int rk2928_hdmi_initial(void);
+extern int rk2928_hdmi_detect_hotplug(void);
+extern int rk2928_hdmi_read_edid(int block, unsigned char *buff);
+extern int rk2928_hdmi_removed(void);
+extern int rk2928_hdmi_config_video(struct hdmi_video_para *vpara);
+extern int rk2928_hdmi_config_audio(struct hdmi_audio *audio);
+extern void rk2928_hdmi_control_output(int enable);
+
+#endif
diff --git a/drivers/video/rockchip/hdmi/chips/rk30/Kconfig b/drivers/video/rockchip/hdmi/chips/rk30/Kconfig
new file mode 100755 (executable)
index 0000000..c33318d
--- /dev/null
@@ -0,0 +1,15 @@
+config HDMI_RK30_CTL_CODEC
+               bool "Mute Codec When HDMI Actived"
+               depends on HDMI_RK30
+               default n
+               help
+                       If you say y heres, Codec will be mute when hdmi inserted,
+                       and unmute when removed. 
+
+config HDMI_RK30_DEBUG
+               bool "RK30 HDMI Debugging"
+        depends on HDMI_RK30 && LCDC_RK30
+        default n
+               help
+                 Enableds verbose debugging the the HDMI drivers
+
diff --git a/drivers/video/rockchip/hdmi/chips/rk30/Makefile b/drivers/video/rockchip/hdmi/chips/rk30/Makefile
new file mode 100755 (executable)
index 0000000..98dfae2
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for HDMI linux kernel module.
+#
+
+ccflags-$(CONFIG_HDMI_RK30_DEBUG) = -DDEBUG -DHDMI_DEBUG
+
+obj-$(CONFIG_HDMI_RK30) += rk30_hdmi_hw.o rk30_hdmi.o
+obj-$(CONFIG_HDCP_RK30) += hdcp/
diff --git a/drivers/video/rockchip/hdmi/chips/rk30/hdcp/Kconfig b/drivers/video/rockchip/hdmi/chips/rk30/hdcp/Kconfig
new file mode 100755 (executable)
index 0000000..1bb3c3a
--- /dev/null
@@ -0,0 +1,14 @@
+config HDCP_RK30
+       bool "RK30 HDCP support"
+        depends on LCDC_RK30 && HDMI_RK30
+        default n
+       help
+         HDCP Interface. This adds the High Definition Content Protection Interface.
+         See http://www.digital-cp.com/ for HDCP specification.
+
+config HDCP_RK30_DEBUG
+       bool "RK30 HDCP Debugging"
+        depends on HDCP_RK30
+        default n
+       help
+         Enableds verbose debugging the the HDCP drivers
diff --git a/drivers/video/rockchip/hdmi/chips/rk30/hdcp/Makefile b/drivers/video/rockchip/hdmi/chips/rk30/hdcp/Makefile
new file mode 100755 (executable)
index 0000000..108b67c
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for HDCP linux kernel module.
+#
+
+ccflags-$(CONFIG_HDCP_RK30_DEBUG) = -DDEBUG -DHDCP_DEBUG
+
+obj-$(CONFIG_HDCP_RK30) += hdcp.o
+hdcp-y := rk30_hdcp.o rk30_hdmi_hdcp.o
diff --git a/drivers/video/rockchip/hdmi/chips/rk30/hdcp/rk30_hdcp.c b/drivers/video/rockchip/hdmi/chips/rk30/hdcp/rk30_hdcp.c
new file mode 100755 (executable)
index 0000000..68d0ac8
--- /dev/null
@@ -0,0 +1,570 @@
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/miscdevice.h>
+#include <linux/workqueue.h>
+#include <linux/firmware.h>
+#include "../rk30_hdmi.h"
+#include "../rk30_hdmi_hw.h"
+#include "rk30_hdmi_hdcp.h"
+
+struct hdcp *hdcp = NULL;
+
+static void hdcp_work_queue(struct work_struct *work);
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_submit_work
+ *-----------------------------------------------------------------------------
+ */
+static struct delayed_work *hdcp_submit_work(int event, int delay)
+{
+       struct hdcp_delayed_work *work;
+
+       DBG("%s event %04x delay %d", __FUNCTION__, event, delay);
+       
+       work = kmalloc(sizeof(struct hdcp_delayed_work), GFP_ATOMIC);
+
+       if (work) {
+               INIT_DELAYED_WORK(&work->work, hdcp_work_queue);
+               work->event = event;
+               queue_delayed_work(hdcp->workqueue,
+                                  &work->work,
+                                  msecs_to_jiffies(delay));
+       } else {
+               printk(KERN_WARNING "HDCP: Cannot allocate memory to "
+                                   "create work\n");
+               return 0;
+       }
+
+       return &work->work;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_cancel_work
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_cancel_work(struct delayed_work **work)
+{
+       int ret = 0;
+
+       if (*work) {
+               ret = cancel_delayed_work(*work);
+               if (ret != 1) {
+                       ret = cancel_work_sync(&((*work)->work));
+                       printk(KERN_INFO "Canceling work failed - "
+                                        "cancel_work_sync done %d\n", ret);
+               }
+               kfree(*work);
+               *work = 0;
+       }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_authentication_failure
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_authentication_failure(void)
+{
+       if (hdcp->hdmi_state == HDMI_STOPPED) {
+               return;
+       }
+
+       rk30_hdcp_disable();
+       rk30_hdmi_control_output(false);
+       
+       hdcp_cancel_work(&hdcp->pending_wq_event);
+
+       if (hdcp->retry_cnt && (hdcp->hdmi_state != HDMI_STOPPED)) {
+               if (hdcp->retry_cnt < HDCP_INFINITE_REAUTH) {
+                       hdcp->retry_cnt--;
+                       printk(KERN_INFO "HDCP: authentication failed - "
+                                        "retrying, attempts=%d\n",
+                                                       hdcp->retry_cnt);
+               } else
+                       printk(KERN_INFO "HDCP: authentication failed - "
+                                        "retrying\n");
+
+               hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
+
+               hdcp->pending_wq_event = hdcp_submit_work(HDCP_AUTH_REATT_EVENT,
+                                                        HDCP_REAUTH_DELAY);
+       } else {
+               printk(KERN_INFO "HDCP: authentication failed - "
+                                "HDCP disabled\n");
+               hdcp->hdcp_state = HDCP_ENABLE_PENDING;
+       }
+
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_start_authentication
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_start_authentication(void)
+{
+       int status = HDCP_OK;
+
+       hdcp->hdcp_state = HDCP_AUTHENTICATION_START;
+
+       DBG("HDCP: authentication start");
+
+       status = rk30_hdcp_start_authentication();
+
+       if (status != HDCP_OK) {
+               DBG("HDCP: authentication failed");
+               hdcp_wq_authentication_failure();
+       } else {
+               hdcp->hdcp_state = HDCP_WAIT_KSV_LIST;
+       }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_check_bksv
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_check_bksv(void)
+{
+       int status = HDCP_OK;
+
+       DBG("Check BKSV start");
+       
+       status = rk30_hdcp_check_bksv();
+
+       if (status != HDCP_OK) {
+               printk(KERN_INFO "HDCP: Check BKSV failed");
+               hdcp->retry_cnt = 0;
+               hdcp_wq_authentication_failure();
+       }
+       else {
+               DBG("HDCP: Check BKSV successful");
+
+               hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
+
+               /* Restore retry counter */
+               if(hdcp->retry_times == 0)
+                       hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
+               else
+                       hdcp->retry_cnt = hdcp->retry_times;
+       }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_authentication_sucess
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_authentication_sucess(void)
+{
+       printk(KERN_INFO "HDCP: authentication pass");
+       rk30_hdmi_control_output(true);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_disable
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_disable(int event)
+{
+       printk(KERN_INFO "HDCP: disabled");
+
+       hdcp_cancel_work(&hdcp->pending_wq_event);
+       rk30_hdcp_disable();
+       if(event == HDCP_DISABLE_CTL) {
+               hdcp->hdcp_state = HDCP_DISABLED;
+               if(hdcp->hdmi_state == HDMI_STARTED)
+                       rk30_hdmi_control_output(true);                 
+       }
+       else if(event == HDCP_STOP_FRAME_EVENT)
+               hdcp->hdcp_state = HDCP_ENABLE_PENDING;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_work_queue
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_work_queue(struct work_struct *work)
+{
+       struct hdcp_delayed_work *hdcp_w =
+               container_of(work, struct hdcp_delayed_work, work.work);
+       int event = hdcp_w->event;
+
+       mutex_lock(&hdcp->lock);
+       
+       DBG("hdcp_work_queue() - START - %u hdmi=%d hdcp=%d evt= %x %d",
+               jiffies_to_msecs(jiffies),
+               hdcp->hdmi_state,
+               hdcp->hdcp_state,
+               (event & 0xFF00) >> 8,
+               event & 0xFF);
+       
+       if(event == HDCP_STOP_FRAME_EVENT) {
+               hdcp->hdmi_state = HDMI_STOPPED;
+       }
+       
+       if (event == HDCP_DISABLE_CTL || event == HDCP_STOP_FRAME_EVENT) {
+               hdcp_wq_disable(event);
+       }
+       
+       if (event & HDCP_WORKQUEUE_SRC)
+               hdcp->pending_wq_event = 0;
+       
+       /* First handle HDMI state */
+       if (event == HDCP_START_FRAME_EVENT) {
+               hdcp->pending_start = 0;
+               hdcp->hdmi_state = HDMI_STARTED;
+       }
+       
+       /**********************/
+       /* HDCP state machine */
+       /**********************/
+       switch (hdcp->hdcp_state) {
+               case HDCP_DISABLED:
+                       /* HDCP enable control or re-authentication event */
+                       if (event == HDCP_ENABLE_CTL) {
+                               if(hdcp->retry_times == 0)
+                                       hdcp->retry_cnt = HDCP_INFINITE_REAUTH;
+                               else
+                                       hdcp->retry_cnt = hdcp->retry_times;
+                               if (hdcp->hdmi_state == HDMI_STARTED)
+                                       hdcp_wq_start_authentication();
+                               else
+                                       hdcp->hdcp_state = HDCP_ENABLE_PENDING;
+                       }
+                       break;
+               
+               case HDCP_ENABLE_PENDING:
+                       /* HDMI start frame event */
+                       if (event == HDCP_START_FRAME_EVENT)
+                               hdcp_wq_start_authentication();
+
+                       break;
+               
+               case HDCP_AUTHENTICATION_START:
+                       /* Re-authentication */
+                       if (event == HDCP_AUTH_REATT_EVENT)
+                               hdcp_wq_start_authentication();
+       
+                       break;
+               
+               case HDCP_WAIT_KSV_LIST:
+                       /* KSV failure */
+                       if (event == HDCP_FAIL_EVENT) {
+                               printk(KERN_INFO "HDCP: KSV switch failure\n");
+       
+                               hdcp_wq_authentication_failure();
+                       }
+                       /* KSV list ready event */
+                       else if (event == HDCP_KSV_LIST_RDY_EVENT)
+                               hdcp_wq_check_bksv();
+                       break;
+               
+               case HDCP_LINK_INTEGRITY_CHECK:
+                       /* Ri failure */
+                       if (event == HDCP_FAIL_EVENT) {
+                               printk(KERN_INFO "HDCP: Ri check failure\n");
+                               hdcp_wq_authentication_failure();
+                       }
+                       else if(event == HDCP_AUTH_PASS_EVENT)
+                               hdcp_wq_authentication_sucess();
+                       break;
+       
+               default:
+                       printk(KERN_WARNING "HDCP: error - unknow HDCP state\n");
+                       break;
+       }
+       
+       kfree(hdcp_w);
+       if(event == HDCP_STOP_FRAME_EVENT)
+               complete(&hdcp->complete);
+               
+       mutex_unlock(&hdcp->lock);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_start_frame_cb
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_start_frame_cb(void)
+{
+       DBG("hdcp_start_frame_cb()");
+
+       /* Cancel any pending work */
+       if (hdcp->pending_start)
+               hdcp_cancel_work(&hdcp->pending_start);
+       if (hdcp->pending_wq_event)
+               hdcp_cancel_work(&hdcp->pending_wq_event);
+
+       hdcp->pending_start = hdcp_submit_work(HDCP_START_FRAME_EVENT,
+                                                       HDCP_ENABLE_DELAY);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_irq_cb
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_irq_cb(int interrupt)
+{
+       int value;
+       DBG("%s 0x%x", __FUNCTION__, interrupt);
+       if(interrupt & m_INT_HDCP_ERR)
+       {
+               value = HDMIRdReg(HDCP_ERROR);
+               HDMIWrReg(HDCP_ERROR, value);
+               printk(KERN_INFO "HDCP: Error 0x%02x\n", value);
+               
+               if( (hdcp->hdcp_state != HDCP_DISABLED) &&
+                       (hdcp->hdcp_state != HDCP_ENABLE_PENDING) )
+               {       
+                       hdcp_submit_work(HDCP_FAIL_EVENT, 0);
+               }
+       }
+       else if(interrupt & (m_INT_BKSV_RPRDY | m_INT_BKSV_RCRDY))
+               hdcp_submit_work(HDCP_KSV_LIST_RDY_EVENT, 0);
+       else if(interrupt & m_INT_AUTH_DONE)
+               hdcp_submit_work(HDCP_AUTH_PASS_EVENT, 0);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_power_on_cb
+ *-----------------------------------------------------------------------------
+ */
+static int hdcp_power_on_cb(void)
+{
+       DBG("%s", __FUNCTION__);
+       return rk30_hdcp_load_key2mem(hdcp->keys);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_power_off_cb
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_power_off_cb(void)
+{
+       DBG("%s", __FUNCTION__);
+       if(!hdcp->enable)
+               return;
+       
+       hdcp_cancel_work(&hdcp->pending_start);
+       hdcp_cancel_work(&hdcp->pending_wq_event);
+       init_completion(&hdcp->complete);
+       /* Post event to workqueue */
+       if (hdcp_submit_work(HDCP_STOP_FRAME_EVENT, 0)) 
+               wait_for_completion_interruptible_timeout(&hdcp->complete,
+                                                       msecs_to_jiffies(2000));
+}
+
+// Load HDCP key to external HDCP memory
+static void hdcp_load_keys_cb(const struct firmware *fw, void *context)
+{
+       if (!fw) {
+               pr_err("HDCP: failed to load keys\n");
+               return;
+       }
+       
+       if(fw->size < HDCP_KEY_SIZE) {
+               pr_err("HDCP: firmware wrong size %d\n", fw->size);
+               return;
+       }
+       
+       hdcp->keys =  kmalloc(HDCP_KEY_SIZE, GFP_KERNEL);
+       if(hdcp->keys == NULL) {
+               pr_err("HDCP: can't allocated space for keys\n");
+               return;
+       }
+       
+       memcpy(hdcp->keys, fw->data, HDCP_KEY_SIZE);
+       
+       rk30_hdcp_load_key2mem(hdcp->keys);
+       printk(KERN_INFO "HDCP: loaded hdcp key success\n");
+
+       if(fw->size > HDCP_KEY_SIZE) {
+               DBG("%s invalid key size %d", __FUNCTION__, fw->size - HDCP_KEY_SIZE);
+               if((fw->size - HDCP_KEY_SIZE) % 5) {
+                       pr_err("HDCP: failed to load invalid keys\n");
+                       return;
+               }
+               hdcp->invalidkeys = kmalloc(fw->size - HDCP_KEY_SIZE, GFP_KERNEL);
+               if(hdcp->invalidkeys == NULL) {
+                       pr_err("HDCP: can't allocated space for invalid keys\n");
+                       return;
+               }
+               memcpy(hdcp->invalidkeys, fw->data + HDCP_KEY_SIZE, fw->size - HDCP_KEY_SIZE);
+               hdcp->invalidkey = (fw->size - HDCP_KEY_SIZE)/5;
+               printk(KERN_INFO "HDCP: loaded hdcp invalid key success\n");
+       }
+}
+
+static ssize_t hdcp_enable_read(struct device *device,
+                           struct device_attribute *attr, char *buf)
+{
+       int enable = 0;
+       
+       if(hdcp)
+               enable = hdcp->enable;
+               
+       return snprintf(buf, PAGE_SIZE, "%d\n", enable);
+}
+
+static ssize_t hdcp_enable_write(struct device *device,
+                          struct device_attribute *attr, const char *buf, size_t count)
+{
+       int enable;
+
+       if(hdcp == NULL)
+               return -EINVAL;
+       
+       sscanf(buf, "%d", &enable);
+       if(hdcp->enable != enable)
+       {
+               /* Post event to workqueue */
+               if(enable) {
+                       if (hdcp_submit_work(HDCP_ENABLE_CTL, 0) == 0)
+                               return -EFAULT;
+               }
+               else {
+                       hdcp_cancel_work(&hdcp->pending_start);
+                       hdcp_cancel_work(&hdcp->pending_wq_event);
+               
+                       /* Post event to workqueue */
+                       if (hdcp_submit_work(HDCP_DISABLE_CTL, 0) == 0)
+                               return -EFAULT;
+               }
+               hdcp->enable =  enable;
+       }
+       return count;
+}
+
+static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR, hdcp_enable_read, hdcp_enable_write);
+
+static ssize_t hdcp_trytimes_read(struct device *device,
+                           struct device_attribute *attr, char *buf)
+{
+       int trytimes = 0;
+       
+       if(hdcp)
+               trytimes = hdcp->retry_times;
+               
+       return snprintf(buf, PAGE_SIZE, "%d\n", trytimes);
+}
+
+static ssize_t hdcp_trytimes_wrtie(struct device *device,
+                          struct device_attribute *attr, const char *buf, size_t count)
+{
+       int trytimes;
+
+       if(hdcp == NULL)
+               return -EINVAL;
+       
+       sscanf(buf, "%d", &trytimes);
+       if(hdcp->retry_times != trytimes)
+               hdcp->retry_times = trytimes;
+       
+       return count;
+}
+
+
+static DEVICE_ATTR(trytimes, S_IRUGO|S_IWUSR, hdcp_trytimes_read, hdcp_trytimes_wrtie);
+
+
+static struct miscdevice mdev;
+
+static int __init rk30_hdcp_init(void)
+{
+       int ret;
+       
+       DBG("[%s] %u", __FUNCTION__, jiffies_to_msecs(jiffies));
+       
+       hdcp = kmalloc(sizeof(struct hdcp), GFP_KERNEL);
+       if(!hdcp)
+       {
+       printk(KERN_ERR ">>HDCP: kmalloc fail!");
+       ret = -ENOMEM;
+       goto error0; 
+       }
+       memset(hdcp, 0, sizeof(struct hdcp));
+       mutex_init(&hdcp->lock);
+       
+       mdev.minor = MISC_DYNAMIC_MINOR;
+       mdev.name = "hdcp";
+       mdev.mode = 0666;
+       if (misc_register(&mdev)) {
+               printk(KERN_ERR "HDCP: Could not add character driver\n");
+               ret = HDMI_ERROR_FALSE;
+               goto error1;
+       }
+       ret = device_create_file(mdev.this_device, &dev_attr_enable);
+    if(ret)
+    {
+        printk(KERN_ERR "HDCP: Could not add sys file enable\n");
+        ret = -EINVAL;
+        goto error2;
+    }
+    
+    ret = device_create_file(mdev.this_device, &dev_attr_trytimes);
+    if(ret)
+    {
+        printk(KERN_ERR "HDCP: Could not add sys file trytimes\n");
+        ret = -EINVAL;
+        goto error3;
+    }
+    
+    hdcp->workqueue = create_singlethread_workqueue("hdcp");
+       if (hdcp->workqueue == NULL) {
+               printk(KERN_ERR "HDCP,: create workqueue failed.\n");
+               goto error4;
+       }
+    
+    
+    ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
+                             "hdcp.keys", mdev.this_device, GFP_KERNEL,
+                             hdcp, hdcp_load_keys_cb);
+       if (ret < 0) {
+               printk(KERN_ERR "HDCP: request_firmware_nowait failed: %d\n", ret);
+               goto error5;
+       }
+       
+       rk30_hdmi_register_hdcp_callbacks(      hdcp_start_frame_cb,
+                                                                               hdcp_irq_cb,
+                                                                               hdcp_power_on_cb,
+                                                                               hdcp_power_off_cb);
+                                                                               
+       DBG("%s success %u", __FUNCTION__, jiffies_to_msecs(jiffies));
+       return 0;
+       
+error5:
+       destroy_workqueue(hdcp->workqueue);
+error4:
+       device_remove_file(mdev.this_device, &dev_attr_trytimes);
+error3:
+       device_remove_file(mdev.this_device, &dev_attr_enable);
+error2:
+       misc_deregister(&mdev);
+error1:
+       if(hdcp->keys)
+               kfree(hdcp->keys);
+       if(hdcp->invalidkeys)
+               kfree(hdcp->invalidkeys);
+       kfree(hdcp);
+error0:
+       return ret;
+}
+
+static void __exit rk30_hdcp_exit(void)
+{
+       if(hdcp) {
+               mutex_lock(&hdcp->lock);
+               rk30_hdmi_register_hdcp_callbacks(0, 0, 0, 0);
+               device_remove_file(mdev.this_device, &dev_attr_enable);
+               misc_deregister(&mdev);
+               destroy_workqueue(hdcp->workqueue);
+               if(hdcp->keys)
+                       kfree(hdcp->keys);
+               if(hdcp->invalidkeys)
+                       kfree(hdcp->invalidkeys);
+               mutex_unlock(&hdcp->lock);
+               kfree(hdcp);
+       }
+}
+
+module_init(rk30_hdcp_init);
+module_exit(rk30_hdcp_exit);
\ No newline at end of file
diff --git a/drivers/video/rockchip/hdmi/chips/rk30/hdcp/rk30_hdmi_hdcp.c b/drivers/video/rockchip/hdmi/chips/rk30/hdcp/rk30_hdmi_hdcp.c
new file mode 100755 (executable)
index 0000000..1184989
--- /dev/null
@@ -0,0 +1,157 @@
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <mach/io.h>
+#include "../rk30_hdmi.h"
+#include "../rk30_hdmi_hw.h"
+#include "rk30_hdmi_hdcp.h"
+
+static void rk30_hdcp_write_mem(int addr_8, char value)
+{
+       int temp;
+       int addr_32 = addr_8 - addr_8%4;
+       int shift = (addr_8%4) * 8;
+       
+       temp = HDMIRdReg(addr_32);
+       temp &= ~(0xff << shift);
+       temp |= value << shift;
+//     printk("temp is %08x\n", temp);
+       HDMIWrReg(addr_32, temp);
+}
+
+int rk30_hdcp_load_key2mem(struct hdcp_keys *key)
+{
+       int i;
+       
+       if(key == NULL) return  HDMI_ERROR_FALSE;
+       
+       HDMIWrReg(0x800, HDMI_INTERANL_CLK_DIV);
+       
+       for(i = 0; i < 7; i++)
+               rk30_hdcp_write_mem(HDCP_RAM_KEY_KSV1 + i, key->KSV[i]);
+       for(i = 0; i < 7; i++)
+               rk30_hdcp_write_mem(HDCP_RAM_KEY_KSV2 + i, key->KSV[i]);
+       for(i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++)
+               rk30_hdcp_write_mem(HDCP_RAM_KEY_PRIVATE + i, key->DeviceKey[i]);
+       for(i = 0; i < HDCP_KEY_SHA_SIZE; i++)
+               rk30_hdcp_write_mem(HDCP_RAM_KEY_PRIVATE + HDCP_PRIVATE_KEY_SIZE + i, key->sha1[i]);
+       
+       HDMIWrReg(0x800, HDMI_INTERANL_CLK_DIV | 0x20);
+       return HDCP_OK;
+}
+
+void rk30_hdcp_disable(void)
+{
+       int temp;
+       // Diable HDCP Interrupt
+       HDMIWrReg(INTR_MASK2, 0x00);
+       // Stop and Reset HDCP
+       HDMIMskReg(temp, HDCP_CTRL, m_HDCP_FRAMED_ENCRYPED | m_HDCP_AUTH_STOP | m_HDCP_RESET, 
+               v_HDCP_FRAMED_ENCRYPED(0) | v_HDCP_AUTH_STOP(1) | v_HDCP_RESET(1) );
+}
+
+static int rk30_hdcp_load_key(void)
+{
+       int value, temp = 0;
+       
+       if(hdcp->keys == NULL) {
+               pr_err("[%s] HDCP key not loaded.\n", __FUNCTION__);
+               return HDCP_KEY_ERR;
+       }
+       
+       value = HDMIRdReg(HDCP_KEY_MEM_CTRL);
+       //Check HDCP key loaded from external HDCP memory
+       while((value & (m_KSV_VALID | m_KEY_VALID | m_KEY_READY)) != (m_KSV_VALID | m_KEY_VALID | m_KEY_READY)) {
+               if(temp > 10) {
+                       pr_err("[%s] loaded hdcp key is incorrectable %02x\n", __FUNCTION__, value & 0xFF);
+                       return HDCP_KEY_ERR;
+               }
+               //Load HDCP Key from external HDCP memory
+               HDMIWrReg(HDCP_KEY_ACCESS_CTRL2, m_LOAD_HDCP_KEY);
+               msleep(1);
+               value = HDMIRdReg(HDCP_KEY_MEM_CTRL);
+               temp++;
+       }
+       
+       return HDCP_OK;
+}
+
+
+int rk30_hdcp_start_authentication(void)
+{
+       int rc, temp;
+       
+       rc = rk30_hdcp_load_key();
+       if(rc != HDCP_OK)
+               return rc;
+       
+       // Set 100ms & 5 sec timer
+       switch(hdmi->vic)
+       {
+               case HDMI_720x576p_50Hz_4_3:
+               case HDMI_720x576p_50Hz_16_9:
+               case HDMI_1280x720p_50Hz:
+               case HDMI_1920x1080i_50Hz:
+               case HDMI_720x576i_50Hz_4_3:
+               case HDMI_720x576i_50Hz_16_9:
+               case HDMI_1920x1080p_50Hz:
+                       HDMIWrReg(HDCP_TIMER_100MS, 5);
+                       HDMIWrReg(HDCP_TIMER_5S, 250);
+                       break;
+               
+               default:
+                       HDMIWrReg(HDCP_TIMER_100MS, 0x26);
+                       HDMIWrReg(HDCP_TIMER_5S, 0x2c);
+                       break;
+       }
+       // Config DDC Clock
+       temp = (hdmi->tmdsclk/HDCP_DDC_CLK)/4;
+       HDMIWrReg(DDC_BUS_FREQ_L, temp & 0xFF);
+       HDMIWrReg(DDC_BUS_FREQ_H, (temp >> 8) & 0xFF);
+       // Enable HDCP Interrupt
+       HDMIWrReg(INTR_MASK2, m_INT_HDCP_ERR | m_INT_BKSV_RPRDY | m_INT_BKSV_RCRDY | m_INT_AUTH_DONE | m_INT_AUTH_READY);
+       // Start HDCP
+       HDMIMskReg(temp, HDCP_CTRL, m_HDCP_AUTH_START | m_HDCP_FRAMED_ENCRYPED, v_HDCP_AUTH_START(1) | v_HDCP_FRAMED_ENCRYPED(0));
+       
+       return HDCP_OK;
+}
+
+int rk30_hdcp_check_bksv(void)
+{
+       int i, temp;
+       char bksv[5];
+       char *invalidkey;
+       
+       temp = HDMIRdReg(HDCP_BCAPS);
+       DBG("Receiver capacity is 0x%02x", temp);
+       
+#ifdef DEBUG   
+       if(temp & m_HDMI_RECEIVED)
+               DBG("Receiver support HDMI");
+       if(temp & m_REPEATER)
+               DBG("Receiver is a repeater");
+       if(temp & m_DDC_FAST)
+               DBG("Receiver support 400K DDC");
+       if(temp & m_1_1_FEATURE)
+               DBG("Receiver support 1.1 features, such as advanced cipher, EESS.");
+       if(temp & m_FAST_REAUTHENTICATION)
+               DBG("Receiver support fast reauthentication.");
+#endif
+               
+       for(i = 0; i < 5; i++) {
+               bksv[i] = HDMIRdReg(HDCP_KSV_BYTE0 + (4 - i)*4) & 0xFF;
+       }
+       
+       DBG("bksv is 0x%02x%02x%02x%02x%02x", bksv[0], bksv[1], bksv[2], bksv[3], bksv[4]);
+       
+       for(i = 0; i < hdcp->invalidkey; i++)
+       {
+               invalidkey = hdcp->invalidkeys + i *5;
+               if(memcmp(bksv, invalidkey, 5) == 0) {
+                       printk(KERN_ERR "HDCP: BKSV was revocated!!!\n");
+                       HDMIMskReg(temp, HDCP_CTRL, m_HDCP_BKSV_FAILED | m_HDCP_FRAMED_ENCRYPED, v_HDCP_BKSV_FAILED(1) | v_HDCP_FRAMED_ENCRYPED(0));
+                       return HDCP_KSV_ERR;
+               }
+       }
+       HDMIMskReg(temp, HDCP_CTRL, m_HDCP_BKSV_PASS | m_HDCP_FRAMED_ENCRYPED, v_HDCP_BKSV_PASS(1) | v_HDCP_FRAMED_ENCRYPED(1));
+       return HDCP_OK;
+}
diff --git a/drivers/video/rockchip/hdmi/chips/rk30/hdcp/rk30_hdmi_hdcp.h b/drivers/video/rockchip/hdmi/chips/rk30/hdcp/rk30_hdmi_hdcp.h
new file mode 100755 (executable)
index 0000000..0224d88
--- /dev/null
@@ -0,0 +1,99 @@
+#ifndef __RK30_HDMI_HDCP_H__
+#define __RK30_HDMI_HDCP_H__
+
+/***************************/
+/* Definitions             */
+/***************************/
+
+/* Status / error codes */
+#define HDCP_OK                        0
+#define HDCP_KEY_ERR   1
+#define HDCP_KSV_ERR   2
+
+/* Delays */
+#define HDCP_ENABLE_DELAY      300
+#define HDCP_REAUTH_DELAY      100
+
+/* Event source */
+#define HDCP_SRC_SHIFT         8
+#define HDCP_IOCTL_SRC         (0x1 << HDCP_SRC_SHIFT)
+#define HDCP_HDMI_SRC          (0x2 << HDCP_SRC_SHIFT)
+#define HDCP_IRQ_SRC           (0x4 << HDCP_SRC_SHIFT)
+#define HDCP_WORKQUEUE_SRC     (0x8 << HDCP_SRC_SHIFT)
+
+/* Event */
+#define HDCP_ENABLE_CTL                        (HDCP_IOCTL_SRC         | 0)
+#define HDCP_DISABLE_CTL               (HDCP_IOCTL_SRC         | 1)
+#define HDCP_START_FRAME_EVENT (HDCP_HDMI_SRC          | 2)
+#define HDCP_STOP_FRAME_EVENT  (HDCP_HDMI_SRC          | 3)
+#define HDCP_KSV_LIST_RDY_EVENT        (HDCP_IRQ_SRC           | 4)
+#define HDCP_FAIL_EVENT                        (HDCP_IRQ_SRC           | 5)
+#define HDCP_AUTH_PASS_EVENT   (HDCP_IRQ_SRC           | 6)
+#define HDCP_AUTH_REATT_EVENT  (HDCP_WORKQUEUE_SRC     | 7)
+
+/* Key size */
+#define HDCP_KEY_SIZE                  308     
+
+/* Authentication retry times */
+#define HDCP_INFINITE_REAUTH   0x100
+
+enum hdcp_states {
+       HDCP_DISABLED,
+       HDCP_ENABLE_PENDING,
+       HDCP_AUTHENTICATION_START,
+       HDCP_WAIT_KSV_LIST,
+       HDCP_LINK_INTEGRITY_CHECK,
+};
+
+enum hdmi_states {
+       HDMI_STOPPED,
+       HDMI_STARTED
+};
+
+#define HDCP_PRIVATE_KEY_SIZE  280
+#define HDCP_KEY_SHA_SIZE              20
+#define HDCP_DDC_CLK                   100000
+
+struct hdcp_keys{
+       u8 KSV[8];
+       u8 DeviceKey[HDCP_PRIVATE_KEY_SIZE];
+       u8 sha1[HDCP_KEY_SHA_SIZE];
+};
+
+struct hdcp_delayed_work {
+       struct delayed_work work;
+       int event;
+};
+
+struct hdcp {
+       int     enable;
+       int retry_times;
+       struct hdcp_keys *keys;
+       int invalidkey;
+       char *invalidkeys;      
+       struct mutex lock;
+       struct completion       complete;
+       struct workqueue_struct *workqueue;
+       
+       enum hdmi_states hdmi_state;
+       enum hdcp_states hdcp_state;
+       
+       struct delayed_work *pending_start;
+       struct delayed_work *pending_wq_event;
+       int retry_cnt;
+};
+
+extern struct hdcp *hdcp;
+
+#ifdef HDCP_DEBUG
+#define DBG(format, ...) \
+               printk(KERN_INFO "HDCP: " format "\n", ## __VA_ARGS__)
+#else
+#define DBG(format, ...)
+#endif
+
+extern void rk30_hdcp_disable(void);
+extern int     rk30_hdcp_start_authentication(void);
+extern int     rk30_hdcp_check_bksv(void);
+extern int     rk30_hdcp_load_key2mem(struct hdcp_keys *key);
+#endif /* __RK30_HDMI_HDCP_H__ */
\ No newline at end of file
diff --git a/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi.c b/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi.c
new file mode 100755 (executable)
index 0000000..0aae519
--- /dev/null
@@ -0,0 +1,299 @@
+#include <linux/module.h>\r
+#include <linux/kernel.h>\r
+#include <linux/errno.h>\r
+#include <linux/string.h>\r
+#include <linux/mm.h>\r
+#include <linux/slab.h>\r
+#include <linux/delay.h>\r
+#include <linux/device.h>\r
+#include <linux/init.h>\r
+#include <linux/dma-mapping.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/clk.h>\r
+\r
+#include <mach/board.h>\r
+#include <mach/io.h>\r
+#include <mach/gpio.h>\r
+#include <mach/iomux.h>\r
+#include "rk30_hdmi.h"\r
+#include "rk30_hdmi_hw.h"\r
+\r
+struct hdmi *hdmi = NULL;\r
+\r
+extern irqreturn_t hdmi_irq(int irq, void *priv);\r
+extern void hdmi_work(struct work_struct *work);\r
+extern struct rk_lcdc_device_driver * rk_get_lcdc_drv(char *name);\r
+extern void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent);\r
+extern void hdmi_unregister_display_sysfs(struct hdmi *hdmi);\r
+\r
+int rk30_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),\r
+                                        void (*hdcp_irq_cb)(int status),\r
+                                        int (*hdcp_power_on_cb)(void),\r
+                                        void (*hdcp_power_off_cb)(void))\r
+{\r
+       if(hdmi == NULL)\r
+               return HDMI_ERROR_FALSE;\r
+\r
+       hdmi->hdcp_cb = hdcp_cb;\r
+       hdmi->hdcp_irq_cb = hdcp_irq_cb;\r
+       hdmi->hdcp_power_on_cb = hdcp_power_on_cb;\r
+       hdmi->hdcp_power_off_cb = hdcp_power_off_cb;\r
+       \r
+       return HDMI_ERROR_SUCESS;\r
+}\r
+\r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+static void hdmi_early_suspend(struct early_suspend *h)\r
+{\r
+       hdmi_dbg(hdmi->dev, "hdmi enter early suspend pwr %d state %d\n", hdmi->pwr_mode, hdmi->state);\r
+       flush_delayed_work(&hdmi->delay_work);  \r
+       mutex_lock(&hdmi->enable_mutex);\r
+       hdmi->suspend = 1;\r
+       if(!hdmi->enable) {\r
+               mutex_unlock(&hdmi->enable_mutex);\r
+               return;\r
+       }\r
+       disable_irq(hdmi->irq);\r
+       mutex_unlock(&hdmi->enable_mutex);\r
+       hdmi->command = HDMI_CONFIG_ENABLE;\r
+       init_completion(&hdmi->complete);\r
+       hdmi->wait = 1;\r
+       queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);\r
+       wait_for_completion_interruptible_timeout(&hdmi->complete,\r
+                                                       msecs_to_jiffies(5000));\r
+       flush_delayed_work(&hdmi->delay_work);\r
+       // When HDMI 1.1V and 2.5V power off, DDC channel will be pull down, current is produced\r
+       // from VCC_IO which is pull up outside soc. We need to switch DDC IO to GPIO.\r
+       rk30_mux_api_set(GPIO0A2_HDMII2CSDA_NAME, GPIO0A_GPIO0A2);\r
+       rk30_mux_api_set(GPIO0A1_HDMII2CSCL_NAME, GPIO0A_GPIO0A1);\r
+       return;\r
+}\r
+\r
+static void hdmi_early_resume(struct early_suspend *h)\r
+{\r
+       hdmi_dbg(hdmi->dev, "hdmi exit early resume\n");\r
+       mutex_lock(&hdmi->enable_mutex);\r
+       \r
+       rk30_mux_api_set(GPIO0A2_HDMII2CSDA_NAME, GPIO0A_HDMI_I2C_SDA);\r
+       rk30_mux_api_set(GPIO0A1_HDMII2CSCL_NAME, GPIO0A_HDMI_I2C_SCL);\r
+       \r
+       hdmi->suspend = 0;\r
+       rk30_hdmi_initial();\r
+       if(hdmi->enable) {\r
+               enable_irq(hdmi->irq);\r
+       }\r
+       mutex_unlock(&hdmi->enable_mutex);\r
+       return;\r
+}\r
+#endif\r
+\r
+static inline void hdmi_io_remap(void)\r
+{\r
+       unsigned int value;\r
+       \r
+       // Remap HDMI IO Pin\r
+       rk30_mux_api_set(GPIO0A2_HDMII2CSDA_NAME, GPIO0A_HDMI_I2C_SDA);\r
+       rk30_mux_api_set(GPIO0A1_HDMII2CSCL_NAME, GPIO0A_HDMI_I2C_SCL);\r
+       rk30_mux_api_set(GPIO0A0_HDMIHOTPLUGIN_NAME, GPIO0A_HDMI_HOT_PLUG_IN);\r
+               \r
+       // Select LCDC0 as video source and enabled.\r
+       value = (HDMI_SOURCE_DEFAULT << 14) | (1 << 30);\r
+       writel(value, GRF_SOC_CON0 + RK30_GRF_BASE);\r
+}\r
+\r
+static int __devinit rk30_hdmi_probe (struct platform_device *pdev)\r
+{\r
+       int ret;\r
+       struct resource *res;\r
+       struct resource *mem;\r
+       \r
+       hdmi = kmalloc(sizeof(struct hdmi), GFP_KERNEL);\r
+       if(!hdmi)\r
+       {\r
+       dev_err(&pdev->dev, ">>rk30 hdmi kmalloc fail!");\r
+       return -ENOMEM;\r
+       }\r
+       memset(hdmi, 0, sizeof(struct hdmi));\r
+       hdmi->dev = &pdev->dev;\r
+       platform_set_drvdata(pdev, hdmi);\r
+\r
+       if(HDMI_SOURCE_DEFAULT == HDMI_SOURCE_LCDC0)\r
+               hdmi->lcdc = rk_get_lcdc_drv("lcdc0");\r
+       else\r
+               hdmi->lcdc = rk_get_lcdc_drv("lcdc1");\r
+       if(hdmi->lcdc == NULL)\r
+       {\r
+               dev_err(hdmi->dev, "can not connect to video source lcdc\n");\r
+               ret = -ENXIO;\r
+               goto err0;\r
+       }\r
+       hdmi->xscale = 95;\r
+       hdmi->yscale = 95;\r
+       \r
+       hdmi->hclk = clk_get(NULL,"hclk_hdmi");\r
+       if(IS_ERR(hdmi->hclk))\r
+       {\r
+               dev_err(hdmi->dev, "Unable to get hdmi hclk\n");\r
+               ret = -ENXIO;\r
+               goto err0;\r
+       }\r
+       clk_enable(hdmi->hclk);\r
+       \r
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
+       if (!res) {\r
+               dev_err(hdmi->dev, "Unable to get register resource\n");\r
+               ret = -ENXIO;\r
+               goto err0;\r
+       }\r
+       hdmi->regbase_phy = res->start;\r
+       hdmi->regsize_phy = (res->end - res->start) + 1;\r
+       mem = request_mem_region(res->start, (res->end - res->start) + 1, pdev->name);\r
+       if (!mem)\r
+       {\r
+       dev_err(hdmi->dev, "failed to request mem region for hdmi\n");\r
+       ret = -ENOENT;\r
+       goto err0;\r
+       }\r
+\r
+       \r
+       hdmi->regbase = (int)ioremap(res->start, (res->end - res->start) + 1);\r
+       if (!hdmi->regbase) {\r
+               dev_err(hdmi->dev, "cannot ioremap registers\n");\r
+               ret = -ENXIO;\r
+               goto err1;\r
+       }\r
+       \r
+       ret = rk30_hdmi_initial();\r
+       if(ret != HDMI_ERROR_SUCESS)\r
+               goto err1;\r
+               \r
+       hdmi_io_remap();\r
+       hdmi_sys_init();\r
+       \r
+       hdmi->workqueue = create_singlethread_workqueue("hdmi");\r
+       INIT_DELAYED_WORK(&(hdmi->delay_work), hdmi_work);\r
+\r
+       #ifdef CONFIG_HAS_EARLYSUSPEND\r
+       hdmi->early_suspend.suspend = hdmi_early_suspend;\r
+       hdmi->early_suspend.resume = hdmi_early_resume;\r
+       hdmi->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 10;\r
+       register_early_suspend(&hdmi->early_suspend);\r
+       #endif\r
+               \r
+       hdmi_register_display_sysfs(hdmi, NULL);\r
+       #ifdef CONFIG_SWITCH\r
+       hdmi->switch_hdmi.name="hdmi";\r
+       switch_dev_register(&(hdmi->switch_hdmi));\r
+       #endif\r
+               \r
+       spin_lock_init(&hdmi->irq_lock);\r
+       mutex_init(&hdmi->enable_mutex);\r
+       \r
+       /* get the IRQ */\r
+       hdmi->irq = platform_get_irq(pdev, 0);\r
+       if(hdmi->irq <= 0) {\r
+               dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);\r
+               ret = -ENXIO;\r
+               goto err2;\r
+       }\r
+\r
+       /* request the IRQ */\r
+       ret = request_irq(hdmi->irq, hdmi_irq, 0, dev_name(&pdev->dev), hdmi);\r
+       if (ret)\r
+       {\r
+               dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);\r
+               goto err2;\r
+       }\r
+\r
+       hdmi_dbg(hdmi->dev, "rk30 hdmi probe sucess.\n");\r
+       return 0;\r
+err2:\r
+       #ifdef CONFIG_SWITCH\r
+       switch_dev_unregister(&(hdmi->switch_hdmi));\r
+       #endif\r
+       hdmi_unregister_display_sysfs(hdmi);\r
+       #ifdef CONFIG_HAS_EARLYSUSPEND\r
+       unregister_early_suspend(&hdmi->early_suspend);\r
+       #endif\r
+       iounmap((void*)hdmi->regbase);\r
+err1:\r
+       release_mem_region(res->start,(res->end - res->start) + 1);\r
+       clk_disable(hdmi->hclk);\r
+err0:\r
+       hdmi_dbg(hdmi->dev, "rk30 hdmi probe error.\n");\r
+       kfree(hdmi);\r
+       hdmi = NULL;\r
+       return ret;\r
+}\r
+\r
+static int __devexit rk30_hdmi_remove(struct platform_device *pdev)\r
+{\r
+       if(hdmi) {\r
+               mutex_lock(&hdmi->enable_mutex);\r
+               if(!hdmi->suspend && hdmi->enable)\r
+                       disable_irq(hdmi->irq);\r
+               mutex_unlock(&hdmi->enable_mutex);\r
+               free_irq(hdmi->irq, NULL);\r
+               flush_workqueue(hdmi->workqueue);\r
+               destroy_workqueue(hdmi->workqueue);\r
+               #ifdef CONFIG_SWITCH\r
+               switch_dev_unregister(&(hdmi->switch_hdmi));\r
+               #endif\r
+               hdmi_unregister_display_sysfs(hdmi);\r
+               #ifdef CONFIG_HAS_EARLYSUSPEND\r
+               unregister_early_suspend(&hdmi->early_suspend);\r
+               #endif\r
+               iounmap((void*)hdmi->regbase);\r
+               release_mem_region(hdmi->regbase_phy, hdmi->regsize_phy);\r
+               clk_disable(hdmi->hclk);\r
+               fb_destroy_modelist(&hdmi->edid.modelist);\r
+               if(hdmi->edid.audio)\r
+                       kfree(hdmi->edid.audio);\r
+               if(hdmi->edid.specs)\r
+               {\r
+                       if(hdmi->edid.specs->modedb)\r
+                               kfree(hdmi->edid.specs->modedb);\r
+                       kfree(hdmi->edid.specs);\r
+               }\r
+               kfree(hdmi);\r
+               hdmi = NULL;\r
+       }\r
+       printk(KERN_INFO "rk30 hdmi removed.\n");\r
+       return 0;\r
+}\r
+\r
+static void rk30_hdmi_shutdown(struct platform_device *pdev)\r
+{\r
+       if(hdmi) {\r
+               #ifdef CONFIG_HAS_EARLYSUSPEND\r
+               unregister_early_suspend(&hdmi->early_suspend);\r
+               #endif\r
+       }\r
+       printk(KERN_INFO "rk30 hdmi shut down.\n");\r
+}\r
+\r
+static struct platform_driver rk30_hdmi_driver = {\r
+       .probe          = rk30_hdmi_probe,\r
+       .remove         = __devexit_p(rk30_hdmi_remove),\r
+       .driver         = {\r
+               .name   = "rk30-hdmi",\r
+               .owner  = THIS_MODULE,\r
+       },\r
+       .shutdown   = rk30_hdmi_shutdown,\r
+};\r
+\r
+static int __init rk30_hdmi_init(void)\r
+{\r
+    return platform_driver_register(&rk30_hdmi_driver);\r
+}\r
+\r
+static void __exit rk30_hdmi_exit(void)\r
+{\r
+    platform_driver_unregister(&rk30_hdmi_driver);\r
+}\r
+\r
+\r
+//fs_initcall(rk30_hdmi_init);\r
+module_init(rk30_hdmi_init);\r
+module_exit(rk30_hdmi_exit);\r
diff --git a/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi.h b/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi.h
new file mode 100755 (executable)
index 0000000..4695086
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __RK30_HDMI_H__
+#define __RK30_HDMI_H__
+
+#include "../../rk_hdmi.h"
+
+
+extern int rk30_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
+                                        void (*hdcp_irq_cb)(int status),
+                                        int  (*hdcp_power_on_cb)(void),
+                                        void (*hdcp_power_off_cb)(void));
+#endif /* __RK30_HDMI_H__ */
diff --git a/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi_hw.c b/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi_hw.c
new file mode 100755 (executable)
index 0000000..e8b5f1e
--- /dev/null
@@ -0,0 +1,656 @@
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <mach/io.h>
+#include "rk30_hdmi.h"
+#include "rk30_hdmi_hw.h"
+
+static char edid_result = 0;
+
+static inline void delay100us(void)
+{
+       msleep(1);
+}
+
+int rk30_hdmi_initial(void)
+{
+       int rc = HDMI_ERROR_SUCESS;
+
+       hdmi->pwr_mode = PWR_SAVE_MODE_A;
+       hdmi->hdmi_removed = rk30_hdmi_removed ;
+       hdmi->control_output = rk30_hdmi_control_output;
+       hdmi->config_video = rk30_hdmi_config_video;
+       hdmi->config_audio = rk30_hdmi_config_audio;
+       hdmi->detect_hotplug = rk30_hdmi_detect_hotplug;
+       hdmi->read_edid = rk30_hdmi_read_edid;
+       // internal hclk = hdmi_hclk/20
+       HDMIWrReg(0x800, HDMI_INTERANL_CLK_DIV);
+       
+       if(hdmi->hdcp_power_on_cb)
+               rc = hdmi->hdcp_power_on_cb();
+
+       return rc;
+}
+
+static void rk30_hdmi_set_pwr_mode(int mode)
+{
+       if(hdmi->pwr_mode == mode)
+               return;
+       hdmi_dbg(hdmi->dev, "[%s] mode %d\n", __FUNCTION__, mode);      
+       switch(mode)
+       {
+               case PWR_SAVE_MODE_A:
+                       HDMIWrReg(SYS_CTRL, 0x10);
+                       break;
+               case PWR_SAVE_MODE_B:
+                       HDMIWrReg(SYS_CTRL, 0x20);
+                       break;
+               case PWR_SAVE_MODE_D:
+                       // reset PLL A&B
+                       HDMIWrReg(SYS_CTRL, 0x4C);
+                       delay100us();
+                       // release PLL A reset
+                       HDMIWrReg(SYS_CTRL, 0x48);
+                       delay100us();
+                       // release PLL B reset
+                       HDMIWrReg(SYS_CTRL, 0x40);
+                       break;
+               case PWR_SAVE_MODE_E:
+                       HDMIWrReg(SYS_CTRL, 0x80);
+                       break;
+       }
+       hdmi->pwr_mode = mode;
+       if(mode != PWR_SAVE_MODE_A)
+               msleep(10);
+       hdmi_dbg(hdmi->dev, "[%s] curmode %02x\n", __FUNCTION__, HDMIRdReg(SYS_CTRL));
+}
+
+int rk30_hdmi_detect_hotplug(void)
+{
+       int value =     HDMIRdReg(HPD_MENS_STA);
+       
+       hdmi_dbg(hdmi->dev, "[%s] value %02x\n", __FUNCTION__, value);
+       value &= m_HOTPLUG_STATUS | m_MSEN_STATUS;
+       if(value  == (m_HOTPLUG_STATUS | m_MSEN_STATUS) )
+               return HDMI_HPD_ACTIVED;
+       else if(value)
+               return HDMI_HPD_INSERT;
+       else
+               return HDMI_HPD_REMOVED;
+}
+
+#define HDMI_EDID_DDC_CLK      90000
+int rk30_hdmi_read_edid(int block, unsigned char *buff)
+{
+       int value, ret = -1, ddc_bus_freq = 0;
+       char interrupt = 0, trytime = 2;
+       unsigned long flags;
+       
+       hdmi_dbg(hdmi->dev, "[%s] block %d\n", __FUNCTION__, block);
+       spin_lock_irqsave(&hdmi->irq_lock, flags);
+       edid_result = 0;
+       spin_unlock_irqrestore(&hdmi->irq_lock, flags);
+       //Before Phy parameter was set, DDC_CLK is equal to PLLA freq which is 30MHz.
+       //Set DDC I2C CLK which devided from DDC_CLK to 100KHz.
+       ddc_bus_freq = (30000000/HDMI_EDID_DDC_CLK)/4;
+       HDMIWrReg(DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
+       HDMIWrReg(DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
+       
+       // Enable edid interrupt
+       HDMIWrReg(INTR_MASK1, m_INT_HOTPLUG | m_INT_MSENS | m_INT_EDID_ERR | m_INT_EDID_READY);
+       
+       while(trytime--) {
+               // Config EDID block and segment addr
+               HDMIWrReg(EDID_WORD_ADDR, (block%2) * 0x80);
+               HDMIWrReg(EDID_SEGMENT_POINTER, block/2);       
+       
+               value = 100;
+               while(value--)
+               {
+                       spin_lock_irqsave(&hdmi->irq_lock, flags);
+                       interrupt = edid_result;
+                       edid_result = 0;
+                       spin_unlock_irqrestore(&hdmi->irq_lock, flags);
+                       if(interrupt & (m_INT_EDID_ERR | m_INT_EDID_READY))
+                               break;
+                       msleep(10);
+               }
+               hdmi_dbg(hdmi->dev, "[%s] edid read value %d\n", __FUNCTION__, value);
+               if(interrupt & m_INT_EDID_READY)
+               {
+                       for(value = 0; value < HDMI_EDID_BLOCK_SIZE; value++) 
+                               buff[value] = HDMIRdReg(DDC_READ_FIFO_ADDR);
+                       ret = 0;
+                       
+                       hdmi_dbg(hdmi->dev, "[%s] edid read sucess\n", __FUNCTION__);
+#ifdef HDMI_DEBUG
+                       for(value = 0; value < 128; value++) {
+                               printk("%02x ,", buff[value]);
+                               if( (value + 1) % 16 == 0)
+                                       printk("\n");
+                       }
+#endif
+                       break;
+               }               
+               if(interrupt & m_INT_EDID_ERR)
+                       hdmi_err(hdmi->dev, "[%s] edid read error\n", __FUNCTION__);
+
+       }
+       // Disable edid interrupt
+       HDMIWrReg(INTR_MASK1, m_INT_HOTPLUG | m_INT_MSENS);
+//     msleep(100);
+       return ret;
+}
+
+static inline void rk30_hdmi_config_phy_reg(int reg, int value)
+{
+       HDMIWrReg(reg, value);
+       HDMIWrReg(SYS_CTRL, 0x2C);
+       delay100us();
+       HDMIWrReg(SYS_CTRL, 0x20);
+       msleep(1);
+}
+
+static void rk30_hdmi_config_phy(unsigned char vic)
+{
+       HDMIWrReg(DEEP_COLOR_MODE, 0x22);       // tmds frequency same as input dlck
+       rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_B);
+       switch(vic)
+       {
+               case HDMI_1920x1080p_60Hz:
+               case HDMI_1920x1080p_50Hz:
+                       rk30_hdmi_config_phy_reg(0x158, 0x0E);
+                       rk30_hdmi_config_phy_reg(0x15c, 0x00);
+                       rk30_hdmi_config_phy_reg(0x160, 0x60);
+                       rk30_hdmi_config_phy_reg(0x164, 0x00);
+                       rk30_hdmi_config_phy_reg(0x168, 0xDA);
+                       rk30_hdmi_config_phy_reg(0x16c, 0xA1);
+                       rk30_hdmi_config_phy_reg(0x170, 0x0e);
+                       rk30_hdmi_config_phy_reg(0x174, 0x22);
+                       rk30_hdmi_config_phy_reg(0x178, 0x00);
+                       break;
+                       
+               case HDMI_1920x1080i_60Hz:
+               case HDMI_1920x1080i_50Hz:
+               case HDMI_1280x720p_60Hz:
+               case HDMI_1280x720p_50Hz:
+                       rk30_hdmi_config_phy_reg(0x158, 0x06);
+                       rk30_hdmi_config_phy_reg(0x15c, 0x00);
+                       rk30_hdmi_config_phy_reg(0x160, 0x60);
+                       rk30_hdmi_config_phy_reg(0x164, 0x00);
+                       rk30_hdmi_config_phy_reg(0x168, 0xCA);
+                       rk30_hdmi_config_phy_reg(0x16c, 0xA3);
+                       rk30_hdmi_config_phy_reg(0x170, 0x0e);
+                       rk30_hdmi_config_phy_reg(0x174, 0x20);
+                       rk30_hdmi_config_phy_reg(0x178, 0x00);
+                       break;
+                       
+               case HDMI_720x576p_50Hz_4_3:
+               case HDMI_720x576p_50Hz_16_9:
+               case HDMI_720x480p_60Hz_4_3:
+               case HDMI_720x480p_60Hz_16_9:
+                       rk30_hdmi_config_phy_reg(0x158, 0x02);
+                       rk30_hdmi_config_phy_reg(0x15c, 0x00);
+                       rk30_hdmi_config_phy_reg(0x160, 0x60);
+                       rk30_hdmi_config_phy_reg(0x164, 0x00);
+                       rk30_hdmi_config_phy_reg(0x168, 0xC2);
+                       rk30_hdmi_config_phy_reg(0x16c, 0xA2);
+                       rk30_hdmi_config_phy_reg(0x170, 0x0e);
+                       rk30_hdmi_config_phy_reg(0x174, 0x20);
+                       rk30_hdmi_config_phy_reg(0x178, 0x00);
+                       break;
+               default:
+                       hdmi_err(hdmi->dev, "not support such vic %d\n", vic);
+                       break;
+       }
+}
+
+static void rk30_hdmi_config_avi(unsigned char vic, unsigned char output_color)
+{
+       int i, clolorimetry, aspect_ratio;
+       char info[SIZE_AVI_INFOFRAME];
+       
+       memset(info, 0, SIZE_AVI_INFOFRAME);
+       HDMIWrReg(CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
+       info[0] = 0x82;
+       info[1] = 0x02;
+       info[2] = 0x0D; 
+       info[3] = info[0] + info[1] + info[2];
+
+       if(output_color == VIDEO_OUTPUT_YCBCR444)       
+               info[4] = (AVI_COLOR_MODE_YCBCR444 << 5);
+       else if(output_color == VIDEO_OUTPUT_YCBCR422)
+               info[4] = (AVI_COLOR_MODE_YCBCR422 << 5);
+       else
+               info[4] = (AVI_COLOR_MODE_RGB << 5);
+       info[4] |= (1 << 4);    //Enable active format data bits is present in info[2]
+       
+       switch(vic)
+       {
+               case HDMI_720x480i_60Hz_4_3:
+               case HDMI_720x576i_50Hz_4_3:
+               case HDMI_720x480p_60Hz_4_3:
+               case HDMI_720x576p_50Hz_4_3:                            
+                       aspect_ratio = AVI_CODED_FRAME_ASPECT_4_3;
+                       clolorimetry = AVI_COLORIMETRY_SMPTE_170M;
+                       break;
+               case HDMI_720x480i_60Hz_16_9:
+               case HDMI_720x576i_50Hz_16_9:
+               case HDMI_720x480p_60Hz_16_9:
+               case HDMI_720x576p_50Hz_16_9:
+                       aspect_ratio = AVI_CODED_FRAME_ASPECT_16_9;
+                       clolorimetry = AVI_COLORIMETRY_SMPTE_170M;
+                       break;
+               default:
+                       aspect_ratio = AVI_CODED_FRAME_ASPECT_16_9;
+                       clolorimetry = AVI_COLORIMETRY_ITU709;
+       }
+
+       if(output_color == VIDEO_OUTPUT_RGB444)
+               clolorimetry = AVI_COLORIMETRY_NO_DATA;
+       
+       info[5] = (clolorimetry << 6) | (aspect_ratio << 4) | ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME;
+       info[6] = 0;
+       info[7] = vic;
+       info[8] = 0;
+
+       // Calculate AVI InfoFrame ChecKsum
+       for (i = 4; i < SIZE_AVI_INFOFRAME; i++)
+       {
+       info[3] += info[i];
+       }
+       info[3] = 0x100 - info[3];
+       
+       for(i = 0; i < SIZE_AVI_INFOFRAME; i++)
+               HDMIWrReg(CONTROL_PACKET_HB0 + i*4, info[i]);
+}
+static char coeff_csc[][24] = {
+               //G                     B                       R                       Bias
+       {       //CSC_RGB_0_255_TO_ITU601_16_235
+               0x11, 0xb6, 0x02, 0x0b, 0x10, 0x55, 0x00, 0x80,         //Cr
+               0x02, 0x59, 0x01, 0x32, 0x00, 0x75, 0x00, 0x10,         //Y
+               0x11, 0x5b, 0x10, 0xb0, 0x02, 0x0b, 0x00, 0x80,         //Cb
+       },
+       {       //CSC_RGB_0_255_TO_ITU709_16_235
+               0x11, 0xdb, 0x02, 0x0b, 0x10, 0x30, 0x00, 0x80,         //Cr
+               0x02, 0xdc, 0x00, 0xda, 0x00, 0x4a, 0x00, 0x10,         //Y
+               0x11, 0x93, 0x10, 0x78, 0x02, 0x0b, 0x00, 0x80,         //Cb
+       },
+               //Y                     Cr                      Cb                      Bias
+       {       //CSC_ITU601_16_235_TO_RGB_16_235
+               0x04, 0x00, 0x05, 0x7c, 0x00, 0x00, 0x02, 0xaf,         //R
+               0x04, 0x00, 0x12, 0xcb, 0x11, 0x58, 0x00, 0x84,         //G
+               0x04, 0x00, 0x00, 0x00, 0x06, 0xee, 0x02, 0xde,         //B
+       },
+       {       //CSC_ITU709_16_235_TO_RGB_16_235
+               0x04, 0x00, 0x06, 0x29, 0x00, 0x00, 0x02, 0xc5,         //R
+               0x04, 0x00, 0x11, 0xd6, 0x10, 0xbb, 0x00, 0x52,         //G
+               0x04, 0x00, 0x00, 0x00, 0x07, 0x44, 0x02, 0xe8,         //B
+       },
+       {       //CSC_ITU601_16_235_TO_RGB_0_255
+               0x04, 0xa8, 0x05, 0x7c, 0x00, 0x00, 0x02, 0xc2,         //R
+               0x04, 0xa8, 0x12, 0xcb, 0x11, 0x58, 0x00, 0x72,         //G
+               0x04, 0xa8, 0x00, 0x00, 0x06, 0xee, 0x02, 0xf0,         //B
+       },
+       {       //CSC_ITU709_16_235_TO_RGB_0_255
+               0x04, 0xa8, 0x06, 0x29, 0x00, 0x00, 0x02, 0xd8,         //R
+               0x04, 0xa8, 0x11, 0xd6, 0x10, 0xbb, 0x00, 0x40,         //G
+               0x04, 0xa8, 0x00, 0x00, 0x07, 0x44, 0x02, 0xfb,         //B
+       },
+       
+};
+
+static void rk30_hdmi_config_csc(struct hdmi_video_para *vpara)
+{
+       int i, mode;
+       char *coeff = NULL;
+               
+       if( ((vpara->input_color == VIDEO_INPUT_COLOR_RGB) && (vpara->output_color == VIDEO_OUTPUT_RGB444)) ||
+               ((vpara->input_color == VIDEO_INPUT_COLOR_YCBCR) && (vpara->output_color != VIDEO_OUTPUT_RGB444) ))
+       {
+               return;
+       }
+       switch(vpara->vic)
+       {
+               case HDMI_720x480i_60Hz_4_3:
+               case HDMI_720x576i_50Hz_4_3:
+               case HDMI_720x480p_60Hz_4_3:
+               case HDMI_720x576p_50Hz_4_3:
+               case HDMI_720x480i_60Hz_16_9:
+               case HDMI_720x576i_50Hz_16_9:
+               case HDMI_720x480p_60Hz_16_9:
+               case HDMI_720x576p_50Hz_16_9:
+                       if(vpara->input_color == VIDEO_INPUT_COLOR_RGB)
+                               mode = CSC_RGB_0_255_TO_ITU601_16_235;
+                       else if(vpara->output_mode == OUTPUT_HDMI)
+                               mode = CSC_ITU601_16_235_TO_RGB_16_235;
+                       else
+                               mode = CSC_ITU601_16_235_TO_RGB_0_255;
+                       break;
+               default:
+                       if(vpara->input_color == VIDEO_INPUT_COLOR_RGB)
+                               mode = CSC_RGB_0_255_TO_ITU709_16_235;
+                       else if(vpara->output_mode == OUTPUT_HDMI)
+                               mode = CSC_ITU709_16_235_TO_RGB_16_235;
+                       else
+                               mode = CSC_ITU709_16_235_TO_RGB_0_255;
+                       break;
+       }
+       
+       coeff = coeff_csc[mode];
+       
+       HDMIWrReg(CSC_CONFIG1, v_CSC_MODE(CSC_MODE_MANUAL) | v_CSC_BRSWAP_DIABLE(1));
+       
+       for(i = 0; i < 24; i++)
+               HDMIWrReg(CSC_PARA_C0_H + i*4, coeff[i]);
+               
+       HDMIWrReg(AV_CTRL2, v_CSC_ENABLE(1));
+}
+
+int rk30_hdmi_config_video(struct hdmi_video_para *vpara)
+{
+       int value;
+       struct fb_videomode *mode;
+       
+       hdmi_dbg(hdmi->dev, "[%s]\n", __FUNCTION__);
+       if(vpara == NULL) {
+               hdmi_err(hdmi->dev, "[%s] input parameter error\n", __FUNCTION__);
+               return -1;
+       }
+       if(hdmi->pwr_mode == PWR_SAVE_MODE_E)
+               rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_D);
+       if(hdmi->pwr_mode == PWR_SAVE_MODE_D || hdmi->pwr_mode == PWR_SAVE_MODE_A)
+               rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_B);
+       
+       if(hdmi->hdcp_power_off_cb)
+               hdmi->hdcp_power_off_cb();
+               
+       // Input video mode is RGB24bit, Data enable signal from external
+       HDMIMskReg(value, AV_CTRL1, m_INPUT_VIDEO_MODE | m_DE_SIGNAL_SELECT, \
+               v_INPUT_VIDEO_MODE(vpara->input_mode) | EXTERNAL_DE)    
+       HDMIMskReg(value, VIDEO_CTRL1, m_VIDEO_OUTPUT_MODE | m_VIDEO_INPUT_DEPTH | m_VIDEO_INPUT_COLOR_MODE, \
+               v_VIDEO_OUTPUT_MODE(vpara->output_color) | v_VIDEO_INPUT_DEPTH(VIDEO_INPUT_DEPTH_8BIT) | vpara->input_color)
+       HDMIWrReg(DEEP_COLOR_MODE, 0x20);
+       // color space convert
+       rk30_hdmi_config_csc(vpara);
+       // Set HDMI Mode
+       HDMIWrReg(HDCP_CTRL, v_HDMI_DVI(vpara->output_mode));
+
+       // Set ext video
+       mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
+       if(mode == NULL)
+       {
+               hdmi_err(hdmi->dev, "[%s] not found vic %d\n", __FUNCTION__, vpara->vic);
+               return -ENOENT;
+       }
+       hdmi->tmdsclk = mode->pixclock;
+
+       if( (vpara->vic == HDMI_720x480p_60Hz_4_3) || (vpara->vic == HDMI_720x480p_60Hz_16_9) )
+               value = v_VSYNC_OFFSET(6);
+       else
+               value = v_VSYNC_OFFSET(0);
+       value |= v_EXT_VIDEO_ENABLE(1) | v_INTERLACE(mode->vmode);
+       if(mode->sync & FB_SYNC_HOR_HIGH_ACT)
+               value |= v_HSYNC_POLARITY(1);
+       if(mode->sync & FB_SYNC_VERT_HIGH_ACT)
+               value |= v_VSYNC_POLARITY(1);
+       HDMIWrReg(EXT_VIDEO_PARA, value);
+       value = mode->left_margin + mode->xres + mode->right_margin + mode->hsync_len;
+       HDMIWrReg(EXT_VIDEO_PARA_HTOTAL_L, value & 0xFF);
+       HDMIWrReg(EXT_VIDEO_PARA_HTOTAL_H, (value >> 8) & 0xFF);
+       
+       value = mode->left_margin + mode->right_margin + mode->hsync_len;
+       HDMIWrReg(EXT_VIDEO_PARA_HBLANK_L, value & 0xFF);
+       HDMIWrReg(EXT_VIDEO_PARA_HBLANK_H, (value >> 8) & 0xFF);
+       
+       value = mode->left_margin + mode->hsync_len;
+       HDMIWrReg(EXT_VIDEO_PARA_HDELAY_L, value & 0xFF);
+       HDMIWrReg(EXT_VIDEO_PARA_HDELAY_H, (value >> 8) & 0xFF);
+       
+       value = mode->hsync_len;
+       HDMIWrReg(EXT_VIDEO_PARA_HSYNCWIDTH_L, value & 0xFF);
+       HDMIWrReg(EXT_VIDEO_PARA_HSYNCWIDTH_H, (value >> 8) & 0xFF);
+       
+       value = mode->upper_margin + mode->yres + mode->lower_margin + mode->vsync_len;
+       HDMIWrReg(EXT_VIDEO_PARA_VTOTAL_L, value & 0xFF);
+       HDMIWrReg(EXT_VIDEO_PARA_VTOTAL_H, (value >> 8) & 0xFF);
+       
+       value = mode->upper_margin + mode->vsync_len + mode->lower_margin;
+       HDMIWrReg(EXT_VIDEO_PARA_VBLANK_L, value & 0xFF);
+       
+       if(vpara->vic == HDMI_720x480p_60Hz_4_3 || vpara->vic == HDMI_720x480p_60Hz_16_9)
+               value = 42;
+       else
+               value = mode->upper_margin + mode->vsync_len;
+
+       HDMIWrReg(EXT_VIDEO_PARA_VDELAY, value & 0xFF);
+       
+       value = mode->vsync_len;
+       HDMIWrReg(EXT_VIDEO_PARA_VSYNCWIDTH, value & 0xFF);
+       
+       if(vpara->output_mode == OUTPUT_HDMI) {
+               rk30_hdmi_config_avi(vpara->vic, vpara->output_color);
+               hdmi_dbg(hdmi->dev, "[%s] sucess output HDMI.\n", __FUNCTION__);
+       }
+       else {
+               hdmi_dbg(hdmi->dev, "[%s] sucess output DVI.\n", __FUNCTION__); 
+       }
+       
+       rk30_hdmi_config_phy(vpara->vic);
+       rk30_hdmi_control_output(0);
+       return 0;
+}
+
+static void rk30_hdmi_config_aai(void)
+{
+       int i;
+       char info[SIZE_AUDIO_INFOFRAME];
+       
+       memset(info, 0, SIZE_AUDIO_INFOFRAME);
+       
+       info[0] = 0x84;
+       info[1] = 0x01;
+       info[2] = 0x0A;
+       
+       info[3] = info[0] + info[1] + info[2];  
+       for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)
+       info[3] += info[i];
+       
+       info[3] = 0x100 - info[3];
+       
+       HDMIWrReg(CONTROL_PACKET_BUF_INDEX, INFOFRAME_AAI);
+       for(i = 0; i < SIZE_AUDIO_INFOFRAME; i++)
+               HDMIWrReg(CONTROL_PACKET_HB0 + i*4, info[i]);
+}
+
+int rk30_hdmi_config_audio(struct hdmi_audio *audio)
+{
+       int value, rate, N;
+       char word_length, channel;
+       
+       if(audio->channel < 3)
+               channel = I2S_CHANNEL_1_2;
+       else if(audio->channel < 5)
+               channel = I2S_CHANNEL_3_4;
+       else if(audio->channel < 7)
+               channel = I2S_CHANNEL_5_6;
+       else
+               channel = I2S_CHANNEL_7_8;
+       
+       switch(audio->rate)
+       {
+               case HDMI_AUDIO_FS_32000:
+                       rate = AUDIO_32K;
+                       N = N_32K;
+                       break;
+               case HDMI_AUDIO_FS_44100:
+                       rate = AUDIO_441K;
+                       N = N_441K;
+                       break;
+               case HDMI_AUDIO_FS_48000:
+                       rate = AUDIO_48K;
+                       N = N_48K;
+                       break;
+               case HDMI_AUDIO_FS_88200:
+                       rate = AUDIO_882K;
+                       N = N_882K;
+                       break;
+               case HDMI_AUDIO_FS_96000:
+                       rate = AUDIO_96K;
+                       N = N_96K;
+                       break;
+               case HDMI_AUDIO_FS_176400:
+                       rate = AUDIO_1764K;
+                       N = N_1764K;
+                       break;
+               case HDMI_AUDIO_FS_192000:
+                       rate = AUDIO_192K;
+                       N = N_192K;
+                       break;
+               default:
+                       hdmi_err(hdmi->dev, "[%s] not support such sample rate %d\n", __FUNCTION__, audio->rate);
+                       return -ENOENT;
+       }
+//     switch(audio->word_length)
+//     {
+//             case HDMI_AUDIO_WORD_LENGTH_16bit:
+//                     word_length = 0x02;
+//                     break;
+//             case HDMI_AUDIO_WORD_LENGTH_20bit:
+//                     word_length = 0x0a;
+//                     break;
+//             case HDMI_AUDIO_WORD_LENGTH_24bit:
+//                     word_length = 0x0b;
+//                     break;
+//             default:
+//                     hdmi_err(hdmi->dev, "[%s] not support such word length %d\n", __FUNCTION__, audio->word_length);
+//                     return -ENOENT;
+//     }
+       //set_audio_if I2S
+       HDMIWrReg(AUDIO_CTRL1, 0x00); //internal CTS, disable down sample, i2s input, disable MCLK
+       HDMIWrReg(AUDIO_CTRL2, 0x40); 
+       HDMIWrReg(I2S_AUDIO_CTRL, v_I2S_MODE(I2S_MODE_STANDARD) | v_I2S_CHANNEL(channel) );     
+       HDMIWrReg(I2S_INPUT_SWAP, 0x00); //no swap
+       HDMIMskReg(value, AV_CTRL1, m_AUDIO_SAMPLE_RATE, v_AUDIO_SAMPLE_RATE(rate))     
+//     HDMIWrReg(SRC_NUM_AUDIO_LEN, word_length);
+               
+    //Set N value 6144, fs=48kHz
+    HDMIWrReg(N_1, N & 0xFF);
+    HDMIWrReg(N_2, (N >> 8) & 0xFF);
+    HDMIWrReg(LR_SWAP_N3, (N >> 16) & 0x0F); 
+    
+    rk30_hdmi_config_aai();
+    return 0;
+}
+
+static void rk30_hdmi_audio_reset(void)
+{
+       int value;
+       
+       HDMIMskReg(value, VIDEO_SETTING2, m_AUDIO_RESET, AUDIO_CAPTURE_RESET)
+       msleep(1);
+       HDMIMskReg(value, VIDEO_SETTING2, m_AUDIO_RESET, 0)
+}
+
+void rk30_hdmi_control_output(int enable)
+{
+       hdmi_dbg(hdmi->dev, "[%s] %d\n", __FUNCTION__, enable);
+       if(enable == 0) {
+               HDMIWrReg(AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
+       }
+       else {
+               HDMIWrReg(VIDEO_SETTING2, 0x03);
+               if(hdmi->pwr_mode == PWR_SAVE_MODE_B) {
+                       //  Switch to power save mode_d
+                       rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_D);
+               }
+               if(hdmi->pwr_mode == PWR_SAVE_MODE_D) {
+                       //  Switch to power save mode_e
+                       rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_E);
+               }
+               HDMIWrReg(VIDEO_SETTING2, 0x00);
+               rk30_hdmi_audio_reset();
+       }
+}
+
+int rk30_hdmi_removed(void)
+{
+       if(hdmi->pwr_mode == PWR_SAVE_MODE_E)
+       {
+               HDMIWrReg(VIDEO_SETTING2, 0x00);
+               rk30_hdmi_audio_reset();
+               rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_D);
+       }
+       if(hdmi->pwr_mode == PWR_SAVE_MODE_D)
+               rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_B);
+       if(hdmi->pwr_mode == PWR_SAVE_MODE_B && hdmi->state == HDMI_SLEEP)
+       {
+               HDMIWrReg(INTR_MASK1, m_INT_HOTPLUG | m_INT_MSENS);
+               HDMIWrReg(INTR_MASK2, 0);
+               HDMIWrReg(INTR_MASK3, 0);
+               HDMIWrReg(INTR_MASK4, 0);
+               // Disable color space convertion
+               HDMIWrReg(AV_CTRL2, v_CSC_ENABLE(0));
+               HDMIWrReg(CSC_CONFIG1, v_CSC_MODE(CSC_MODE_AUTO) | v_CSC_BRSWAP_DIABLE(1));
+               if(hdmi->hdcp_power_off_cb)
+                       hdmi->hdcp_power_off_cb();
+               rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_A);
+       }
+       dev_printk(KERN_INFO , hdmi->dev , "Removed.\n");
+       return HDMI_ERROR_SUCESS;
+}
+
+
+irqreturn_t hdmi_irq(int irq, void *priv)
+{              
+       char interrupt1 = 0, interrupt2 = 0, interrupt3 = 0, interrupt4 = 0;
+       
+       if(hdmi->pwr_mode == PWR_SAVE_MODE_A)
+       {
+               HDMIWrReg(SYS_CTRL, 0x20);
+               hdmi->pwr_mode = PWR_SAVE_MODE_B;
+               
+               hdmi_dbg(hdmi->dev, "hdmi irq wake up\n");
+               // HDMI was inserted when system is sleeping, irq was triggered only once
+               // when wake up. So we need to check hotplug status.
+               if(HDMIRdReg(HPD_MENS_STA) & (m_HOTPLUG_STATUS | m_MSEN_STATUS)) {                      
+                       queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));
+               }
+       }
+       else
+       {
+               interrupt1 = HDMIRdReg(INTR_STATUS1);
+               interrupt2 = HDMIRdReg(INTR_STATUS2);
+               interrupt3 = HDMIRdReg(INTR_STATUS3);
+               interrupt4 = HDMIRdReg(INTR_STATUS4);
+               HDMIWrReg(INTR_STATUS1, interrupt1);
+               HDMIWrReg(INTR_STATUS2, interrupt2);
+               HDMIWrReg(INTR_STATUS3, interrupt3);
+               HDMIWrReg(INTR_STATUS4, interrupt4);
+#if 0
+               hdmi_dbg(hdmi->dev, "[%s] interrupt1 %02x interrupt2 %02x interrupt3 %02x interrupt4 %02x\n",\
+                        __FUNCTION__, interrupt1, interrupt2, interrupt3, interrupt4);
+#endif
+               if(interrupt1 & (m_INT_HOTPLUG | m_INT_MSENS))
+               {
+                       if(hdmi->state == HDMI_SLEEP)
+                               hdmi->state = WAIT_HOTPLUG;
+                       interrupt1 &= ~(m_INT_HOTPLUG | m_INT_MSENS);
+                       queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));   
+               }
+               else if(interrupt1 & (m_INT_EDID_READY | m_INT_EDID_ERR)) {
+                       spin_lock(&hdmi->irq_lock);
+                       edid_result = interrupt1;
+                       spin_unlock(&hdmi->irq_lock);
+               }
+               else if(hdmi->state == HDMI_SLEEP) {
+                       hdmi_dbg(hdmi->dev, "hdmi return to sleep mode\n");
+                       HDMIWrReg(SYS_CTRL, 0x10);
+                       hdmi->pwr_mode = PWR_SAVE_MODE_A;
+               }
+               if(interrupt2 && hdmi->hdcp_irq_cb)
+                       hdmi->hdcp_irq_cb(interrupt2);
+       }
+       return IRQ_HANDLED;
+}
+
diff --git a/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi_hw.h b/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi_hw.h
new file mode 100755 (executable)
index 0000000..c42f061
--- /dev/null
@@ -0,0 +1,422 @@
+#ifndef __RK30_HDMI_HW_H__
+#define __RK30_HDMI_HW_H__
+
+/* HDMI_SYS_CONTROL */
+#define SYS_CTRL       0x0
+
+enum {
+       PWR_SAVE_MODE_A = 1,
+       PWR_SAVE_MODE_B = 2,
+       PWR_SAVE_MODE_D = 4,
+       PWR_SAVE_MODE_E = 8
+};
+#define m_PWR_SAVE_MODE                0xF0
+#define v_PWR_SAVE_MODE(n)     (n << 4)
+#define PLL_B_RESET                    (1 << 3)
+
+#define N_32K          0x1000
+#define N_441K                 0x1880
+#define N_882K                 0x3100
+#define N_1764K        0x6200
+#define N_48K          0x1800
+#define N_96K          0x3000
+#define N_192K                 0x6000
+
+#define LR_SWAP_N3                     0x04
+#define N_2                                    0x08
+#define N_1                                    0x0c
+
+#define AUDIO_CTRL1                    0x28
+#define AUDIO_CTRL2            0x2c
+#define I2S_AUDIO_CTRL         0x30
+enum {
+       I2S_MODE_STANDARD = 0,
+       I2S_MODE_RIGHT_JUSTIFIED,
+       I2S_MODE_LEFT_JUSTIFIED
+};
+#define v_I2S_MODE(n)          n
+enum {
+       I2S_CHANNEL_1_2 = 1,
+       I2S_CHANNEL_3_4 = 3,
+       I2S_CHANNEL_5_6 = 7,
+       I2S_CHANNEL_7_8 = 0xf
+};
+#define v_I2S_CHANNEL(n)       ( (n) << 2 )
+
+#define I2S_INPUT_SWAP         0x40
+
+#define SRC_NUM_AUDIO_LEN      0x50
+
+/* HDMI_AV_CTRL1*/
+#define AV_CTRL1       0x54
+enum {
+       AUDIO_32K       = 0x3,
+       AUDIO_441K      = 0x0,
+       AUDIO_48K       = 0x2,
+       AUDIO_882K      = 0x8,
+       AUDIO_96K       = 0xa,
+       AUDIO_1764K     = 0xc,
+       AUDIO_192K      = 0xe,
+};
+#define m_AUDIO_SAMPLE_RATE            0xF0
+#define v_AUDIO_SAMPLE_RATE(n) (n << 4)
+#define m_INPUT_VIDEO_MODE                     (7 << 1)
+#define v_INPUT_VIDEO_MODE(n)          (n << 1)
+enum {
+       INTERNAL_DE = 0,
+       EXTERNAL_DE
+};
+#define m_DE_SIGNAL_SELECT                     (1 << 0)
+
+/* HDMI_AV_CTRL2 */
+#define AV_CTRL2       0xec
+#define m_CSC_ENABLE                           (1 << 0)
+#define v_CSC_ENABLE(n)                                (n)
+
+/* HDMI_VIDEO_CTRL1 */
+#define VIDEO_CTRL1    0x58
+
+#define m_VIDEO_OUTPUT_MODE            (0x3 << 6)
+#define v_VIDEO_OUTPUT_MODE(n) (n << 6)
+enum {
+       VIDEO_INPUT_DEPTH_12BIT = 0,
+       VIDEO_INPUT_DEPTH_10BIT = 0x1,
+       VIDEO_INPUT_DEPTH_8BIT = 0x3
+};
+#define m_VIDEO_INPUT_DEPTH            (3 << 4)
+#define v_VIDEO_INPUT_DEPTH(n) (n << 4)
+enum {
+       VIDEO_EMBEDDED_SYNC_LOCATION_0 = 0,
+       VIDEO_EMBEDDED_SYNC_LOCATION_1,
+       VIDEO_EMBEDDED_SYNC_LOCATION_2
+};
+#define m_VIDEO_EMBEDDED_SYNC_LOCATION         (3 << 2)
+#define VIDEO_EMBEDDED_SYNC_LOCATION(n)                (n << 2)
+#define m_VIDEO_INPUT_COLOR_MODE                       (1 << 0)
+
+/* DEEP_COLOR_MODE */
+#define DEEP_COLOR_MODE        0x5c
+enum{
+       TMDS_CLOCK_MODE_8BIT = 0,
+       TMDS_CLOKK_MODE_10BIT,
+       TMDS_CLOKK_MODE_12BIT
+};
+#define TMDS_CLOCK_MODE_MASK   0x3 << 6
+#define TMDS_CLOCK_MODE(n)             (n) << 6
+
+/* VIDEO_CTRL2 */
+#define VIDEO_SETTING2 0x114
+#define m_UNMUTE                                       (1 << 7)
+#define m_MUTE                                         (1 << 6)
+#define m_AUDIO_RESET                          (1 << 2)
+#define m_NOT_SEND_AUDIO                       (1 << 1)
+#define m_NOT_SEND_VIDEO                       (1 << 0)
+#define AV_UNMUTE                                      (1 << 7)                // Unmute video and audio, send normal video and audio data
+#define AV_MUTE                                                (1 << 6)                // Mute video and audio, send black video data and silent audio data
+#define AUDIO_CAPTURE_RESET                    (1 << 2)                // Reset audio process logic, only available in pwr_e mode.
+#define NOT_SEND_AUDIO                         (1 << 1)                // Send silent audio data
+#define NOT_SEND_VIDEO                         (1 << 0)                // Send black video data
+
+/* Color Space Convertion Parameter*/
+#define CSC_PARA_C0_H  0x60
+#define CSC_PARA_C0_L  0x64
+#define CSC_PARA_C1_H  0x68
+#define CSC_PARA_C1_L  0x6c
+#define CSC_PARA_C2_H  0x70
+#define CSC_PARA_C2_L  0x74
+#define CSC_PARA_C3_H  0x78
+#define CSC_PARA_C3_L  0x7c
+#define CSC_PARA_C4_H  0x80
+#define CSC_PARA_C4_L  0x84
+#define CSC_PARA_C5_H  0x88
+#define CSC_PARA_C5_L  0x8c
+#define CSC_PARA_C6_H  0x90
+#define CSC_PARA_C6_L  0x94
+#define CSC_PARA_C7_H  0x98
+#define CSC_PARA_C7_L  0x9c
+#define CSC_PARA_C8_H  0xa0
+#define CSC_PARA_C8_L  0xa4
+#define CSC_PARA_C9_H  0xa8
+#define CSC_PARA_C9_L  0xac
+#define CSC_PARA_C10_H 0xac
+#define CSC_PARA_C10_L 0xb4
+#define CSC_PARA_C11_H 0xb8
+#define CSC_PARA_C11_L 0xbc
+
+#define CSC_CONFIG1            0x34c
+#define m_CSC_MODE                     (1 << 7)
+#define m_CSC_COEF_MODE        (0xF << 3)      //Only used in auto csc mode
+#define m_CSC_STATUS           (1 << 2)
+#define m_CSC_VID_SELECT       (1 << 1)
+#define m_CSC_BRSWAP_DIABLE    (1)
+
+enum {
+       CSC_MODE_MANUAL = 0,
+       CSC_MODE_AUTO
+};
+#define v_CSC_MODE(n)                  (n << 7)
+enum {
+       COE_SDTV_LIMITED_RANGE = 0x08,
+       COE_SDTV_FULL_RANGE = 0x04,
+       COE_HDTV_60Hz = 0x2,
+       COE_HDTV_50Hz = 0x1
+};
+#define v_CSC_COE_MODE(n)              (n << 3)
+enum {
+       CSC_INPUT_VID_5_19 = 0,
+       CSC_INPUT_VID_28_29
+};
+#define v_CSC_VID_SELECT(n)            (n << 1)
+#define v_CSC_BRSWAP_DIABLE(n) (n)
+
+/* CONTROL_PACKET_BUF_INDEX */
+#define CONTROL_PACKET_BUF_INDEX       0x17c
+enum {
+       INFOFRAME_AVI = 0x06,
+       INFOFRAME_AAI = 0x08
+};
+#define CONTROL_PACKET_HB0                     0x180
+#define CONTROL_PACKET_HB1                     0x184
+#define CONTROL_PACKET_HB2                     0x188
+#define CONTROL_PACKET_PB_ADDR         0x18c
+#define SIZE_AVI_INFOFRAME                     0x11    // 17 bytes
+#define SIZE_AUDIO_INFOFRAME           0x0F    // 15 bytes
+enum {
+       AVI_COLOR_MODE_RGB = 0,
+       AVI_COLOR_MODE_YCBCR422,
+       AVI_COLOR_MODE_YCBCR444
+};
+enum {
+       AVI_COLORIMETRY_NO_DATA = 0,
+       AVI_COLORIMETRY_SMPTE_170M,
+       AVI_COLORIMETRY_ITU709,
+       AVI_COLORIMETRY_EXTENDED
+};
+enum {
+       AVI_CODED_FRAME_ASPECT_NO_DATA,
+       AVI_CODED_FRAME_ASPECT_4_3,
+       AVI_CODED_FRAME_ASPECT_16_9
+};
+enum {
+       ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME = 0x08,
+       ACTIVE_ASPECT_RATE_4_3,
+       ACTIVE_ASPECT_RATE_16_9,
+       ACTIVE_ASPECT_RATE_14_9
+};
+
+/* External Video Parameter Setting*/
+#define EXT_VIDEO_PARA                 0xC0
+#define m_VSYNC_OFFSET                 (0xF << 4)
+#define m_VSYNC_POLARITY               (1 << 3)
+#define m_HSYNC_POLARITY               (1 << 2)
+#define m_INTERLACE                            (1 << 1)
+#define m_EXT_VIDEO_ENABLE             (1 << 0)
+
+#define v_VSYNC_OFFSET(n)              (n << 4)
+#define v_VSYNC_POLARITY(n)            (n << 3)
+#define v_HSYNC_POLARITY(n)            (n << 2)
+#define v_INTERLACE(n)                 (n << 1)
+#define v_EXT_VIDEO_ENABLE(n)  (n << 0) 
+
+#define EXT_VIDEO_PARA_HTOTAL_L                0xC4
+#define EXT_VIDEO_PARA_HTOTAL_H                0xC8
+#define EXT_VIDEO_PARA_HBLANK_L                0xCC
+#define EXT_VIDEO_PARA_HBLANK_H                0xD0
+#define EXT_VIDEO_PARA_HDELAY_L                0xD4
+#define EXT_VIDEO_PARA_HDELAY_H                0xD8
+#define EXT_VIDEO_PARA_HSYNCWIDTH_L    0xDC
+#define EXT_VIDEO_PARA_HSYNCWIDTH_H    0xE0
+
+#define EXT_VIDEO_PARA_VTOTAL_L                0xE4
+#define EXT_VIDEO_PARA_VTOTAL_H                0xE8
+#define EXT_VIDEO_PARA_VBLANK_L                0xF4
+#define EXT_VIDEO_PARA_VDELAY          0xF8
+#define EXT_VIDEO_PARA_VSYNCWIDTH      0xFC
+
+#define PHY_PLL_SPEED                          0x158
+       #define v_TEST_EN(n)                    (n << 6)
+       #define v_PLLA_BYPASS(n)                (n << 4)
+       #define v_PLLB_SPEED(n)                 (n << 2)
+       #define v_PLLA_SPEED(n)                 (n)
+       enum {
+               PLL_SPEED_LOWEST = 0,
+               PLL_SPEED_MIDLOW,
+               PLL_SPEED_MIDHIGH,
+               PLL_SPEED_HIGHEST
+       };
+
+#define PHY_PLL_17                                     0x15c           // PLL A & B config bit 17
+       #define v_PLLA_BIT17(n)                 (n << 2)
+       #define v_PLLB_BIT17(n)                 (n << 1)
+       
+#define PHY_BGR                                                0x160
+       #define v_BGR_DISCONNECT(n)             (n << 7)
+       #define v_BGR_V_OFFSET(n)               (n << 4)
+       #define v_BGR_I_OFFSET(n)               (n)
+
+#define PHY_PLLA_1                                     0x164
+#define PHY_PLLA_2                                     0x168
+#define PHY_PLLB_1                                     0x16c
+#define PHY_PLLB_2                                     0x170
+
+#define PHY_DRIVER_PREEMPHASIS         0x174
+       #define v_TMDS_SWING(n)                 (n << 4)
+       #define v_PRE_EMPHASIS(n)               (n)
+       
+#define PHY_PLL_16_AML                         0x178           // PLL A & B config bit 16 and AML control
+       #define v_PLLA_BIT16(n)                 (n << 5)
+       #define v_PLLB_BIT16(n)                 (n << 4)
+       #define v_AML(n)                                (n)
+
+/* Interrupt Setting */
+#define INTR_MASK1                                     0x248
+#define INTR_STATUS1                           0x250
+       #define m_INT_HOTPLUG                           (1 << 7)
+       #define m_INT_MSENS                                     (1 << 6)
+       #define m_INT_VSYNC                                     (1 << 5)
+       #define m_INT_AUDIO_FIFO_FULL           (1 << 4)
+       #define m_INT_EDID_READY                        (1 << 2)
+       #define m_INT_EDID_ERR                          (1 << 1)
+#define INTR_MASK2                                     0x24c
+#define INTR_STATUS2                           0x254
+       #define m_INT_HDCP_ERR                          (1 << 7)        // HDCP error detected
+       #define m_INT_BKSV_RPRDY                        (1 << 6)        // BKSV list ready from repeater
+       #define m_INT_BKSV_RCRDY                        (1 << 5)        // BKSV list ready from receiver
+       #define m_INT_AUTH_DONE                         (1 << 4)        // HDCP authentication done
+       #define m_INT_AUTH_READY                        (1 << 3)        // HDCP authentication ready
+#define INTR_MASK3                                     0x258
+#define INTR_STATUS3                           0x260
+
+#define INTR_MASK4                                     0x25c
+#define INTR_STATUS4                           0x264
+
+#define DDC_READ_FIFO_ADDR                     0x200
+#define DDC_BUS_FREQ_L                         0x204
+#define DDC_BUS_FREQ_H                         0x208
+#define DDC_BUS_CTRL                           0x2dc
+#define DDC_I2C_LEN                                    0x278
+#define DDC_I2C_OFFSET                         0x280
+#define DDC_I2C_CTRL                           0x284
+#define DDC_I2C_READ_BUF0                      0x288
+#define DDC_I2C_READ_BUF1                      0x28c
+#define DDC_I2C_READ_BUF2                      0x290
+#define DDC_I2C_READ_BUF3                      0x294
+#define DDC_I2C_WRITE_BUF0                     0x298
+#define DDC_I2C_WRITE_BUF1                     0x29c
+#define DDC_I2C_WRITE_BUF2                     0x2a0
+#define DDC_I2C_WRITE_BUF3                     0x2a4
+#define DDC_I2C_WRITE_BUF4                     0x2ac
+#define DDC_I2C_WRITE_BUF5                     0x2b0
+#define DDC_I2C_WRITE_BUF6                     0x2b4
+
+#define EDID_SEGMENT_POINTER           0x310
+#define EDID_WORD_ADDR                         0x314
+#define EDID_FIFO_ADDR                         0x318
+
+#define HPD_MENS_STA                           0x37c
+#define m_HOTPLUG_STATUS                       (1 << 7)
+#define m_MSEN_STATUS                          (1 << 6)
+
+/* HDCP_CTRL */
+#define HDCP_CTRL              0x2bc
+       enum {
+               OUTPUT_DVI = 0,
+               OUTPUT_HDMI
+       };
+       #define m_HDCP_AUTH_START                       (1 << 7)        // start hdcp
+       #define m_HDCP_BKSV_PASS                        (1 << 6)        // bksv valid
+       #define m_HDCP_BKSV_FAILED                      (1 << 5)        // bksv invalid
+       #define m_HDCP_FRAMED_ENCRYPED          (1 << 4)
+       #define m_HDCP_AUTH_STOP                        (1 << 3)        // stop hdcp
+       #define m_HDCP_ADV_CIPHER                       (1 << 2)        // advanced cipher mode
+       #define m_HDMI_DVI                                      (1 << 1)
+       #define m_HDCP_RESET                            (1 << 0)        // reset hdcp
+       #define v_HDCP_AUTH_START(n)            (n << 7)
+       #define v_HDCP_BKSV_PASS(n)                     (n << 6)
+       #define v_HDCP_BKSV_FAILED(n)           (n << 5)
+       #define v_HDCP_FRAMED_ENCRYPED(n)       (n << 4)
+       #define v_HDCP_AUTH_STOP(n)                     (n << 3)
+       #define v_HDCP_ADV_CIPHER(n)            (n << 2)
+       #define v_HDMI_DVI(n)                           (n << 1)
+       #define v_HDCP_RESET(n)                         (n << 0)
+#define HDCP_CTRL2             0x340
+
+/* HDCP Key Memory Access Control */
+#define HDCP_KEY_ACCESS_CTRL1  0x338
+#define HDCP_KEY_ACCESS_CTRL2  0x33c
+       #define m_LOAD_FACSIMILE_HDCP_KEY       (1 << 1)
+       #define m_LOAD_HDCP_KEY                         (1 << 0)
+/* HDCP Key Memory Control */
+#define HDCP_KEY_MEM_CTRL      0x348
+       #define m_USE_KEY1              (1 << 6)
+       #define m_USE_KEY2              (1 << 5)
+       #define m_LOAD_AKSV             (1 << 4)
+       #define m_KSV_SELECTED  (1 << 3)
+       #define m_KSV_VALID             (1 << 2)
+       #define m_KEY_VALID             (1 << 1)
+       #define m_KEY_READY             (1 << 0)
+       #define v_USE_KEY1(n)   (n << 6)
+       #define v_USE_KEY2(n)   (n << 5)
+       #define v_LOAD_AKSV(n)  (n << 4)
+
+/* HDCP B device capacity */
+#define HDCP_BCAPS                             0x2f8
+       #define m_HDMI_RECEIVED                 (1 << 7) //If HDCP receiver support HDMI, this bit must be 1.
+       #define m_REPEATER                              (1 << 6)
+       #define m_KSV_FIFO_READY                (1 << 5)
+       #define m_DDC_FAST                              (1 << 4)
+       #define m_1_1_FEATURE                   (1 << 1)
+       #define m_FAST_REAUTHENTICATION (1 << 0) //For HDMI, this function is supported whether this bit is enabled or not.
+
+/* HDCP KSV Value */
+#define HDCP_KSV_BYTE0                 0x2fc
+#define HDCP_KSV_BYTE1                 0x300
+#define HDCP_KSV_BYTE2                 0x304
+#define HDCP_KSV_BYTE3                 0x308
+#define HDCP_KSV_BYTE4                 0x30c
+
+/* HDCP error status */
+#define HDCP_ERROR                             0x320
+
+/* HDCP 100 ms timer */
+#define HDCP_TIMER_100MS               0x324
+/* HDCP 5s timer */
+#define HDCP_TIMER_5S                  0x328
+
+/* HDCP Key ram address */
+#define HDCP_RAM_KEY_KSV1              0x400
+#define HDCP_RAM_KEY_KSV2              0x407
+#define HDCP_RAM_KEY_PRIVATE   0x40e
+#define HDCP_KEY_LENGTH                        0x13C
+
+
+#define HDCP_ENABLE_HW_AUTH            // Enable hardware authentication mode  
+#define HDMI_INTERANL_CLK_DIV  0x19
+
+#define HDMIRdReg(addr)                                                __raw_readl(hdmi->regbase + addr)
+#define HDMIWrReg(addr, val)                   __raw_writel((val), hdmi->regbase + addr);
+#define HDMIMskReg(temp, addr, msk, val)       \
+       temp = __raw_readl(hdmi->regbase + addr) & (0xFF - (msk)) ; \
+       __raw_writel(temp | ( (val) & (msk) ),  hdmi->regbase + addr); 
+
+
+
+/* Color Space Convertion Mode */
+enum {
+       CSC_RGB_0_255_TO_ITU601_16_235 = 0,     //RGB 0-255 input to YCbCr 16-235 output according BT601
+       CSC_RGB_0_255_TO_ITU709_16_235,         //RGB 0-255 input to YCbCr 16-235 output accroding BT709
+       CSC_ITU601_16_235_TO_RGB_16_235,        //YCbCr 16-235 input to RGB 16-235 output according BT601
+       CSC_ITU709_16_235_TO_RGB_16_235,        //YCbCr 16-235 input to RGB 16-235 output according BT709
+       CSC_ITU601_16_235_TO_RGB_0_255,         //YCbCr 16-235 input to RGB 0-255 output according BT601
+       CSC_ITU709_16_235_TO_RGB_0_255          //YCbCr 16-235 input to RGB 0-255 output according BT709
+};
+
+extern int rk30_hdmi_initial(void);
+extern int rk30_hdmi_detect_hotplug(void);
+extern int rk30_hdmi_read_edid(int block, unsigned char *buff);
+extern int rk30_hdmi_removed(void);
+extern int rk30_hdmi_config_video(struct hdmi_video_para *vpara);
+extern int rk30_hdmi_config_audio(struct hdmi_audio *audio);
+extern void rk30_hdmi_control_output(int enable);
+
+#endif
diff --git a/drivers/video/rockchip/hdmi/rk30_hdmi.c b/drivers/video/rockchip/hdmi/rk30_hdmi.c
deleted file mode 100755 (executable)
index 0aae519..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-#include <linux/module.h>\r
-#include <linux/kernel.h>\r
-#include <linux/errno.h>\r
-#include <linux/string.h>\r
-#include <linux/mm.h>\r
-#include <linux/slab.h>\r
-#include <linux/delay.h>\r
-#include <linux/device.h>\r
-#include <linux/init.h>\r
-#include <linux/dma-mapping.h>\r
-#include <linux/interrupt.h>\r
-#include <linux/platform_device.h>\r
-#include <linux/clk.h>\r
-\r
-#include <mach/board.h>\r
-#include <mach/io.h>\r
-#include <mach/gpio.h>\r
-#include <mach/iomux.h>\r
-#include "rk30_hdmi.h"\r
-#include "rk30_hdmi_hw.h"\r
-\r
-struct hdmi *hdmi = NULL;\r
-\r
-extern irqreturn_t hdmi_irq(int irq, void *priv);\r
-extern void hdmi_work(struct work_struct *work);\r
-extern struct rk_lcdc_device_driver * rk_get_lcdc_drv(char *name);\r
-extern void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent);\r
-extern void hdmi_unregister_display_sysfs(struct hdmi *hdmi);\r
-\r
-int rk30_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),\r
-                                        void (*hdcp_irq_cb)(int status),\r
-                                        int (*hdcp_power_on_cb)(void),\r
-                                        void (*hdcp_power_off_cb)(void))\r
-{\r
-       if(hdmi == NULL)\r
-               return HDMI_ERROR_FALSE;\r
-\r
-       hdmi->hdcp_cb = hdcp_cb;\r
-       hdmi->hdcp_irq_cb = hdcp_irq_cb;\r
-       hdmi->hdcp_power_on_cb = hdcp_power_on_cb;\r
-       hdmi->hdcp_power_off_cb = hdcp_power_off_cb;\r
-       \r
-       return HDMI_ERROR_SUCESS;\r
-}\r
-\r
-#ifdef CONFIG_HAS_EARLYSUSPEND\r
-static void hdmi_early_suspend(struct early_suspend *h)\r
-{\r
-       hdmi_dbg(hdmi->dev, "hdmi enter early suspend pwr %d state %d\n", hdmi->pwr_mode, hdmi->state);\r
-       flush_delayed_work(&hdmi->delay_work);  \r
-       mutex_lock(&hdmi->enable_mutex);\r
-       hdmi->suspend = 1;\r
-       if(!hdmi->enable) {\r
-               mutex_unlock(&hdmi->enable_mutex);\r
-               return;\r
-       }\r
-       disable_irq(hdmi->irq);\r
-       mutex_unlock(&hdmi->enable_mutex);\r
-       hdmi->command = HDMI_CONFIG_ENABLE;\r
-       init_completion(&hdmi->complete);\r
-       hdmi->wait = 1;\r
-       queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);\r
-       wait_for_completion_interruptible_timeout(&hdmi->complete,\r
-                                                       msecs_to_jiffies(5000));\r
-       flush_delayed_work(&hdmi->delay_work);\r
-       // When HDMI 1.1V and 2.5V power off, DDC channel will be pull down, current is produced\r
-       // from VCC_IO which is pull up outside soc. We need to switch DDC IO to GPIO.\r
-       rk30_mux_api_set(GPIO0A2_HDMII2CSDA_NAME, GPIO0A_GPIO0A2);\r
-       rk30_mux_api_set(GPIO0A1_HDMII2CSCL_NAME, GPIO0A_GPIO0A1);\r
-       return;\r
-}\r
-\r
-static void hdmi_early_resume(struct early_suspend *h)\r
-{\r
-       hdmi_dbg(hdmi->dev, "hdmi exit early resume\n");\r
-       mutex_lock(&hdmi->enable_mutex);\r
-       \r
-       rk30_mux_api_set(GPIO0A2_HDMII2CSDA_NAME, GPIO0A_HDMI_I2C_SDA);\r
-       rk30_mux_api_set(GPIO0A1_HDMII2CSCL_NAME, GPIO0A_HDMI_I2C_SCL);\r
-       \r
-       hdmi->suspend = 0;\r
-       rk30_hdmi_initial();\r
-       if(hdmi->enable) {\r
-               enable_irq(hdmi->irq);\r
-       }\r
-       mutex_unlock(&hdmi->enable_mutex);\r
-       return;\r
-}\r
-#endif\r
-\r
-static inline void hdmi_io_remap(void)\r
-{\r
-       unsigned int value;\r
-       \r
-       // Remap HDMI IO Pin\r
-       rk30_mux_api_set(GPIO0A2_HDMII2CSDA_NAME, GPIO0A_HDMI_I2C_SDA);\r
-       rk30_mux_api_set(GPIO0A1_HDMII2CSCL_NAME, GPIO0A_HDMI_I2C_SCL);\r
-       rk30_mux_api_set(GPIO0A0_HDMIHOTPLUGIN_NAME, GPIO0A_HDMI_HOT_PLUG_IN);\r
-               \r
-       // Select LCDC0 as video source and enabled.\r
-       value = (HDMI_SOURCE_DEFAULT << 14) | (1 << 30);\r
-       writel(value, GRF_SOC_CON0 + RK30_GRF_BASE);\r
-}\r
-\r
-static int __devinit rk30_hdmi_probe (struct platform_device *pdev)\r
-{\r
-       int ret;\r
-       struct resource *res;\r
-       struct resource *mem;\r
-       \r
-       hdmi = kmalloc(sizeof(struct hdmi), GFP_KERNEL);\r
-       if(!hdmi)\r
-       {\r
-       dev_err(&pdev->dev, ">>rk30 hdmi kmalloc fail!");\r
-       return -ENOMEM;\r
-       }\r
-       memset(hdmi, 0, sizeof(struct hdmi));\r
-       hdmi->dev = &pdev->dev;\r
-       platform_set_drvdata(pdev, hdmi);\r
-\r
-       if(HDMI_SOURCE_DEFAULT == HDMI_SOURCE_LCDC0)\r
-               hdmi->lcdc = rk_get_lcdc_drv("lcdc0");\r
-       else\r
-               hdmi->lcdc = rk_get_lcdc_drv("lcdc1");\r
-       if(hdmi->lcdc == NULL)\r
-       {\r
-               dev_err(hdmi->dev, "can not connect to video source lcdc\n");\r
-               ret = -ENXIO;\r
-               goto err0;\r
-       }\r
-       hdmi->xscale = 95;\r
-       hdmi->yscale = 95;\r
-       \r
-       hdmi->hclk = clk_get(NULL,"hclk_hdmi");\r
-       if(IS_ERR(hdmi->hclk))\r
-       {\r
-               dev_err(hdmi->dev, "Unable to get hdmi hclk\n");\r
-               ret = -ENXIO;\r
-               goto err0;\r
-       }\r
-       clk_enable(hdmi->hclk);\r
-       \r
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
-       if (!res) {\r
-               dev_err(hdmi->dev, "Unable to get register resource\n");\r
-               ret = -ENXIO;\r
-               goto err0;\r
-       }\r
-       hdmi->regbase_phy = res->start;\r
-       hdmi->regsize_phy = (res->end - res->start) + 1;\r
-       mem = request_mem_region(res->start, (res->end - res->start) + 1, pdev->name);\r
-       if (!mem)\r
-       {\r
-       dev_err(hdmi->dev, "failed to request mem region for hdmi\n");\r
-       ret = -ENOENT;\r
-       goto err0;\r
-       }\r
-\r
-       \r
-       hdmi->regbase = (int)ioremap(res->start, (res->end - res->start) + 1);\r
-       if (!hdmi->regbase) {\r
-               dev_err(hdmi->dev, "cannot ioremap registers\n");\r
-               ret = -ENXIO;\r
-               goto err1;\r
-       }\r
-       \r
-       ret = rk30_hdmi_initial();\r
-       if(ret != HDMI_ERROR_SUCESS)\r
-               goto err1;\r
-               \r
-       hdmi_io_remap();\r
-       hdmi_sys_init();\r
-       \r
-       hdmi->workqueue = create_singlethread_workqueue("hdmi");\r
-       INIT_DELAYED_WORK(&(hdmi->delay_work), hdmi_work);\r
-\r
-       #ifdef CONFIG_HAS_EARLYSUSPEND\r
-       hdmi->early_suspend.suspend = hdmi_early_suspend;\r
-       hdmi->early_suspend.resume = hdmi_early_resume;\r
-       hdmi->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 10;\r
-       register_early_suspend(&hdmi->early_suspend);\r
-       #endif\r
-               \r
-       hdmi_register_display_sysfs(hdmi, NULL);\r
-       #ifdef CONFIG_SWITCH\r
-       hdmi->switch_hdmi.name="hdmi";\r
-       switch_dev_register(&(hdmi->switch_hdmi));\r
-       #endif\r
-               \r
-       spin_lock_init(&hdmi->irq_lock);\r
-       mutex_init(&hdmi->enable_mutex);\r
-       \r
-       /* get the IRQ */\r
-       hdmi->irq = platform_get_irq(pdev, 0);\r
-       if(hdmi->irq <= 0) {\r
-               dev_err(hdmi->dev, "failed to get hdmi irq resource (%d).\n", hdmi->irq);\r
-               ret = -ENXIO;\r
-               goto err2;\r
-       }\r
-\r
-       /* request the IRQ */\r
-       ret = request_irq(hdmi->irq, hdmi_irq, 0, dev_name(&pdev->dev), hdmi);\r
-       if (ret)\r
-       {\r
-               dev_err(hdmi->dev, "hdmi request_irq failed (%d).\n", ret);\r
-               goto err2;\r
-       }\r
-\r
-       hdmi_dbg(hdmi->dev, "rk30 hdmi probe sucess.\n");\r
-       return 0;\r
-err2:\r
-       #ifdef CONFIG_SWITCH\r
-       switch_dev_unregister(&(hdmi->switch_hdmi));\r
-       #endif\r
-       hdmi_unregister_display_sysfs(hdmi);\r
-       #ifdef CONFIG_HAS_EARLYSUSPEND\r
-       unregister_early_suspend(&hdmi->early_suspend);\r
-       #endif\r
-       iounmap((void*)hdmi->regbase);\r
-err1:\r
-       release_mem_region(res->start,(res->end - res->start) + 1);\r
-       clk_disable(hdmi->hclk);\r
-err0:\r
-       hdmi_dbg(hdmi->dev, "rk30 hdmi probe error.\n");\r
-       kfree(hdmi);\r
-       hdmi = NULL;\r
-       return ret;\r
-}\r
-\r
-static int __devexit rk30_hdmi_remove(struct platform_device *pdev)\r
-{\r
-       if(hdmi) {\r
-               mutex_lock(&hdmi->enable_mutex);\r
-               if(!hdmi->suspend && hdmi->enable)\r
-                       disable_irq(hdmi->irq);\r
-               mutex_unlock(&hdmi->enable_mutex);\r
-               free_irq(hdmi->irq, NULL);\r
-               flush_workqueue(hdmi->workqueue);\r
-               destroy_workqueue(hdmi->workqueue);\r
-               #ifdef CONFIG_SWITCH\r
-               switch_dev_unregister(&(hdmi->switch_hdmi));\r
-               #endif\r
-               hdmi_unregister_display_sysfs(hdmi);\r
-               #ifdef CONFIG_HAS_EARLYSUSPEND\r
-               unregister_early_suspend(&hdmi->early_suspend);\r
-               #endif\r
-               iounmap((void*)hdmi->regbase);\r
-               release_mem_region(hdmi->regbase_phy, hdmi->regsize_phy);\r
-               clk_disable(hdmi->hclk);\r
-               fb_destroy_modelist(&hdmi->edid.modelist);\r
-               if(hdmi->edid.audio)\r
-                       kfree(hdmi->edid.audio);\r
-               if(hdmi->edid.specs)\r
-               {\r
-                       if(hdmi->edid.specs->modedb)\r
-                               kfree(hdmi->edid.specs->modedb);\r
-                       kfree(hdmi->edid.specs);\r
-               }\r
-               kfree(hdmi);\r
-               hdmi = NULL;\r
-       }\r
-       printk(KERN_INFO "rk30 hdmi removed.\n");\r
-       return 0;\r
-}\r
-\r
-static void rk30_hdmi_shutdown(struct platform_device *pdev)\r
-{\r
-       if(hdmi) {\r
-               #ifdef CONFIG_HAS_EARLYSUSPEND\r
-               unregister_early_suspend(&hdmi->early_suspend);\r
-               #endif\r
-       }\r
-       printk(KERN_INFO "rk30 hdmi shut down.\n");\r
-}\r
-\r
-static struct platform_driver rk30_hdmi_driver = {\r
-       .probe          = rk30_hdmi_probe,\r
-       .remove         = __devexit_p(rk30_hdmi_remove),\r
-       .driver         = {\r
-               .name   = "rk30-hdmi",\r
-               .owner  = THIS_MODULE,\r
-       },\r
-       .shutdown   = rk30_hdmi_shutdown,\r
-};\r
-\r
-static int __init rk30_hdmi_init(void)\r
-{\r
-    return platform_driver_register(&rk30_hdmi_driver);\r
-}\r
-\r
-static void __exit rk30_hdmi_exit(void)\r
-{\r
-    platform_driver_unregister(&rk30_hdmi_driver);\r
-}\r
-\r
-\r
-//fs_initcall(rk30_hdmi_init);\r
-module_init(rk30_hdmi_init);\r
-module_exit(rk30_hdmi_exit);\r
diff --git a/drivers/video/rockchip/hdmi/rk30_hdmi.h b/drivers/video/rockchip/hdmi/rk30_hdmi.h
deleted file mode 100755 (executable)
index 54f5a5c..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-#ifndef __RK30_HDMI_H__
-#define __RK30_HDMI_H__
-
-#include <linux/kernel.h>
-#include <linux/fb.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
-#include <linux/workqueue.h>
-#include <linux/display-sys.h>
-#ifdef CONFIG_SWITCH
-#include <linux/switch.h>
-#endif
-#ifdef CONFIG_HAS_EARLYSUSPEND
-#include <linux/earlysuspend.h>
-#endif
-#include <asm/atomic.h>
-#include<linux/rk_screen.h>
-#include <linux/rk_fb.h>
-#include "rk_hdmi.h"
-
-// HDMI video source
-enum {
-       HDMI_SOURCE_LCDC0 = 0,
-       HDMI_SOURCE_LCDC1 = 1
-};
-
-/* default HDMI video source */
-#define HDMI_SOURCE_DEFAULT            HDMI_SOURCE_LCDC1
-
-/* If HDMI_ENABLE, system will auto configure output mode according to EDID 
- * If HDMI_DISABLE, system will output mode according to macro HDMI_VIDEO_DEFAULT_MODE
- */
-#define HDMI_AUTO_CONFIGURE                    HDMI_ENABLE
-
-/* default HDMI output video mode */
-#define HDMI_VIDEO_DEFAULT_MODE                        HDMI_1280x720p_60Hz//HDMI_1920x1080p_60Hz
-/* default HDMI output audio mode */
-#define HDMI_AUDIO_DEFAULT_CHANNEL             2
-#define HDMI_AUDIO_DEFAULT_RATE                        HDMI_AUDIO_FS_44100
-#define HDMI_AUDIO_DEFAULT_WORD_LENGTH HDMI_AUDIO_WORD_LENGTH_16bit
-
-struct hdmi {
-       struct device   *dev;
-       struct clk              *hclk;                          //HDMI AHP clk
-       int                     regbase;
-       int                             irq;
-       int                             regbase_phy;
-       int                             regsize_phy;
-       struct rk_lcdc_device_driver *lcdc;
-       
-       #ifdef CONFIG_SWITCH
-       struct switch_dev       switch_hdmi;
-       #endif
-       
-       struct workqueue_struct *workqueue;
-       struct delayed_work delay_work;
-       
-       spinlock_t      irq_lock;
-       struct mutex enable_mutex;
-       
-       int wait;
-       struct completion       complete;
-       
-       int suspend;
-#ifdef CONFIG_HAS_EARLYSUSPEND
-       struct early_suspend    early_suspend;
-#endif
-       
-       struct hdmi_edid edid;
-       int enable;                                     // Enable HDMI output or not
-       int vic;                                        // HDMI output video mode code
-       struct hdmi_audio audio;        // HDMI output audio type.
-       
-       int pwr_mode;                           // power mode
-       int hotplug;                            // hot plug status
-       int state;                                      // hdmi state machine status
-       int autoconfig;                         // if true, auto config hdmi output mode according to EDID.
-       int command;                            // HDMI configuration command
-       int display;                            // HDMI display status
-       int xscale;                                     // x direction scale value
-       int yscale;                                     // y directoon scale value
-       int tmdsclk;                            // TDMS Clock frequency
-       // call back for hdcp operatoion
-       void (*hdcp_cb)(void);
-       void (*hdcp_irq_cb)(int);
-       int (*hdcp_power_on_cb)(void);
-       void (*hdcp_power_off_cb)(void);
-};
-
-extern struct hdmi *hdmi;
-
-extern int hdmi_sys_init(void);
-extern int hdmi_sys_parse_edid(struct hdmi* hdmi);
-extern const char *hdmi_get_video_mode_name(unsigned char vic);
-extern int hdmi_videomode_to_vic(struct fb_videomode *vmode);
-extern const struct fb_videomode* hdmi_vic_to_videomode(int vic);
-extern int hdmi_add_videomode(const struct fb_videomode *mode, struct list_head *head);
-extern struct hdmi_video_timing * hdmi_find_mode(int vic);
-extern int hdmi_find_best_mode(struct hdmi* hdmi, int vic);
-extern int hdmi_ouputmode_select(struct hdmi *hdmi, int edid_ok);
-extern int hdmi_switch_fb(struct hdmi *hdmi, int vic);
-extern void hdmi_sys_remove(void);
-extern int rk30_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
-                                        void (*hdcp_irq_cb)(int status),
-                                        int  (*hdcp_power_on_cb)(void),
-                                        void (*hdcp_power_off_cb)(void));
-#endif /* __RK30_HDMI_H__ */
diff --git a/drivers/video/rockchip/hdmi/rk30_hdmi_edid.c b/drivers/video/rockchip/hdmi/rk30_hdmi_edid.c
deleted file mode 100755 (executable)
index 9fec195..0000000
+++ /dev/null
@@ -1,410 +0,0 @@
-#include "rk30_hdmi.h"\r
-#include "rk30_hdmi_hw.h"\r
-#include "../../edid.h"\r
-\r
-#define hdmi_edid_error(fmt, ...) \\r
-        printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)\r
-\r
-#if 0\r
-#define hdmi_edid_debug(fmt, ...) \\r
-        printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)\r
-#else\r
-#define hdmi_edid_debug(fmt, ...)      \r
-#endif\r
-\r
-typedef enum HDMI_EDID_ERRORCODE\r
-{\r
-       E_HDMI_EDID_SUCCESS = 0,\r
-       E_HDMI_EDID_PARAM,\r
-       E_HDMI_EDID_HEAD,\r
-       E_HDMI_EDID_CHECKSUM,\r
-       E_HDMI_EDID_VERSION,\r
-       E_HDMI_EDID_UNKOWNDATA,\r
-       E_HDMI_EDID_NOMEMORY\r
-}HDMI_EDID_ErrorCode;\r
-\r
-static const unsigned int double_aspect_vic[] = {3, 7, 9, 11, 13, 15, 18, 22, 24, 26, 28, 30, 36, 38, 43, 45, 49, 51, 53, 55, 57, 59};\r
-static int hdmi_edid_checksum(unsigned char *buf)\r
-{\r
-       int i;\r
-       int checksum = 0;\r
-       \r
-       for(i = 0; i < HDMI_EDID_BLOCK_SIZE; i++)\r
-               checksum += buf[i];     \r
-       \r
-       checksum &= 0xff;\r
-       \r
-       if(checksum == 0)\r
-               return E_HDMI_EDID_SUCCESS;\r
-       else\r
-               return E_HDMI_EDID_CHECKSUM;\r
-}\r
-\r
-/*\r
-       @Des    Parse Detail Timing Descriptor.\r
-       @Param  buf     :       pointer to DTD data.\r
-       @Param  pvic:   VIC of DTD descripted.\r
- */\r
-static int hdmi_edid_parse_dtd(unsigned char *block, struct fb_videomode *mode)\r
-{\r
-       mode->xres = H_ACTIVE;\r
-       mode->yres = V_ACTIVE;\r
-       mode->pixclock = PIXEL_CLOCK;\r
-//     mode->pixclock /= 1000;\r
-//     mode->pixclock = KHZ2PICOS(mode->pixclock);\r
-       mode->right_margin = H_SYNC_OFFSET;\r
-       mode->left_margin = (H_ACTIVE + H_BLANKING) -\r
-               (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);\r
-       mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -\r
-               V_SYNC_WIDTH;\r
-       mode->lower_margin = V_SYNC_OFFSET;\r
-       mode->hsync_len = H_SYNC_WIDTH;\r
-       mode->vsync_len = V_SYNC_WIDTH;\r
-       if (HSYNC_POSITIVE)\r
-               mode->sync |= FB_SYNC_HOR_HIGH_ACT;\r
-       if (VSYNC_POSITIVE)\r
-               mode->sync |= FB_SYNC_VERT_HIGH_ACT;\r
-       mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *\r
-                                    (V_ACTIVE + V_BLANKING));\r
-       if (INTERLACED) {\r
-               mode->yres *= 2;\r
-               mode->upper_margin *= 2;\r
-               mode->lower_margin *= 2;\r
-               mode->vsync_len *= 2;\r
-               mode->vmode |= FB_VMODE_INTERLACED;\r
-       }\r
-       mode->flag = FB_MODE_IS_DETAILED;\r
-\r
-       hdmi_edid_debug("<<<<<<<<Detailed Time>>>>>>>>>\n");\r
-       hdmi_edid_debug("%d KHz Refresh %d Hz",  PIXEL_CLOCK/1000, mode->refresh);\r
-       hdmi_edid_debug("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,\r
-              H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);\r
-       hdmi_edid_debug("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,\r
-              V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);\r
-       hdmi_edid_debug("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",\r
-              (VSYNC_POSITIVE) ? "+" : "-");\r
-       return E_HDMI_EDID_SUCCESS;\r
-}\r
-\r
-static int hdmi_edid_parse_base(unsigned char *buf, int *extend_num, struct hdmi_edid *pedid)\r
-{\r
-       int rc, i;\r
-       \r
-       if(buf == NULL || extend_num == NULL)\r
-               return E_HDMI_EDID_PARAM;\r
-               \r
-       #ifdef DEBUG    \r
-       for(i = 0; i < HDMI_EDID_BLOCK_SIZE; i++)\r
-       {\r
-               hdmi_edid_debug("%02x ", buf[i]&0xff);\r
-               if((i+1) % 16 == 0)\r
-                       hdmi_edid_debug("\n");\r
-       }\r
-       #endif\r
-       \r
-       // Check first 8 byte to ensure it is an edid base block.\r
-       if( buf[0] != 0x00 ||\r
-           buf[1] != 0xFF ||\r
-           buf[2] != 0xFF ||\r
-           buf[3] != 0xFF ||\r
-           buf[4] != 0xFF ||\r
-           buf[5] != 0xFF ||\r
-           buf[6] != 0xFF ||\r
-           buf[7] != 0x00)\r
-    {\r
-        hdmi_edid_error("[EDID] check header error\n");\r
-        return E_HDMI_EDID_HEAD;\r
-    }\r
-    \r
-    *extend_num = buf[0x7e];\r
-    #ifdef DEBUG\r
-    hdmi_edid_debug("[EDID] extend block num is %d\n", buf[0x7e]);\r
-    #endif\r
-    \r
-    // Checksum\r
-    rc = hdmi_edid_checksum(buf);\r
-    if( rc != E_HDMI_EDID_SUCCESS)\r
-    {\r
-       hdmi_edid_error("[EDID] base block checksum error\n");\r
-       return E_HDMI_EDID_CHECKSUM;\r
-    }\r
-\r
-       pedid->specs = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);\r
-       if(pedid->specs == NULL)\r
-               return E_HDMI_EDID_NOMEMORY;\r
-               \r
-       fb_edid_to_monspecs(buf, pedid->specs);\r
-       \r
-    return E_HDMI_EDID_SUCCESS;\r
-}\r
-\r
-// Parse CEA Short Video Descriptor\r
-static int hdmi_edid_get_cea_svd(unsigned char *buf, struct hdmi_edid *pedid)\r
-{\r
-       const struct fb_videomode *mode;\r
-       int count, i, j, vic;\r
-\r
-       count = buf[0] & 0x1F;\r
-       for(i = 0; i < count; i++)\r
-       {\r
-               hdmi_edid_debug("[EDID-CEA] %02x VID %d native %d\n", buf[1 + i], buf[1 + i] & 0x7f, buf[1 + i] >> 7);\r
-               vic = buf[1 + i] & 0x7f;\r
-               for(j = 0; j < ARRAY_SIZE(double_aspect_vic); j++)\r
-               {\r
-                       if(vic == double_aspect_vic[j])\r
-                       {       \r
-                               vic--;\r
-                               break;\r
-                       }\r
-               }\r
-               if(vic)\r
-               {\r
-                       mode = hdmi_vic_to_videomode(vic);\r
-                       if(mode)\r
-                       {       \r
-                               hdmi_add_videomode(mode, &pedid->modelist);\r
-                       }\r
-               }\r
-       }\r
-       return 0;\r
-}\r
-\r
-// Parse CEA Short Audio Descriptor\r
-static int hdmi_edid_parse_cea_sad(unsigned char *buf, struct hdmi_edid *pedid)\r
-{\r
-       int i, count;\r
-       \r
-       count = buf[0] & 0x1F;\r
-       pedid->audio = kmalloc((count/3)*sizeof(struct hdmi_audio), GFP_KERNEL);\r
-       if(pedid->audio == NULL)\r
-               return E_HDMI_EDID_NOMEMORY;\r
-       pedid->audio_num = count/3;\r
-       for(i = 0; i < pedid->audio_num; i++)\r
-       {\r
-               pedid->audio[i].type = (buf[1 + i*3] >> 3) & 0x0F;\r
-               pedid->audio[i].channel = (buf[1 + i*3] & 0x07) + 1;\r
-               pedid->audio[i].rate = buf[1 + i*3 + 1];\r
-               if(pedid->audio[i].type == HDMI_AUDIO_LPCM)//LPCM \r
-               {\r
-                       pedid->audio[i].word_length = buf[1 + i*3 + 2];\r
-               }\r
-//             printk("[EDID-CEA] type %d channel %d rate %d word length %d\n", \r
-//                     pedid->audio[i].type, pedid->audio[i].channel, pedid->audio[i].rate, pedid->audio[i].word_length);\r
-       }\r
-       return E_HDMI_EDID_SUCCESS;\r
-}\r
-// Parse CEA 861 Serial Extension.\r
-static int hdmi_edid_parse_extensions_cea(unsigned char *buf, struct hdmi_edid *pedid)\r
-{\r
-       unsigned int ddc_offset, native_dtd_num, cur_offset = 4;\r
-       unsigned int underscan_support, baseaudio_support;\r
-       unsigned int tag, IEEEOUI = 0;\r
-//     unsigned int supports_ai,  dc_48bit, dc_36bit, dc_30bit, dc_y444;\r
-//     unsigned char vic;\r
-       \r
-       if(buf == NULL)\r
-               return E_HDMI_EDID_PARAM;\r
-               \r
-       // Check ces extension version\r
-       if(buf[1] != 3)\r
-       {\r
-               hdmi_edid_error("[EDID-CEA] error version.\n");\r
-               return E_HDMI_EDID_VERSION;\r
-       }\r
-       \r
-       ddc_offset = buf[2];\r
-       underscan_support = (buf[3] >> 7) & 0x01;\r
-       baseaudio_support = (buf[3] >> 6) & 0x01;\r
-       pedid->ycbcr444 = (buf[3] >> 5) & 0x01;\r
-       pedid->ycbcr422 = (buf[3] >> 4) & 0x01;\r
-       native_dtd_num = buf[3] & 0x0F;\r
-//     hdmi_edid_debug("[EDID-CEA] ddc_offset %d underscan_support %d baseaudio_support %d yuv_support %d native_dtd_num %d\n", ddc_offset, underscan_support, baseaudio_support, yuv_support, native_dtd_num);\r
-       // Parse data block\r
-       while(cur_offset < ddc_offset)\r
-       {\r
-               tag = buf[cur_offset] >> 5;\r
-               switch(tag)\r
-               {\r
-                       case 0x02:      // Video Data Block\r
-                               hdmi_edid_debug("[EDID-CEA] It is a Video Data Block.\n");\r
-                               hdmi_edid_get_cea_svd(buf + cur_offset, pedid);\r
-                               break;\r
-                       case 0x01:      // Audio Data Block\r
-                               hdmi_edid_debug("[EDID-CEA] It is a Audio Data Block.\n");\r
-                               hdmi_edid_parse_cea_sad(buf + cur_offset, pedid);\r
-                               break;\r
-                       case 0x04:      // Speaker Allocation Data Block\r
-                               hdmi_edid_debug("[EDID-CEA] It is a Speaker Allocatio Data Block.\n");\r
-                               break;\r
-                       case 0x03:      // Vendor Specific Data Block\r
-                               hdmi_edid_debug("[EDID-CEA] It is a Vendor Specific Data Block.\n");\r
-\r
-                               IEEEOUI = buf[cur_offset + 2 + 1];\r
-                               IEEEOUI <<= 8;\r
-                               IEEEOUI += buf[cur_offset + 1 + 1];\r
-                               IEEEOUI <<= 8;\r
-                               IEEEOUI += buf[cur_offset + 1];\r
-                               hdmi_edid_debug("[EDID-CEA] IEEEOUI is 0x%08x.\n", IEEEOUI);\r
-                               if(IEEEOUI == 0x0c03)\r
-                                       pedid->sink_hdmi = 1;\r
-//                             if(count > 5)\r
-//                             {\r
-//                                     pedid->deepcolor = (buf[cur_offset + 5] >> 3) & 0x0F;\r
-//                                     supports_ai = buf[cur_offset + 5] >> 7;\r
-//                                     dc_48bit = (buf[cur_offset + 5] >> 6) & 0x1;\r
-//                                     dc_36bit = (buf[cur_offset + 5] >> 5) & 0x1;\r
-//                                     dc_30bit = (buf[cur_offset + 5] >> 4) & 0x1;\r
-//                                     dc_y444 = (buf[cur_offset + 5] >> 3) & 0x1;\r
-//                                     hdmi_edid_debug("[EDID-CEA] supports_ai %d dc_48bit %d dc_36bit %d dc_30bit %d dc_y444 %d \n", supports_ai, dc_48bit, dc_36bit, dc_30bit, dc_y444);\r
-//                             }\r
-//                             if(count > 6)\r
-//                                     pedid->maxtmdsclock = buf[cur_offset + 6] * 5000000;\r
-//                             if(count > 7)\r
-//                             {\r
-//                                     pedid->latency_fields_present = (buf[cur_offset + 7] & 0x80) ? 1:0;\r
-//                                     pedid->i_latency_fields_present = (buf[cur_offset + 7] & 0x40) ? 1:0;\r
-//                             }\r
-//                             if(count > 9 && pedid->latency_fields_present)\r
-//                             {\r
-//                                     pedid->video_latency = buf[cur_offset + 8];\r
-//                                     pedid->audio_latency = buf[cur_offset + 9];\r
-//                             }\r
-//                             if(count > 11 && pedid->i_latency_fields_present)\r
-//                             {\r
-//                                     pedid->interlaced_video_latency = buf[cur_offset + 10];\r
-//                                     pedid->interlaced_audio_latency = buf[cur_offset + 11];\r
-//                             }\r
-                               break;          \r
-                       case 0x05:      // VESA DTC Data Block\r
-                               hdmi_edid_debug("[EDID-CEA] It is a VESA DTC Data Block.\n");\r
-                               break;\r
-                       case 0x07:      // Use Extended Tag\r
-                               hdmi_edid_debug("[EDID-CEA] It is a Use Extended Tag Data Block.\n");\r
-                               break;\r
-                       default:\r
-                               hdmi_edid_error("[EDID-CEA] unkowned data block tag.\n");\r
-                               break;\r
-               }\r
-               cur_offset += (buf[cur_offset] & 0x1F) + 1;\r
-       }\r
-#if 1  \r
-{\r
-       // Parse DTD\r
-       struct fb_videomode *vmode = kmalloc(sizeof(struct fb_videomode), GFP_KERNEL);\r
-       if(vmode == NULL)\r
-               return E_HDMI_EDID_SUCCESS; \r
-       while(ddc_offset < HDMI_EDID_BLOCK_SIZE - 2)    //buf[126] = 0 and buf[127] = checksum\r
-       {\r
-               if(!buf[ddc_offset] && !buf[ddc_offset + 1])\r
-                       break;\r
-               memset(vmode, 0, sizeof(struct fb_videomode));\r
-               hdmi_edid_parse_dtd(buf + ddc_offset, vmode);\r
-               hdmi_add_videomode(vmode, &pedid->modelist);\r
-               ddc_offset += 18;\r
-       }\r
-       kfree(vmode);\r
-}\r
-#endif\r
-       return E_HDMI_EDID_SUCCESS;\r
-}\r
-\r
-static int hdmi_edid_parse_extensions(unsigned char *buf, struct hdmi_edid *pedid)\r
-{\r
-       int rc;\r
-       \r
-       if(buf == NULL || pedid == NULL)\r
-               return E_HDMI_EDID_PARAM;\r
-               \r
-       // Checksum\r
-    rc = hdmi_edid_checksum(buf);\r
-    if( rc != E_HDMI_EDID_SUCCESS)\r
-    {\r
-       hdmi_edid_error("[EDID] extensions block checksum error\n");\r
-       return E_HDMI_EDID_CHECKSUM;\r
-    }\r
-    \r
-    switch(buf[0])\r
-    {\r
-       case 0xF0:\r
-               hdmi_edid_debug("[EDID-EXTEND] It is a extensions block map.\n");\r
-               break;\r
-       case 0x02:\r
-               hdmi_edid_debug("[EDID-EXTEND] It is a  CEA 861 Series Extension.\n");\r
-               hdmi_edid_parse_extensions_cea(buf, pedid);\r
-               break;\r
-       case 0x10:\r
-               hdmi_edid_debug("[EDID-EXTEND] It is a Video Timing Block Extension.\n");\r
-               break;\r
-       case 0x40:\r
-               hdmi_edid_debug("[EDID-EXTEND] It is a Display Information Extension.\n");\r
-               break;\r
-       case 0x50:\r
-               hdmi_edid_debug("[EDID-EXTEND] It is a Localized String Extension.\n");\r
-               break;\r
-       case 0x60:\r
-               hdmi_edid_debug("[EDID-EXTEND] It is a Digital Packet Video Link Extension.\n");\r
-               break;\r
-       default:\r
-               hdmi_edid_debug("[EDID-EXTEND] Unkowned extension.\n");\r
-               break;\r
-    }\r
-    \r
-    return E_HDMI_EDID_SUCCESS;\r
-}\r
-\r
-\r
-int hdmi_sys_parse_edid(struct hdmi* hdmi)\r
-{\r
-       struct hdmi_edid *pedid;\r
-       unsigned char *buff = NULL;\r
-       int rc = HDMI_ERROR_SUCESS, extendblock = 0, i;\r
-       \r
-       if(hdmi == NULL)\r
-               return HDMI_ERROR_FALSE;\r
-\r
-       pedid = &(hdmi->edid);\r
-       memset(pedid, 0, sizeof(struct hdmi_edid));\r
-       INIT_LIST_HEAD(&pedid->modelist);\r
-       \r
-       buff = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);\r
-       if(buff == NULL)\r
-       {               \r
-               hdmi_dbg(hdmi->dev, "[%s] can not allocate memory for edid buff.\n", __FUNCTION__);\r
-               return -1;\r
-       }\r
-       // Read base block edid.\r
-       memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);\r
-       rc = rk30_hdmi_read_edid(0, buff);\r
-       if(rc)\r
-       {\r
-               dev_err(hdmi->dev, "[HDMI] read edid base block error\n");\r
-               goto out;\r
-       }\r
-       rc = hdmi_edid_parse_base(buff, &extendblock, pedid);\r
-       if(rc)\r
-       {\r
-               dev_err(hdmi->dev, "[HDMI] parse edid base block error\n");\r
-               goto out;\r
-       }\r
-       for(i = 1; i < extendblock + 1; i++)\r
-       {\r
-               memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);\r
-               rc = rk30_hdmi_read_edid(i, buff);\r
-               if(rc)\r
-               {\r
-                       printk("[HDMI] read edid block %d error\n", i); \r
-                       goto out;\r
-               }\r
-               rc = hdmi_edid_parse_extensions(buff, pedid);\r
-               if(rc)\r
-               {\r
-                       dev_err(hdmi->dev, "[HDMI] parse edid block %d error\n", i);\r
-                       continue;\r
-               }\r
-       }\r
-out:\r
-       if(buff)\r
-               kfree(buff);\r
-       rc = hdmi_ouputmode_select(hdmi, rc);\r
-       return rc;\r
-}
\ No newline at end of file
diff --git a/drivers/video/rockchip/hdmi/rk30_hdmi_hw.c b/drivers/video/rockchip/hdmi/rk30_hdmi_hw.c
deleted file mode 100755 (executable)
index 8cb76eb..0000000
+++ /dev/null
@@ -1,647 +0,0 @@
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <mach/io.h>
-#include "rk30_hdmi.h"
-#include "rk30_hdmi_hw.h"
-
-static char edid_result = 0;
-
-static inline void delay100us(void)
-{
-       msleep(1);
-}
-
-int rk30_hdmi_initial(void)
-{
-       int rc = HDMI_ERROR_SUCESS;
-       // internal hclk = hdmi_hclk/20
-       HDMIWrReg(0x800, HDMI_INTERANL_CLK_DIV);
-       
-       if(hdmi->hdcp_power_on_cb)
-               rc = hdmi->hdcp_power_on_cb();
-
-       return rc;
-}
-
-static void rk30_hdmi_set_pwr_mode(int mode)
-{
-       if(hdmi->pwr_mode == mode)
-               return;
-       hdmi_dbg(hdmi->dev, "[%s] mode %d\n", __FUNCTION__, mode);      
-       switch(mode)
-       {
-               case PWR_SAVE_MODE_A:
-                       HDMIWrReg(SYS_CTRL, 0x10);
-                       break;
-               case PWR_SAVE_MODE_B:
-                       HDMIWrReg(SYS_CTRL, 0x20);
-                       break;
-               case PWR_SAVE_MODE_D:
-                       // reset PLL A&B
-                       HDMIWrReg(SYS_CTRL, 0x4C);
-                       delay100us();
-                       // release PLL A reset
-                       HDMIWrReg(SYS_CTRL, 0x48);
-                       delay100us();
-                       // release PLL B reset
-                       HDMIWrReg(SYS_CTRL, 0x40);
-                       break;
-               case PWR_SAVE_MODE_E:
-                       HDMIWrReg(SYS_CTRL, 0x80);
-                       break;
-       }
-       hdmi->pwr_mode = mode;
-       if(mode != PWR_SAVE_MODE_A)
-               msleep(10);
-       hdmi_dbg(hdmi->dev, "[%s] curmode %02x\n", __FUNCTION__, HDMIRdReg(SYS_CTRL));
-}
-
-int rk30_hdmi_detect_hotplug(void)
-{
-       int value =     HDMIRdReg(HPD_MENS_STA);
-       
-       hdmi_dbg(hdmi->dev, "[%s] value %02x\n", __FUNCTION__, value);
-       value &= m_HOTPLUG_STATUS | m_MSEN_STATUS;
-       if(value  == (m_HOTPLUG_STATUS | m_MSEN_STATUS) )
-               return HDMI_HPD_ACTIVED;
-       else if(value)
-               return HDMI_HPD_INSERT;
-       else
-               return HDMI_HPD_REMOVED;
-}
-
-#define HDMI_EDID_DDC_CLK      90000
-int rk30_hdmi_read_edid(int block, unsigned char *buff)
-{
-       int value, ret = -1, ddc_bus_freq = 0;
-       char interrupt = 0, trytime = 2;
-       unsigned long flags;
-       
-       hdmi_dbg(hdmi->dev, "[%s] block %d\n", __FUNCTION__, block);
-       spin_lock_irqsave(&hdmi->irq_lock, flags);
-       edid_result = 0;
-       spin_unlock_irqrestore(&hdmi->irq_lock, flags);
-       //Before Phy parameter was set, DDC_CLK is equal to PLLA freq which is 30MHz.
-       //Set DDC I2C CLK which devided from DDC_CLK to 100KHz.
-       ddc_bus_freq = (30000000/HDMI_EDID_DDC_CLK)/4;
-       HDMIWrReg(DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
-       HDMIWrReg(DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
-       
-       // Enable edid interrupt
-       HDMIWrReg(INTR_MASK1, m_INT_HOTPLUG | m_INT_MSENS | m_INT_EDID_ERR | m_INT_EDID_READY);
-       
-       while(trytime--) {
-               // Config EDID block and segment addr
-               HDMIWrReg(EDID_WORD_ADDR, (block%2) * 0x80);
-               HDMIWrReg(EDID_SEGMENT_POINTER, block/2);       
-       
-               value = 100;
-               while(value--)
-               {
-                       spin_lock_irqsave(&hdmi->irq_lock, flags);
-                       interrupt = edid_result;
-                       edid_result = 0;
-                       spin_unlock_irqrestore(&hdmi->irq_lock, flags);
-                       if(interrupt & (m_INT_EDID_ERR | m_INT_EDID_READY))
-                               break;
-                       msleep(10);
-               }
-               hdmi_dbg(hdmi->dev, "[%s] edid read value %d\n", __FUNCTION__, value);
-               if(interrupt & m_INT_EDID_READY)
-               {
-                       for(value = 0; value < HDMI_EDID_BLOCK_SIZE; value++) 
-                               buff[value] = HDMIRdReg(DDC_READ_FIFO_ADDR);
-                       ret = 0;
-                       
-                       hdmi_dbg(hdmi->dev, "[%s] edid read sucess\n", __FUNCTION__);
-#ifdef HDMI_DEBUG
-                       for(value = 0; value < 128; value++) {
-                               printk("%02x ,", buff[value]);
-                               if( (value + 1) % 16 == 0)
-                                       printk("\n");
-                       }
-#endif
-                       break;
-               }               
-               if(interrupt & m_INT_EDID_ERR)
-                       hdmi_err(hdmi->dev, "[%s] edid read error\n", __FUNCTION__);
-
-       }
-       // Disable edid interrupt
-       HDMIWrReg(INTR_MASK1, m_INT_HOTPLUG | m_INT_MSENS);
-//     msleep(100);
-       return ret;
-}
-
-static inline void rk30_hdmi_config_phy_reg(int reg, int value)
-{
-       HDMIWrReg(reg, value);
-       HDMIWrReg(SYS_CTRL, 0x2C);
-       delay100us();
-       HDMIWrReg(SYS_CTRL, 0x20);
-       msleep(1);
-}
-
-static void rk30_hdmi_config_phy(unsigned char vic)
-{
-       HDMIWrReg(DEEP_COLOR_MODE, 0x22);       // tmds frequency same as input dlck
-       rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_B);
-       switch(vic)
-       {
-               case HDMI_1920x1080p_60Hz:
-               case HDMI_1920x1080p_50Hz:
-                       rk30_hdmi_config_phy_reg(0x158, 0x0E);
-                       rk30_hdmi_config_phy_reg(0x15c, 0x00);
-                       rk30_hdmi_config_phy_reg(0x160, 0x60);
-                       rk30_hdmi_config_phy_reg(0x164, 0x00);
-                       rk30_hdmi_config_phy_reg(0x168, 0xDA);
-                       rk30_hdmi_config_phy_reg(0x16c, 0xA1);
-                       rk30_hdmi_config_phy_reg(0x170, 0x0e);
-                       rk30_hdmi_config_phy_reg(0x174, 0x22);
-                       rk30_hdmi_config_phy_reg(0x178, 0x00);
-                       break;
-                       
-               case HDMI_1920x1080i_60Hz:
-               case HDMI_1920x1080i_50Hz:
-               case HDMI_1280x720p_60Hz:
-               case HDMI_1280x720p_50Hz:
-                       rk30_hdmi_config_phy_reg(0x158, 0x06);
-                       rk30_hdmi_config_phy_reg(0x15c, 0x00);
-                       rk30_hdmi_config_phy_reg(0x160, 0x60);
-                       rk30_hdmi_config_phy_reg(0x164, 0x00);
-                       rk30_hdmi_config_phy_reg(0x168, 0xCA);
-                       rk30_hdmi_config_phy_reg(0x16c, 0xA3);
-                       rk30_hdmi_config_phy_reg(0x170, 0x0e);
-                       rk30_hdmi_config_phy_reg(0x174, 0x20);
-                       rk30_hdmi_config_phy_reg(0x178, 0x00);
-                       break;
-                       
-               case HDMI_720x576p_50Hz_4_3:
-               case HDMI_720x576p_50Hz_16_9:
-               case HDMI_720x480p_60Hz_4_3:
-               case HDMI_720x480p_60Hz_16_9:
-                       rk30_hdmi_config_phy_reg(0x158, 0x02);
-                       rk30_hdmi_config_phy_reg(0x15c, 0x00);
-                       rk30_hdmi_config_phy_reg(0x160, 0x60);
-                       rk30_hdmi_config_phy_reg(0x164, 0x00);
-                       rk30_hdmi_config_phy_reg(0x168, 0xC2);
-                       rk30_hdmi_config_phy_reg(0x16c, 0xA2);
-                       rk30_hdmi_config_phy_reg(0x170, 0x0e);
-                       rk30_hdmi_config_phy_reg(0x174, 0x20);
-                       rk30_hdmi_config_phy_reg(0x178, 0x00);
-                       break;
-               default:
-                       hdmi_err(hdmi->dev, "not support such vic %d\n", vic);
-                       break;
-       }
-}
-
-static void rk30_hdmi_config_avi(unsigned char vic, unsigned char output_color)
-{
-       int i, clolorimetry, aspect_ratio;
-       char info[SIZE_AVI_INFOFRAME];
-       
-       memset(info, 0, SIZE_AVI_INFOFRAME);
-       HDMIWrReg(CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
-       info[0] = 0x82;
-       info[1] = 0x02;
-       info[2] = 0x0D; 
-       info[3] = info[0] + info[1] + info[2];
-
-       if(output_color == VIDEO_OUTPUT_YCBCR444)       
-               info[4] = (AVI_COLOR_MODE_YCBCR444 << 5);
-       else if(output_color == VIDEO_OUTPUT_YCBCR422)
-               info[4] = (AVI_COLOR_MODE_YCBCR422 << 5);
-       else
-               info[4] = (AVI_COLOR_MODE_RGB << 5);
-       info[4] |= (1 << 4);    //Enable active format data bits is present in info[2]
-       
-       switch(vic)
-       {
-               case HDMI_720x480i_60Hz_4_3:
-               case HDMI_720x576i_50Hz_4_3:
-               case HDMI_720x480p_60Hz_4_3:
-               case HDMI_720x576p_50Hz_4_3:                            
-                       aspect_ratio = AVI_CODED_FRAME_ASPECT_4_3;
-                       clolorimetry = AVI_COLORIMETRY_SMPTE_170M;
-                       break;
-               case HDMI_720x480i_60Hz_16_9:
-               case HDMI_720x576i_50Hz_16_9:
-               case HDMI_720x480p_60Hz_16_9:
-               case HDMI_720x576p_50Hz_16_9:
-                       aspect_ratio = AVI_CODED_FRAME_ASPECT_16_9;
-                       clolorimetry = AVI_COLORIMETRY_SMPTE_170M;
-                       break;
-               default:
-                       aspect_ratio = AVI_CODED_FRAME_ASPECT_16_9;
-                       clolorimetry = AVI_COLORIMETRY_ITU709;
-       }
-
-       if(output_color == VIDEO_OUTPUT_RGB444)
-               clolorimetry = AVI_COLORIMETRY_NO_DATA;
-       
-       info[5] = (clolorimetry << 6) | (aspect_ratio << 4) | ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME;
-       info[6] = 0;
-       info[7] = vic;
-       info[8] = 0;
-
-       // Calculate AVI InfoFrame ChecKsum
-       for (i = 4; i < SIZE_AVI_INFOFRAME; i++)
-       {
-       info[3] += info[i];
-       }
-       info[3] = 0x100 - info[3];
-       
-       for(i = 0; i < SIZE_AVI_INFOFRAME; i++)
-               HDMIWrReg(CONTROL_PACKET_HB0 + i*4, info[i]);
-}
-static char coeff_csc[][24] = {
-               //G                     B                       R                       Bias
-       {       //CSC_RGB_0_255_TO_ITU601_16_235
-               0x11, 0xb6, 0x02, 0x0b, 0x10, 0x55, 0x00, 0x80,         //Cr
-               0x02, 0x59, 0x01, 0x32, 0x00, 0x75, 0x00, 0x10,         //Y
-               0x11, 0x5b, 0x10, 0xb0, 0x02, 0x0b, 0x00, 0x80,         //Cb
-       },
-       {       //CSC_RGB_0_255_TO_ITU709_16_235
-               0x11, 0xdb, 0x02, 0x0b, 0x10, 0x30, 0x00, 0x80,         //Cr
-               0x02, 0xdc, 0x00, 0xda, 0x00, 0x4a, 0x00, 0x10,         //Y
-               0x11, 0x93, 0x10, 0x78, 0x02, 0x0b, 0x00, 0x80,         //Cb
-       },
-               //Y                     Cr                      Cb                      Bias
-       {       //CSC_ITU601_16_235_TO_RGB_16_235
-               0x04, 0x00, 0x05, 0x7c, 0x00, 0x00, 0x02, 0xaf,         //R
-               0x04, 0x00, 0x12, 0xcb, 0x11, 0x58, 0x00, 0x84,         //G
-               0x04, 0x00, 0x00, 0x00, 0x06, 0xee, 0x02, 0xde,         //B
-       },
-       {       //CSC_ITU709_16_235_TO_RGB_16_235
-               0x04, 0x00, 0x06, 0x29, 0x00, 0x00, 0x02, 0xc5,         //R
-               0x04, 0x00, 0x11, 0xd6, 0x10, 0xbb, 0x00, 0x52,         //G
-               0x04, 0x00, 0x00, 0x00, 0x07, 0x44, 0x02, 0xe8,         //B
-       },
-       {       //CSC_ITU601_16_235_TO_RGB_0_255
-               0x04, 0xa8, 0x05, 0x7c, 0x00, 0x00, 0x02, 0xc2,         //R
-               0x04, 0xa8, 0x12, 0xcb, 0x11, 0x58, 0x00, 0x72,         //G
-               0x04, 0xa8, 0x00, 0x00, 0x06, 0xee, 0x02, 0xf0,         //B
-       },
-       {       //CSC_ITU709_16_235_TO_RGB_0_255
-               0x04, 0xa8, 0x06, 0x29, 0x00, 0x00, 0x02, 0xd8,         //R
-               0x04, 0xa8, 0x11, 0xd6, 0x10, 0xbb, 0x00, 0x40,         //G
-               0x04, 0xa8, 0x00, 0x00, 0x07, 0x44, 0x02, 0xfb,         //B
-       },
-       
-};
-
-static void rk30_hdmi_config_csc(struct rk30_hdmi_video_para *vpara)
-{
-       int i, mode;
-       char *coeff = NULL;
-               
-       if( ((vpara->input_color == VIDEO_INPUT_COLOR_RGB) && (vpara->output_color == VIDEO_OUTPUT_RGB444)) ||
-               ((vpara->input_color == VIDEO_INPUT_COLOR_YCBCR) && (vpara->output_color != VIDEO_OUTPUT_RGB444) ))
-       {
-               return;
-       }
-       switch(vpara->vic)
-       {
-               case HDMI_720x480i_60Hz_4_3:
-               case HDMI_720x576i_50Hz_4_3:
-               case HDMI_720x480p_60Hz_4_3:
-               case HDMI_720x576p_50Hz_4_3:
-               case HDMI_720x480i_60Hz_16_9:
-               case HDMI_720x576i_50Hz_16_9:
-               case HDMI_720x480p_60Hz_16_9:
-               case HDMI_720x576p_50Hz_16_9:
-                       if(vpara->input_color == VIDEO_INPUT_COLOR_RGB)
-                               mode = CSC_RGB_0_255_TO_ITU601_16_235;
-                       else if(vpara->output_mode == OUTPUT_HDMI)
-                               mode = CSC_ITU601_16_235_TO_RGB_16_235;
-                       else
-                               mode = CSC_ITU601_16_235_TO_RGB_0_255;
-                       break;
-               default:
-                       if(vpara->input_color == VIDEO_INPUT_COLOR_RGB)
-                               mode = CSC_RGB_0_255_TO_ITU709_16_235;
-                       else if(vpara->output_mode == OUTPUT_HDMI)
-                               mode = CSC_ITU709_16_235_TO_RGB_16_235;
-                       else
-                               mode = CSC_ITU709_16_235_TO_RGB_0_255;
-                       break;
-       }
-       
-       coeff = coeff_csc[mode];
-       
-       HDMIWrReg(CSC_CONFIG1, v_CSC_MODE(CSC_MODE_MANUAL) | v_CSC_BRSWAP_DIABLE(1));
-       
-       for(i = 0; i < 24; i++)
-               HDMIWrReg(CSC_PARA_C0_H + i*4, coeff[i]);
-               
-       HDMIWrReg(AV_CTRL2, v_CSC_ENABLE(1));
-}
-
-int rk30_hdmi_config_video(struct rk30_hdmi_video_para *vpara)
-{
-       int value;
-       struct fb_videomode *mode;
-       
-       hdmi_dbg(hdmi->dev, "[%s]\n", __FUNCTION__);
-       if(vpara == NULL) {
-               hdmi_err(hdmi->dev, "[%s] input parameter error\n", __FUNCTION__);
-               return -1;
-       }
-       if(hdmi->pwr_mode == PWR_SAVE_MODE_E)
-               rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_D);
-       if(hdmi->pwr_mode == PWR_SAVE_MODE_D || hdmi->pwr_mode == PWR_SAVE_MODE_A)
-               rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_B);
-       
-       if(hdmi->hdcp_power_off_cb)
-               hdmi->hdcp_power_off_cb();
-               
-       // Input video mode is RGB24bit, Data enable signal from external
-       HDMIMskReg(value, AV_CTRL1, m_INPUT_VIDEO_MODE | m_DE_SIGNAL_SELECT, \
-               v_INPUT_VIDEO_MODE(vpara->input_mode) | EXTERNAL_DE)    
-       HDMIMskReg(value, VIDEO_CTRL1, m_VIDEO_OUTPUT_MODE | m_VIDEO_INPUT_DEPTH | m_VIDEO_INPUT_COLOR_MODE, \
-               v_VIDEO_OUTPUT_MODE(vpara->output_color) | v_VIDEO_INPUT_DEPTH(VIDEO_INPUT_DEPTH_8BIT) | vpara->input_color)
-       HDMIWrReg(DEEP_COLOR_MODE, 0x20);
-       // color space convert
-       rk30_hdmi_config_csc(vpara);
-       // Set HDMI Mode
-       HDMIWrReg(HDCP_CTRL, v_HDMI_DVI(vpara->output_mode));
-
-       // Set ext video
-       mode = (struct fb_videomode *)hdmi_vic_to_videomode(vpara->vic);
-       if(mode == NULL)
-       {
-               hdmi_err(hdmi->dev, "[%s] not found vic %d\n", __FUNCTION__, vpara->vic);
-               return -ENOENT;
-       }
-       hdmi->tmdsclk = mode->pixclock;
-
-       if( (vpara->vic == HDMI_720x480p_60Hz_4_3) || (vpara->vic == HDMI_720x480p_60Hz_16_9) )
-               value = v_VSYNC_OFFSET(6);
-       else
-               value = v_VSYNC_OFFSET(0);
-       value |= v_EXT_VIDEO_ENABLE(1) | v_INTERLACE(mode->vmode);
-       if(mode->sync & FB_SYNC_HOR_HIGH_ACT)
-               value |= v_HSYNC_POLARITY(1);
-       if(mode->sync & FB_SYNC_VERT_HIGH_ACT)
-               value |= v_VSYNC_POLARITY(1);
-       HDMIWrReg(EXT_VIDEO_PARA, value);
-       value = mode->left_margin + mode->xres + mode->right_margin + mode->hsync_len;
-       HDMIWrReg(EXT_VIDEO_PARA_HTOTAL_L, value & 0xFF);
-       HDMIWrReg(EXT_VIDEO_PARA_HTOTAL_H, (value >> 8) & 0xFF);
-       
-       value = mode->left_margin + mode->right_margin + mode->hsync_len;
-       HDMIWrReg(EXT_VIDEO_PARA_HBLANK_L, value & 0xFF);
-       HDMIWrReg(EXT_VIDEO_PARA_HBLANK_H, (value >> 8) & 0xFF);
-       
-       value = mode->left_margin + mode->hsync_len;
-       HDMIWrReg(EXT_VIDEO_PARA_HDELAY_L, value & 0xFF);
-       HDMIWrReg(EXT_VIDEO_PARA_HDELAY_H, (value >> 8) & 0xFF);
-       
-       value = mode->hsync_len;
-       HDMIWrReg(EXT_VIDEO_PARA_HSYNCWIDTH_L, value & 0xFF);
-       HDMIWrReg(EXT_VIDEO_PARA_HSYNCWIDTH_H, (value >> 8) & 0xFF);
-       
-       value = mode->upper_margin + mode->yres + mode->lower_margin + mode->vsync_len;
-       HDMIWrReg(EXT_VIDEO_PARA_VTOTAL_L, value & 0xFF);
-       HDMIWrReg(EXT_VIDEO_PARA_VTOTAL_H, (value >> 8) & 0xFF);
-       
-       value = mode->upper_margin + mode->vsync_len + mode->lower_margin;
-       HDMIWrReg(EXT_VIDEO_PARA_VBLANK_L, value & 0xFF);
-       
-       if(vpara->vic == HDMI_720x480p_60Hz_4_3 || vpara->vic == HDMI_720x480p_60Hz_16_9)
-               value = 42;
-       else
-               value = mode->upper_margin + mode->vsync_len;
-
-       HDMIWrReg(EXT_VIDEO_PARA_VDELAY, value & 0xFF);
-       
-       value = mode->vsync_len;
-       HDMIWrReg(EXT_VIDEO_PARA_VSYNCWIDTH, value & 0xFF);
-       
-       if(vpara->output_mode == OUTPUT_HDMI) {
-               rk30_hdmi_config_avi(vpara->vic, vpara->output_color);
-               hdmi_dbg(hdmi->dev, "[%s] sucess output HDMI.\n", __FUNCTION__);
-       }
-       else {
-               hdmi_dbg(hdmi->dev, "[%s] sucess output DVI.\n", __FUNCTION__); 
-       }
-       
-       rk30_hdmi_config_phy(vpara->vic);
-       rk30_hdmi_control_output(0);
-       return 0;
-}
-
-static void rk30_hdmi_config_aai(void)
-{
-       int i;
-       char info[SIZE_AUDIO_INFOFRAME];
-       
-       memset(info, 0, SIZE_AUDIO_INFOFRAME);
-       
-       info[0] = 0x84;
-       info[1] = 0x01;
-       info[2] = 0x0A;
-       
-       info[3] = info[0] + info[1] + info[2];  
-       for (i = 4; i < SIZE_AUDIO_INFOFRAME; i++)
-       info[3] += info[i];
-       
-       info[3] = 0x100 - info[3];
-       
-       HDMIWrReg(CONTROL_PACKET_BUF_INDEX, INFOFRAME_AAI);
-       for(i = 0; i < SIZE_AUDIO_INFOFRAME; i++)
-               HDMIWrReg(CONTROL_PACKET_HB0 + i*4, info[i]);
-}
-
-int rk30_hdmi_config_audio(struct hdmi_audio *audio)
-{
-       int value, rate, N;
-       char word_length, channel;
-       
-       if(audio->channel < 3)
-               channel = I2S_CHANNEL_1_2;
-       else if(audio->channel < 5)
-               channel = I2S_CHANNEL_3_4;
-       else if(audio->channel < 7)
-               channel = I2S_CHANNEL_5_6;
-       else
-               channel = I2S_CHANNEL_7_8;
-       
-       switch(audio->rate)
-       {
-               case HDMI_AUDIO_FS_32000:
-                       rate = AUDIO_32K;
-                       N = N_32K;
-                       break;
-               case HDMI_AUDIO_FS_44100:
-                       rate = AUDIO_441K;
-                       N = N_441K;
-                       break;
-               case HDMI_AUDIO_FS_48000:
-                       rate = AUDIO_48K;
-                       N = N_48K;
-                       break;
-               case HDMI_AUDIO_FS_88200:
-                       rate = AUDIO_882K;
-                       N = N_882K;
-                       break;
-               case HDMI_AUDIO_FS_96000:
-                       rate = AUDIO_96K;
-                       N = N_96K;
-                       break;
-               case HDMI_AUDIO_FS_176400:
-                       rate = AUDIO_1764K;
-                       N = N_1764K;
-                       break;
-               case HDMI_AUDIO_FS_192000:
-                       rate = AUDIO_192K;
-                       N = N_192K;
-                       break;
-               default:
-                       hdmi_err(hdmi->dev, "[%s] not support such sample rate %d\n", __FUNCTION__, audio->rate);
-                       return -ENOENT;
-       }
-//     switch(audio->word_length)
-//     {
-//             case HDMI_AUDIO_WORD_LENGTH_16bit:
-//                     word_length = 0x02;
-//                     break;
-//             case HDMI_AUDIO_WORD_LENGTH_20bit:
-//                     word_length = 0x0a;
-//                     break;
-//             case HDMI_AUDIO_WORD_LENGTH_24bit:
-//                     word_length = 0x0b;
-//                     break;
-//             default:
-//                     hdmi_err(hdmi->dev, "[%s] not support such word length %d\n", __FUNCTION__, audio->word_length);
-//                     return -ENOENT;
-//     }
-       //set_audio_if I2S
-       HDMIWrReg(AUDIO_CTRL1, 0x00); //internal CTS, disable down sample, i2s input, disable MCLK
-       HDMIWrReg(AUDIO_CTRL2, 0x40); 
-       HDMIWrReg(I2S_AUDIO_CTRL, v_I2S_MODE(I2S_MODE_STANDARD) | v_I2S_CHANNEL(channel) );     
-       HDMIWrReg(I2S_INPUT_SWAP, 0x00); //no swap
-       HDMIMskReg(value, AV_CTRL1, m_AUDIO_SAMPLE_RATE, v_AUDIO_SAMPLE_RATE(rate))     
-//     HDMIWrReg(SRC_NUM_AUDIO_LEN, word_length);
-               
-    //Set N value 6144, fs=48kHz
-    HDMIWrReg(N_1, N & 0xFF);
-    HDMIWrReg(N_2, (N >> 8) & 0xFF);
-    HDMIWrReg(LR_SWAP_N3, (N >> 16) & 0x0F); 
-    
-    rk30_hdmi_config_aai();
-    return 0;
-}
-
-static void rk30_hdmi_audio_reset(void)
-{
-       int value;
-       
-       HDMIMskReg(value, VIDEO_SETTING2, m_AUDIO_RESET, AUDIO_CAPTURE_RESET)
-       msleep(1);
-       HDMIMskReg(value, VIDEO_SETTING2, m_AUDIO_RESET, 0)
-}
-
-void rk30_hdmi_control_output(int enable)
-{
-       hdmi_dbg(hdmi->dev, "[%s] %d\n", __FUNCTION__, enable);
-       if(enable == 0) {
-               HDMIWrReg(VIDEO_SETTING2, 0x03);
-       }
-       else {
-               if(hdmi->pwr_mode == PWR_SAVE_MODE_B) {
-                       //  Switch to power save mode_d
-                       rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_D);
-               }
-               if(hdmi->pwr_mode == PWR_SAVE_MODE_D) {
-                       //  Switch to power save mode_e
-                       rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_E);
-               }
-               HDMIWrReg(VIDEO_SETTING2, 0x00);
-               rk30_hdmi_audio_reset();
-       }
-}
-
-int rk30_hdmi_removed(void)
-{
-       if(hdmi->pwr_mode == PWR_SAVE_MODE_E)
-       {
-               HDMIWrReg(VIDEO_SETTING2, 0x00);
-               rk30_hdmi_audio_reset();
-               rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_D);
-       }
-       if(hdmi->pwr_mode == PWR_SAVE_MODE_D)
-               rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_B);
-       if(hdmi->pwr_mode == PWR_SAVE_MODE_B && hdmi->state == HDMI_SLEEP)
-       {
-               HDMIWrReg(INTR_MASK1, m_INT_HOTPLUG | m_INT_MSENS);
-               HDMIWrReg(INTR_MASK2, 0);
-               HDMIWrReg(INTR_MASK3, 0);
-               HDMIWrReg(INTR_MASK4, 0);
-               // Disable color space convertion
-               HDMIWrReg(AV_CTRL2, v_CSC_ENABLE(0));
-               HDMIWrReg(CSC_CONFIG1, v_CSC_MODE(CSC_MODE_AUTO) | v_CSC_BRSWAP_DIABLE(1));
-               if(hdmi->hdcp_power_off_cb)
-                       hdmi->hdcp_power_off_cb();
-               rk30_hdmi_set_pwr_mode(PWR_SAVE_MODE_A);
-       }
-       dev_printk(KERN_INFO , hdmi->dev , "Removed.\n");
-       return HDMI_ERROR_SUCESS;
-}
-
-
-irqreturn_t hdmi_irq(int irq, void *priv)
-{              
-       char interrupt1 = 0, interrupt2 = 0, interrupt3 = 0, interrupt4 = 0;
-       
-       if(hdmi->pwr_mode == PWR_SAVE_MODE_A)
-       {
-               HDMIWrReg(SYS_CTRL, 0x20);
-               hdmi->pwr_mode = PWR_SAVE_MODE_B;
-               
-               hdmi_dbg(hdmi->dev, "hdmi irq wake up\n");
-               // HDMI was inserted when system is sleeping, irq was triggered only once
-               // when wake up. So we need to check hotplug status.
-               if(HDMIRdReg(HPD_MENS_STA) & (m_HOTPLUG_STATUS | m_MSEN_STATUS)) {                      
-                       queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));
-               }
-       }
-       else
-       {
-               interrupt1 = HDMIRdReg(INTR_STATUS1);
-               interrupt2 = HDMIRdReg(INTR_STATUS2);
-               interrupt3 = HDMIRdReg(INTR_STATUS3);
-               interrupt4 = HDMIRdReg(INTR_STATUS4);
-               HDMIWrReg(INTR_STATUS1, interrupt1);
-               HDMIWrReg(INTR_STATUS2, interrupt2);
-               HDMIWrReg(INTR_STATUS3, interrupt3);
-               HDMIWrReg(INTR_STATUS4, interrupt4);
-#if 0
-               hdmi_dbg(hdmi->dev, "[%s] interrupt1 %02x interrupt2 %02x interrupt3 %02x interrupt4 %02x\n",\
-                        __FUNCTION__, interrupt1, interrupt2, interrupt3, interrupt4);
-#endif
-               if(interrupt1 & (m_INT_HOTPLUG | m_INT_MSENS))
-               {
-                       if(hdmi->state == HDMI_SLEEP)
-                               hdmi->state = WAIT_HOTPLUG;
-                       interrupt1 &= ~(m_INT_HOTPLUG | m_INT_MSENS);
-                       queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, msecs_to_jiffies(10));   
-               }
-               else if(interrupt1 & (m_INT_EDID_READY | m_INT_EDID_ERR)) {
-                       spin_lock(&hdmi->irq_lock);
-                       edid_result = interrupt1;
-                       spin_unlock(&hdmi->irq_lock);
-               }
-               else if(hdmi->state == HDMI_SLEEP) {
-                       hdmi_dbg(hdmi->dev, "hdmi return to sleep mode\n");
-                       HDMIWrReg(SYS_CTRL, 0x10);
-                       hdmi->pwr_mode = PWR_SAVE_MODE_A;
-               }
-               if(interrupt2 && hdmi->hdcp_irq_cb)
-                       hdmi->hdcp_irq_cb(interrupt2);
-       }
-       return IRQ_HANDLED;
-}
-
diff --git a/drivers/video/rockchip/hdmi/rk30_hdmi_hw.h b/drivers/video/rockchip/hdmi/rk30_hdmi_hw.h
deleted file mode 100755 (executable)
index 6a5fc33..0000000
+++ /dev/null
@@ -1,446 +0,0 @@
-#ifndef __RK30_HDMI_HW_H__
-#define __RK30_HDMI_HW_H__
-
-/* HDMI_SYS_CONTROL */
-#define SYS_CTRL       0x0
-
-enum {
-       PWR_SAVE_MODE_A = 1,
-       PWR_SAVE_MODE_B = 2,
-       PWR_SAVE_MODE_D = 4,
-       PWR_SAVE_MODE_E = 8
-};
-#define m_PWR_SAVE_MODE                0xF0
-#define v_PWR_SAVE_MODE(n)     (n << 4)
-#define PLL_B_RESET                    (1 << 3)
-
-#define N_32K          0x1000
-#define N_441K                 0x1880
-#define N_882K                 0x3100
-#define N_1764K        0x6200
-#define N_48K          0x1800
-#define N_96K          0x3000
-#define N_192K                 0x6000
-
-#define LR_SWAP_N3                     0x04
-#define N_2                                    0x08
-#define N_1                                    0x0c
-
-#define AUDIO_CTRL1                    0x28
-#define AUDIO_CTRL2            0x2c
-#define I2S_AUDIO_CTRL         0x30
-enum {
-       I2S_MODE_STANDARD = 0,
-       I2S_MODE_RIGHT_JUSTIFIED,
-       I2S_MODE_LEFT_JUSTIFIED
-};
-#define v_I2S_MODE(n)          n
-enum {
-       I2S_CHANNEL_1_2 = 1,
-       I2S_CHANNEL_3_4 = 3,
-       I2S_CHANNEL_5_6 = 7,
-       I2S_CHANNEL_7_8 = 0xf
-};
-#define v_I2S_CHANNEL(n)       ( (n) << 2 )
-
-#define I2S_INPUT_SWAP         0x40
-
-#define SRC_NUM_AUDIO_LEN      0x50
-
-/* HDMI_AV_CTRL1*/
-#define AV_CTRL1       0x54
-enum {
-       AUDIO_32K       = 0x3,
-       AUDIO_441K      = 0x0,
-       AUDIO_48K       = 0x2,
-       AUDIO_882K      = 0x8,
-       AUDIO_96K       = 0xa,
-       AUDIO_1764K     = 0xc,
-       AUDIO_192K      = 0xe,
-};
-#define m_AUDIO_SAMPLE_RATE            0xF0
-#define v_AUDIO_SAMPLE_RATE(n) (n << 4)
-enum {
-       VIDEO_INPUT_RGB_YCBCR_444 = 0,
-       VIDEO_INPUT_YCBCR422,
-       VIDEO_INPUT_YCBCR422_EMBEDDED_SYNC,
-       VIDEO_INPUT_2X_CLOCK,
-       VIDEO_INPUT_2X_CLOCK_EMBEDDED_SYNC,
-       VIDEO_INPUT_RGB444_DDR,
-       VIDEO_INPUT_YCBCR422_DDR
-};
-#define m_INPUT_VIDEO_MODE                     (7 << 1)
-#define v_INPUT_VIDEO_MODE(n)          (n << 1)
-enum {
-       INTERNAL_DE = 0,
-       EXTERNAL_DE
-};
-#define m_DE_SIGNAL_SELECT                     (1 << 0)
-
-/* HDMI_AV_CTRL2 */
-#define AV_CTRL2       0xec
-#define m_CSC_ENABLE                           (1 << 0)
-#define v_CSC_ENABLE(n)                                (n)
-
-/* HDMI_VIDEO_CTRL1 */
-#define VIDEO_CTRL1    0x58
-enum {
-       VIDEO_OUTPUT_RGB444 = 0,
-       VIDEO_OUTPUT_YCBCR444,
-       VIDEO_OUTPUT_YCBCR422
-};
-#define m_VIDEO_OUTPUT_MODE            (0x3 << 6)
-#define v_VIDEO_OUTPUT_MODE(n) (n << 6)
-enum {
-       VIDEO_INPUT_DEPTH_12BIT = 0,
-       VIDEO_INPUT_DEPTH_10BIT = 0x1,
-       VIDEO_INPUT_DEPTH_8BIT = 0x3
-};
-#define m_VIDEO_INPUT_DEPTH            (3 << 4)
-#define v_VIDEO_INPUT_DEPTH(n) (n << 4)
-enum {
-       VIDEO_EMBEDDED_SYNC_LOCATION_0 = 0,
-       VIDEO_EMBEDDED_SYNC_LOCATION_1,
-       VIDEO_EMBEDDED_SYNC_LOCATION_2
-};
-#define m_VIDEO_EMBEDDED_SYNC_LOCATION         (3 << 2)
-#define VIDEO_EMBEDDED_SYNC_LOCATION(n)                (n << 2)
-enum {
-       VIDEO_INPUT_COLOR_RGB = 0,
-       VIDEO_INPUT_COLOR_YCBCR
-};
-#define m_VIDEO_INPUT_COLOR_MODE                       (1 << 0)
-
-/* DEEP_COLOR_MODE */
-#define DEEP_COLOR_MODE        0x5c
-enum{
-       TMDS_CLOCK_MODE_8BIT = 0,
-       TMDS_CLOKK_MODE_10BIT,
-       TMDS_CLOKK_MODE_12BIT
-};
-#define TMDS_CLOCK_MODE_MASK   0x3 << 6
-#define TMDS_CLOCK_MODE(n)             (n) << 6
-
-/* VIDEO_CTRL2 */
-#define VIDEO_SETTING2 0x114
-#define m_UNMUTE                                       (1 << 7)
-#define m_MUTE                                         (1 << 6)
-#define m_AUDIO_RESET                          (1 << 2)
-#define m_NOT_SEND_AUDIO                       (1 << 1)
-#define m_NOT_SEND_VIDEO                       (1 << 0)
-#define AV_UNMUTE                                      (1 << 7)                // Unmute video and audio, send normal video and audio data
-#define AV_MUTE                                                (1 << 6)                // Mute video and audio, send black video data and silent audio data
-#define AUDIO_CAPTURE_RESET                    (1 << 2)                // Reset audio process logic, only available in pwr_e mode.
-#define NOT_SEND_AUDIO                         (1 << 1)                // Send silent audio data
-#define NOT_SEND_VIDEO                         (1 << 0)                // Send black video data
-
-/* Color Space Convertion Parameter*/
-#define CSC_PARA_C0_H  0x60
-#define CSC_PARA_C0_L  0x64
-#define CSC_PARA_C1_H  0x68
-#define CSC_PARA_C1_L  0x6c
-#define CSC_PARA_C2_H  0x70
-#define CSC_PARA_C2_L  0x74
-#define CSC_PARA_C3_H  0x78
-#define CSC_PARA_C3_L  0x7c
-#define CSC_PARA_C4_H  0x80
-#define CSC_PARA_C4_L  0x84
-#define CSC_PARA_C5_H  0x88
-#define CSC_PARA_C5_L  0x8c
-#define CSC_PARA_C6_H  0x90
-#define CSC_PARA_C6_L  0x94
-#define CSC_PARA_C7_H  0x98
-#define CSC_PARA_C7_L  0x9c
-#define CSC_PARA_C8_H  0xa0
-#define CSC_PARA_C8_L  0xa4
-#define CSC_PARA_C9_H  0xa8
-#define CSC_PARA_C9_L  0xac
-#define CSC_PARA_C10_H 0xac
-#define CSC_PARA_C10_L 0xb4
-#define CSC_PARA_C11_H 0xb8
-#define CSC_PARA_C11_L 0xbc
-
-#define CSC_CONFIG1            0x34c
-#define m_CSC_MODE                     (1 << 7)
-#define m_CSC_COEF_MODE        (0xF << 3)      //Only used in auto csc mode
-#define m_CSC_STATUS           (1 << 2)
-#define m_CSC_VID_SELECT       (1 << 1)
-#define m_CSC_BRSWAP_DIABLE    (1)
-
-enum {
-       CSC_MODE_MANUAL = 0,
-       CSC_MODE_AUTO
-};
-#define v_CSC_MODE(n)                  (n << 7)
-enum {
-       COE_SDTV_LIMITED_RANGE = 0x08,
-       COE_SDTV_FULL_RANGE = 0x04,
-       COE_HDTV_60Hz = 0x2,
-       COE_HDTV_50Hz = 0x1
-};
-#define v_CSC_COE_MODE(n)              (n << 3)
-enum {
-       CSC_INPUT_VID_5_19 = 0,
-       CSC_INPUT_VID_28_29
-};
-#define v_CSC_VID_SELECT(n)            (n << 1)
-#define v_CSC_BRSWAP_DIABLE(n) (n)
-
-/* CONTROL_PACKET_BUF_INDEX */
-#define CONTROL_PACKET_BUF_INDEX       0x17c
-enum {
-       INFOFRAME_AVI = 0x06,
-       INFOFRAME_AAI = 0x08
-};
-#define CONTROL_PACKET_HB0                     0x180
-#define CONTROL_PACKET_HB1                     0x184
-#define CONTROL_PACKET_HB2                     0x188
-#define CONTROL_PACKET_PB_ADDR         0x18c
-#define SIZE_AVI_INFOFRAME                     0x11    // 17 bytes
-#define SIZE_AUDIO_INFOFRAME           0x0F    // 15 bytes
-enum {
-       AVI_COLOR_MODE_RGB = 0,
-       AVI_COLOR_MODE_YCBCR422,
-       AVI_COLOR_MODE_YCBCR444
-};
-enum {
-       AVI_COLORIMETRY_NO_DATA = 0,
-       AVI_COLORIMETRY_SMPTE_170M,
-       AVI_COLORIMETRY_ITU709,
-       AVI_COLORIMETRY_EXTENDED
-};
-enum {
-       AVI_CODED_FRAME_ASPECT_NO_DATA,
-       AVI_CODED_FRAME_ASPECT_4_3,
-       AVI_CODED_FRAME_ASPECT_16_9
-};
-enum {
-       ACTIVE_ASPECT_RATE_SAME_AS_CODED_FRAME = 0x08,
-       ACTIVE_ASPECT_RATE_4_3,
-       ACTIVE_ASPECT_RATE_16_9,
-       ACTIVE_ASPECT_RATE_14_9
-};
-
-/* External Video Parameter Setting*/
-#define EXT_VIDEO_PARA                 0xC0
-#define m_VSYNC_OFFSET                 (0xF << 4)
-#define m_VSYNC_POLARITY               (1 << 3)
-#define m_HSYNC_POLARITY               (1 << 2)
-#define m_INTERLACE                            (1 << 1)
-#define m_EXT_VIDEO_ENABLE             (1 << 0)
-
-#define v_VSYNC_OFFSET(n)              (n << 4)
-#define v_VSYNC_POLARITY(n)            (n << 3)
-#define v_HSYNC_POLARITY(n)            (n << 2)
-#define v_INTERLACE(n)                 (n << 1)
-#define v_EXT_VIDEO_ENABLE(n)  (n << 0) 
-
-#define EXT_VIDEO_PARA_HTOTAL_L                0xC4
-#define EXT_VIDEO_PARA_HTOTAL_H                0xC8
-#define EXT_VIDEO_PARA_HBLANK_L                0xCC
-#define EXT_VIDEO_PARA_HBLANK_H                0xD0
-#define EXT_VIDEO_PARA_HDELAY_L                0xD4
-#define EXT_VIDEO_PARA_HDELAY_H                0xD8
-#define EXT_VIDEO_PARA_HSYNCWIDTH_L    0xDC
-#define EXT_VIDEO_PARA_HSYNCWIDTH_H    0xE0
-
-#define EXT_VIDEO_PARA_VTOTAL_L                0xE4
-#define EXT_VIDEO_PARA_VTOTAL_H                0xE8
-#define EXT_VIDEO_PARA_VBLANK_L                0xF4
-#define EXT_VIDEO_PARA_VDELAY          0xF8
-#define EXT_VIDEO_PARA_VSYNCWIDTH      0xFC
-
-#define PHY_PLL_SPEED                          0x158
-       #define v_TEST_EN(n)                    (n << 6)
-       #define v_PLLA_BYPASS(n)                (n << 4)
-       #define v_PLLB_SPEED(n)                 (n << 2)
-       #define v_PLLA_SPEED(n)                 (n)
-       enum {
-               PLL_SPEED_LOWEST = 0,
-               PLL_SPEED_MIDLOW,
-               PLL_SPEED_MIDHIGH,
-               PLL_SPEED_HIGHEST
-       };
-
-#define PHY_PLL_17                                     0x15c           // PLL A & B config bit 17
-       #define v_PLLA_BIT17(n)                 (n << 2)
-       #define v_PLLB_BIT17(n)                 (n << 1)
-       
-#define PHY_BGR                                                0x160
-       #define v_BGR_DISCONNECT(n)             (n << 7)
-       #define v_BGR_V_OFFSET(n)               (n << 4)
-       #define v_BGR_I_OFFSET(n)               (n)
-
-#define PHY_PLLA_1                                     0x164
-#define PHY_PLLA_2                                     0x168
-#define PHY_PLLB_1                                     0x16c
-#define PHY_PLLB_2                                     0x170
-
-#define PHY_DRIVER_PREEMPHASIS         0x174
-       #define v_TMDS_SWING(n)                 (n << 4)
-       #define v_PRE_EMPHASIS(n)               (n)
-       
-#define PHY_PLL_16_AML                         0x178           // PLL A & B config bit 16 and AML control
-       #define v_PLLA_BIT16(n)                 (n << 5)
-       #define v_PLLB_BIT16(n)                 (n << 4)
-       #define v_AML(n)                                (n)
-
-/* Interrupt Setting */
-#define INTR_MASK1                                     0x248
-#define INTR_STATUS1                           0x250
-       #define m_INT_HOTPLUG                           (1 << 7)
-       #define m_INT_MSENS                                     (1 << 6)
-       #define m_INT_VSYNC                                     (1 << 5)
-       #define m_INT_AUDIO_FIFO_FULL           (1 << 4)
-       #define m_INT_EDID_READY                        (1 << 2)
-       #define m_INT_EDID_ERR                          (1 << 1)
-#define INTR_MASK2                                     0x24c
-#define INTR_STATUS2                           0x254
-       #define m_INT_HDCP_ERR                          (1 << 7)        // HDCP error detected
-       #define m_INT_BKSV_RPRDY                        (1 << 6)        // BKSV list ready from repeater
-       #define m_INT_BKSV_RCRDY                        (1 << 5)        // BKSV list ready from receiver
-       #define m_INT_AUTH_DONE                         (1 << 4)        // HDCP authentication done
-       #define m_INT_AUTH_READY                        (1 << 3)        // HDCP authentication ready
-#define INTR_MASK3                                     0x258
-#define INTR_STATUS3                           0x260
-
-#define INTR_MASK4                                     0x25c
-#define INTR_STATUS4                           0x264
-
-#define DDC_READ_FIFO_ADDR                     0x200
-#define DDC_BUS_FREQ_L                         0x204
-#define DDC_BUS_FREQ_H                         0x208
-#define DDC_BUS_CTRL                           0x2dc
-#define DDC_I2C_LEN                                    0x278
-#define DDC_I2C_OFFSET                         0x280
-#define DDC_I2C_CTRL                           0x284
-#define DDC_I2C_READ_BUF0                      0x288
-#define DDC_I2C_READ_BUF1                      0x28c
-#define DDC_I2C_READ_BUF2                      0x290
-#define DDC_I2C_READ_BUF3                      0x294
-#define DDC_I2C_WRITE_BUF0                     0x298
-#define DDC_I2C_WRITE_BUF1                     0x29c
-#define DDC_I2C_WRITE_BUF2                     0x2a0
-#define DDC_I2C_WRITE_BUF3                     0x2a4
-#define DDC_I2C_WRITE_BUF4                     0x2ac
-#define DDC_I2C_WRITE_BUF5                     0x2b0
-#define DDC_I2C_WRITE_BUF6                     0x2b4
-
-#define EDID_SEGMENT_POINTER           0x310
-#define EDID_WORD_ADDR                         0x314
-#define EDID_FIFO_ADDR                         0x318
-
-#define HPD_MENS_STA                           0x37c
-#define m_HOTPLUG_STATUS                       (1 << 7)
-#define m_MSEN_STATUS                          (1 << 6)
-
-/* HDCP_CTRL */
-#define HDCP_CTRL              0x2bc
-       enum {
-               OUTPUT_DVI = 0,
-               OUTPUT_HDMI
-       };
-       #define m_HDCP_AUTH_START                       (1 << 7)        // start hdcp
-       #define m_HDCP_BKSV_PASS                        (1 << 6)        // bksv valid
-       #define m_HDCP_BKSV_FAILED                      (1 << 5)        // bksv invalid
-       #define m_HDCP_FRAMED_ENCRYPED          (1 << 4)
-       #define m_HDCP_AUTH_STOP                        (1 << 3)        // stop hdcp
-       #define m_HDCP_ADV_CIPHER                       (1 << 2)        // advanced cipher mode
-       #define m_HDMI_DVI                                      (1 << 1)
-       #define m_HDCP_RESET                            (1 << 0)        // reset hdcp
-       #define v_HDCP_AUTH_START(n)            (n << 7)
-       #define v_HDCP_BKSV_PASS(n)                     (n << 6)
-       #define v_HDCP_BKSV_FAILED(n)           (n << 5)
-       #define v_HDCP_FRAMED_ENCRYPED(n)       (n << 4)
-       #define v_HDCP_AUTH_STOP(n)                     (n << 3)
-       #define v_HDCP_ADV_CIPHER(n)            (n << 2)
-       #define v_HDMI_DVI(n)                           (n << 1)
-       #define v_HDCP_RESET(n)                         (n << 0)
-#define HDCP_CTRL2             0x340
-
-/* HDCP Key Memory Access Control */
-#define HDCP_KEY_ACCESS_CTRL1  0x338
-#define HDCP_KEY_ACCESS_CTRL2  0x33c
-       #define m_LOAD_FACSIMILE_HDCP_KEY       (1 << 1)
-       #define m_LOAD_HDCP_KEY                         (1 << 0)
-/* HDCP Key Memory Control */
-#define HDCP_KEY_MEM_CTRL      0x348
-       #define m_USE_KEY1              (1 << 6)
-       #define m_USE_KEY2              (1 << 5)
-       #define m_LOAD_AKSV             (1 << 4)
-       #define m_KSV_SELECTED  (1 << 3)
-       #define m_KSV_VALID             (1 << 2)
-       #define m_KEY_VALID             (1 << 1)
-       #define m_KEY_READY             (1 << 0)
-       #define v_USE_KEY1(n)   (n << 6)
-       #define v_USE_KEY2(n)   (n << 5)
-       #define v_LOAD_AKSV(n)  (n << 4)
-
-/* HDCP B device capacity */
-#define HDCP_BCAPS                             0x2f8
-       #define m_HDMI_RECEIVED                 (1 << 7) //If HDCP receiver support HDMI, this bit must be 1.
-       #define m_REPEATER                              (1 << 6)
-       #define m_KSV_FIFO_READY                (1 << 5)
-       #define m_DDC_FAST                              (1 << 4)
-       #define m_1_1_FEATURE                   (1 << 1)
-       #define m_FAST_REAUTHENTICATION (1 << 0) //For HDMI, this function is supported whether this bit is enabled or not.
-
-/* HDCP KSV Value */
-#define HDCP_KSV_BYTE0                 0x2fc
-#define HDCP_KSV_BYTE1                 0x300
-#define HDCP_KSV_BYTE2                 0x304
-#define HDCP_KSV_BYTE3                 0x308
-#define HDCP_KSV_BYTE4                 0x30c
-
-/* HDCP error status */
-#define HDCP_ERROR                             0x320
-
-/* HDCP 100 ms timer */
-#define HDCP_TIMER_100MS               0x324
-/* HDCP 5s timer */
-#define HDCP_TIMER_5S                  0x328
-
-/* HDCP Key ram address */
-#define HDCP_RAM_KEY_KSV1              0x400
-#define HDCP_RAM_KEY_KSV2              0x407
-#define HDCP_RAM_KEY_PRIVATE   0x40e
-#define HDCP_KEY_LENGTH                        0x13C
-
-
-#define HDCP_ENABLE_HW_AUTH            // Enable hardware authentication mode  
-#define HDMI_INTERANL_CLK_DIV  0x19
-
-#define HDMIRdReg(addr)                                                __raw_readl(hdmi->regbase + addr)
-#define HDMIWrReg(addr, val)                   __raw_writel((val), hdmi->regbase + addr);
-#define HDMIMskReg(temp, addr, msk, val)       \
-       temp = __raw_readl(hdmi->regbase + addr) & (0xFF - (msk)) ; \
-       __raw_writel(temp | ( (val) & (msk) ),  hdmi->regbase + addr); 
-
-/* RK30 HDMI Video Configure Parameters */
-struct rk30_hdmi_video_para {
-       int vic;
-       int input_mode;         //input video data interface
-       int input_color;        //input video color mode
-       int output_mode;        //output hdmi or dvi
-       int output_color;       //output video color mode
-};
-
-/* Color Space Convertion Mode */
-enum {
-       CSC_RGB_0_255_TO_ITU601_16_235 = 0,     //RGB 0-255 input to YCbCr 16-235 output according BT601
-       CSC_RGB_0_255_TO_ITU709_16_235,         //RGB 0-255 input to YCbCr 16-235 output accroding BT709
-       CSC_ITU601_16_235_TO_RGB_16_235,        //YCbCr 16-235 input to RGB 16-235 output according BT601
-       CSC_ITU709_16_235_TO_RGB_16_235,        //YCbCr 16-235 input to RGB 16-235 output according BT709
-       CSC_ITU601_16_235_TO_RGB_0_255,         //YCbCr 16-235 input to RGB 0-255 output according BT601
-       CSC_ITU709_16_235_TO_RGB_0_255          //YCbCr 16-235 input to RGB 0-255 output according BT709
-};
-
-extern int rk30_hdmi_initial(void);
-extern int rk30_hdmi_detect_hotplug(void);
-extern int rk30_hdmi_read_edid(int block, unsigned char *buff);
-extern int rk30_hdmi_removed(void);
-extern int rk30_hdmi_config_video(struct rk30_hdmi_video_para *vpara);
-extern int rk30_hdmi_config_audio(struct hdmi_audio *audio);
-extern void rk30_hdmi_control_output(int enable);
-
-#endif
\ No newline at end of file
diff --git a/drivers/video/rockchip/hdmi/rk30_hdmi_lcdc.c b/drivers/video/rockchip/hdmi/rk30_hdmi_lcdc.c
deleted file mode 100755 (executable)
index 406837e..0000000
+++ /dev/null
@@ -1,527 +0,0 @@
-#include <linux/console.h>
-#include "rk30_hdmi.h"
-#include "rk30_hdmi_hw.h"
-#include<linux/rk_fb.h>
-
-#define OUT_TYPE               SCREEN_HDMI
-#define OUT_FACE               OUT_P888
-#define DCLK_POL               1
-#define SWAP_RB                        0
-#define LCD_ACLK               800000000
-
-const struct fb_videomode hdmi_mode [] = {
-       //name                          refresh         xres    yres    pixclock        h_bp    h_fp    v_bp    v_fp    h_pw    v_pw    polariry        PorI    flag(used for vic)
-//{    "640x480p@60Hz",        60,                     640,    480,    25175000,       48,             16,             33,             10,             96,             2,              0,                      0,              1       },
-//{    "720x480i@60Hz",        60,                     720,    480,    27000000,       114,    38,             15,             4,              124,    3,              0,                      1,              6       },
-//{    "720x576i@50Hz",        50,                     720,    576,    27000000,       138,    24,             19,             2,              126,    3,              0,                      1,              21      },
-{      "720x480p@60Hz",        60,                     720,    480,    27000000,       60,             16,             30,             9,              62,             6,              0,                      0,              2       },
-{      "720x576p@50Hz",        50,                     720,    576,    27000000,       68,             12,             39,             5,              64,             5,              0,                      0,              17      },
-//{    "1280x720p@24Hz",       24,                     1280,   720,    59400000,       220,    1760,   20,             5,              40,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              60      },
-//{    "1280x720p@25Hz",       25,                     1280,   720,    74250000,       220,    2420,   20,             5,              40,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              61      },
-//{    "1280x720p@30Hz",       30,                     1280,   720,    74250000,       220,    1760,   20,             5,              40,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              62      },
-{      "1280x720p@50Hz",       50,                     1280,   720,    74250000,       220,    440,    20,             5,              40,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              19      },
-{      "1280x720p@60Hz",       60,                     1280,   720,    74250000,       220,    110,    20,             5,              40,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              4       },
-//{    "1920x1080p@24Hz",      24,                     1920,   1080,   74250000,       148,    638,    36,             4,              44,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              32      },
-//{    "1920x1080p@25Hz",      25,                     1920,   1080,   74250000,       148,    528,    36,             4,              44,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              33      },
-//{    "1920x1080p@30Hz",      30,                     1920,   1080,   74250000,       148,    88,             36,             4,              44,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              34      },      
-//{    "1920x1080i@50Hz_2",50,                 1920,   1080,   72000000,       184,    32,             57,             23,             168,    5,              FB_SYNC_HOR_HIGH_ACT,                   1,              39      },
-//{    "1920x1080i@50Hz",      50,                     1920,   1080,   74250000,       148,    528,    15,             2,              44,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   1,              20      },
-//{    "1920x1080i@60Hz",      60,                     1920,   1080,   74250000,       148,    88,             15,             2,              44,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   1,              5       },
-{      "1920x1080p@50Hz",      50,                     1920,   1080,   148500000,      148,    528,    36,             4,              44,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              31      },
-{      "1920x1080p@60Hz",      60,                     1920,   1080,   148500000,      148,    88,             36,             4,              44,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              16      },
-/*
-{      "1440x288p@50Hz",       50,                     720,    480,    27000000,       138,    24,             19,             2,              126,    3,              0,                      0,              23      },
-{      "2880x576i@50Hz",       50,                     1440,   240,    54000000,       276,    48,             19,             2,              252,    3,              0,                      1,              25      },
-{      "2880x288p@50Hz",       50,                     2880,   480,    54000000,       276,    48,             19,             3,              252,    3,              0,                      0,              27      },
-{      "1440x576p@50Hz",       50,                     2880,   480,    54000000,       136,    24,             39,             5,              128,    5,              0,                      0,              29      },
-{      "2880x576p@50Hz",       50,                     1920,   1080,   108000000,      272,    48,             39,             5,              256,    5,              0,                      0,              37      },
-{      "1440x240p@60Hz",       60,                     1440,   240,    27000000,       114,    38,             15,             4,              124,    3,              0,                      0,              8       },
-{      "2880x480i@60Hz",       60,                     2880,   480,    54000000,       228,    76,             15,             4,              248,    3,              0,                      1,              10      },
-{      "2880x480p@60Hz",       60,                     2880,   480,    54000000,       228,    76,             15,             4,              248,    3,              0,                      0,              12      },
-{      "1440x480p@60Hz",       60,                     1440,   480,    54000000,       120,    32,             30,             9,              124,    6,              0,                      0,              14      },
-{      "2880x480p@60Hz",       60,                     2880,   480,    54000000,       240,    64,             30,             9,              248,    6,              0,                      0,              35      },
-
-{      "1920x1080i@100Hz",     100,            1920,   1080,   148500000,      148,    528,    15,             2,              44,             5,              1,                      1,              40      },
-{      "1280x720p@100Hz",      100,            1280,   720,    148500000,      220,    440,    20,             5,              40,             5,              1,                      0,              41      },
-{      "720x576p@100Hz",       100,            720,    576,    54000000,       68,             12,             39,             5,              64,             5,              0,                      0,              42      },
-{      "1440x576i@100Hz",      100,            1440,   576,    54000000,       138,    24,             19,             2,              12,             3,              0,                      1,              44      },
-{      "1920x1080p@100Hz",     100,            1920,   1080,   297000000,      148,    528,    36,             4,              44,             5,              1,                      0,              64      },
-
-{      "1920x1080i@120Hz",     120,            1920,   1080,   148500000,      148,    88,             15,             2,              44,             5,              1,                      1,              46      },
-{      "1280x720p@120Hz",      120,            1280,   720,    148500000,      220,    110,    20,             5,              40,             5,              1,                      0,              47      },
-{      "720x480p@120Hz",       120,            720,    480,    54000000,       60,             16,             30,             9,              62,             6,              0,                      0,              48      },
-{      "1440x480i@120Hz",      120,            1440,   480,    54000000,       114,    38,             15,             4,              12,             3,              0,                      1,              50      },
-{      "1920x1080p@120Hz",     120,            1920,   1080,   297000000,      148,    88,             36,             4,              44,             5,              1,                      0,              63      },
-
-{      "720x576p@200Hz",       200,            720,    576,    108000000,      68,             12,             39,             5,              64,             5,              0,                      0,              52      },
-{      "1440x576i@200Hz",      200,            1920,   1080,   108000000,      138,    24,             19,             2,              12,             3,              0,                      1,              54      },
-
-{      "720x480p@240Hz",       240,            720,    480,    108000000,      60,             16,             30,             9,              62,             6,              0,                      0,              56      },
-{      "1440x480i@240Hz",      240,            1440,   480,    108000000,      114,    38,             15,             4,              12,             3,              0,                      1,              58      },
-*/
-
-};
-
-void hdmi_init_lcdc(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info)
-{
-       hdmi_set_info(screen, HDMI_VIDEO_DEFAULT_MODE);
-}
-
-int hdmi_set_info(struct rk29fb_screen *screen, unsigned int vic)
-{
-    int i;
-    
-    if(screen == NULL)
-       return -1;
-    
-    if(vic == 0)
-       vic = HDMI_VIDEO_DEFAULT_MODE;
-       
-    for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++)
-    {
-       if(hdmi_mode[i].flag == vic)
-               break;
-    }
-    if(i == ARRAY_SIZE(hdmi_mode))
-       return -1;
-    
-    memset(screen, 0, sizeof(struct rk29fb_screen));
-    
-    /* screen type & face */
-    screen->type = OUT_TYPE;
-    screen->face = OUT_FACE;
-
-    /* Screen size */
-    screen->x_res = hdmi_mode[i].xres;
-    screen->y_res = hdmi_mode[i].yres;
-    
-    /* Timing */
-    screen->pixclock = hdmi_mode[i].pixclock;
-       screen->lcdc_aclk = LCD_ACLK;
-       screen->left_margin = hdmi_mode[i].left_margin;
-       screen->right_margin = hdmi_mode[i].right_margin;
-       screen->hsync_len = hdmi_mode[i].hsync_len;
-       screen->upper_margin = hdmi_mode[i].upper_margin;
-       screen->lower_margin = hdmi_mode[i].lower_margin;
-       screen->vsync_len = hdmi_mode[i].vsync_len;
-
-       /* Pin polarity */
-       if(FB_SYNC_HOR_HIGH_ACT & hdmi_mode[i].sync)
-               screen->pin_hsync = 1;
-       else
-               screen->pin_hsync = 0;
-       if(FB_SYNC_VERT_HIGH_ACT & hdmi_mode[i].sync)
-               screen->pin_vsync = 1;
-       else
-               screen->pin_vsync = 0;
-       screen->pin_den = 0;
-       screen->pin_dclk = DCLK_POL;
-
-       /* Swap rule */
-    screen->swap_rb = SWAP_RB;
-    screen->swap_rg = 0;
-    screen->swap_gb = 0;
-    screen->swap_delta = 0;
-    screen->swap_dumy = 0;
-
-    /* Operation function*/
-    screen->init = NULL;
-    screen->standby = NULL;
-    
-    return 0;
-}
-
-static void hdmi_show_sink_info(struct hdmi *hdmi)
-{
-       struct list_head *pos, *head = &hdmi->edid.modelist;
-       struct fb_modelist *modelist;
-       struct fb_videomode *m;
-       int i;
-       struct hdmi_audio *audio;
-
-       hdmi_dbg(hdmi->dev, "******** Show Sink Info ********\n");
-       hdmi_dbg(hdmi->dev, "Support video mode: \n");
-       list_for_each(pos, head) {
-               modelist = list_entry(pos, struct fb_modelist, list);
-               m = &modelist->mode;
-               hdmi_dbg(hdmi->dev, "   %s.\n", m->name);
-       }
-       
-       for(i = 0; i < hdmi->edid.audio_num; i++)
-       {
-               audio = &(hdmi->edid.audio[i]);
-               switch(audio->type)
-               {
-                       case HDMI_AUDIO_LPCM:
-                               hdmi_dbg(hdmi->dev, "Support audio type: LPCM\n");
-                               break;
-                       case HDMI_AUDIO_AC3:
-                               hdmi_dbg(hdmi->dev, "Support audio type: AC3\n");
-                               break;
-                       case HDMI_AUDIO_MPEG1:
-                               hdmi_dbg(hdmi->dev, "Support audio type: MPEG1\n");
-                               break;
-                       case HDMI_AUDIO_MP3:
-                               hdmi_dbg(hdmi->dev, "Support audio type: MP3\n");
-                               break;
-                       case HDMI_AUDIO_MPEG2:
-                               hdmi_dbg(hdmi->dev, "Support audio type: MPEG2\n");
-                               break;
-                       case HDMI_AUDIO_AAC_LC:
-                               hdmi_dbg(hdmi->dev, "Support audio type: AAC\n");
-                               break;
-                       case HDMI_AUDIO_DTS:
-                               hdmi_dbg(hdmi->dev, "Support audio type: DTS\n");
-                               break;
-                       case HDMI_AUDIO_ATARC:
-                               hdmi_dbg(hdmi->dev, "Support audio type: ATARC\n");
-                               break;
-                       case HDMI_AUDIO_DSD:
-                               hdmi_dbg(hdmi->dev, "Support audio type: DSD\n");
-                               break;
-                       case HDMI_AUDIO_E_AC3:
-                               hdmi_dbg(hdmi->dev, "Support audio type: E-AC3\n");
-                               break;
-                       case HDMI_AUDIO_DTS_HD:
-                               hdmi_dbg(hdmi->dev, "Support audio type: DTS-HD\n");
-                               break;
-                       case HDMI_AUDIO_MLP:
-                               hdmi_dbg(hdmi->dev, "Support audio type: MLP\n");
-                               break;
-                       case HDMI_AUDIO_DST:
-                               hdmi_dbg(hdmi->dev, "Support audio type: DST\n");
-                               break;
-                       case HDMI_AUDIO_WMA_PRO:
-                               hdmi_dbg(hdmi->dev, "Support audio type: WMP-PRO\n");
-                               break;
-                       default:
-                               hdmi_dbg(hdmi->dev, "Support audio type: Unkown\n");
-                               break;
-               }
-               
-               hdmi_dbg(hdmi->dev, "Support audio sample rate: \n");
-               if(audio->rate & HDMI_AUDIO_FS_32000)
-                       hdmi_dbg(hdmi->dev, "   32000\n");
-               if(audio->rate & HDMI_AUDIO_FS_44100)
-                       hdmi_dbg(hdmi->dev, "   44100\n");
-               if(audio->rate & HDMI_AUDIO_FS_48000)
-                       hdmi_dbg(hdmi->dev, "   48000\n");
-               if(audio->rate & HDMI_AUDIO_FS_88200)
-                       hdmi_dbg(hdmi->dev, "   88200\n");
-               if(audio->rate & HDMI_AUDIO_FS_96000)
-                       hdmi_dbg(hdmi->dev, "   96000\n");
-               if(audio->rate & HDMI_AUDIO_FS_176400)
-                       hdmi_dbg(hdmi->dev, "   176400\n");
-               if(audio->rate & HDMI_AUDIO_FS_192000)
-                       hdmi_dbg(hdmi->dev, "   192000\n");
-               
-               hdmi_dbg(hdmi->dev, "Support audio word lenght: \n");
-               if(audio->rate & HDMI_AUDIO_WORD_LENGTH_16bit)
-                       hdmi_dbg(hdmi->dev, "   16bit\n");
-               if(audio->rate & HDMI_AUDIO_WORD_LENGTH_20bit)
-                       hdmi_dbg(hdmi->dev, "   20bit\n");
-               if(audio->rate & HDMI_AUDIO_WORD_LENGTH_24bit)
-                       hdmi_dbg(hdmi->dev, "   24bit\n");
-       }
-       hdmi_dbg(hdmi->dev, "******** Show Sink Info ********\n");
-}
-
-/**
- * hdmi_ouputmode_select - select hdmi transmitter output mode: hdmi or dvi?
- * @hdmi: handle of hdmi
- * @edid_ok: get EDID data success or not, HDMI_ERROR_SUCESS means success.
- */
-int hdmi_ouputmode_select(struct hdmi *hdmi, int edid_ok)
-{
-       struct list_head *head = &hdmi->edid.modelist;
-       struct fb_monspecs      *specs = hdmi->edid.specs;
-       struct fb_videomode *modedb = NULL;
-       int i, pixclock;
-       
-       if(edid_ok != HDMI_ERROR_SUCESS) {
-               dev_err(hdmi->dev, "warning: EDID error, assume sink as HDMI !!!!");
-               hdmi->edid.sink_hdmi = 1;
-       }
-
-       if(edid_ok != HDMI_ERROR_SUCESS) {
-               hdmi->edid.ycbcr444 = 0;
-               hdmi->edid.ycbcr422 = 0;
-               hdmi->autoconfig = HDMI_DISABLE;
-       }
-       if(head->next == head) {
-               dev_info(hdmi->dev, "warning: no CEA video mode parsed from EDID !!!!");
-               // If EDID get error, list all system supported mode.
-               // If output mode is set to DVI and EDID is ok, check
-               // the output timing.
-               
-               if(hdmi->edid.sink_hdmi == 0 && specs && specs->modedb_len) {
-                       /* Get max resolution timing */
-                       modedb = &specs->modedb[0];
-                       for (i = 0; i < specs->modedb_len; i++) {
-                               if(specs->modedb[i].xres > modedb->xres)
-                                       modedb = &specs->modedb[i];
-                               else if(specs->modedb[i].yres > modedb->yres)
-                                       modedb = &specs->modedb[i];
-                       }
-                       // For some monitor, the max pixclock read from EDID is smaller
-                       // than the clock of max resolution mode supported. We fix it.
-                       pixclock = PICOS2KHZ(modedb->pixclock);
-                       pixclock /= 250;
-                       pixclock *= 250;
-                       pixclock *= 1000;
-                       if(pixclock == 148250000)
-                               pixclock = 148500000;
-                       if(pixclock > specs->dclkmax)
-                               specs->dclkmax = pixclock;
-               }
-               
-               for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
-                       if(modedb) {
-                               if( (hdmi_mode[i].pixclock < specs->dclkmin) || 
-                                       (hdmi_mode[i].pixclock > specs->dclkmax) || 
-                                       (hdmi_mode[i].refresh < specs->vfmin) ||
-                                       (hdmi_mode[i].refresh > specs->vfmax) ||
-                                       (hdmi_mode[i].xres > modedb->xres) ||
-                                       (hdmi_mode[i].yres > modedb->yres) )
-                               continue;
-                       }
-                       hdmi_add_videomode(&hdmi_mode[i], head);
-               }
-       }
-       
-       #ifdef HDMI_DEBUG
-       hdmi_show_sink_info(hdmi);
-       #endif
-       return HDMI_ERROR_SUCESS;
-}
-/**
- * hdmi_videomode_compare - compare 2 videomodes
- * @mode1: first videomode
- * @mode2: second videomode
- *
- * RETURNS:
- * 1 if mode1 > mode2, 0 if mode1 = mode2, -1 mode1 < mode2
- */
-static int hdmi_videomode_compare(const struct fb_videomode *mode1,
-                    const struct fb_videomode *mode2)
-{
-       if(mode1->xres > mode2->xres)
-               return 1;
-       else if(mode1->xres == mode2->xres)
-       { 
-               if(mode1->yres > mode2->yres)
-                       return 1;
-               else if(mode1->yres == mode2->yres)
-               {
-                       if(mode1->pixclock > mode2->pixclock)   
-                               return 1;
-                       else if(mode1->pixclock == mode2->pixclock)
-                       {       
-                               if(mode1->refresh > mode2->refresh)
-                                       return 1;
-                               else if(mode1->refresh == mode2->refresh) 
-                                       return 0;
-                       }
-               }
-       }
-       return -1;              
-}
-/**
- * hdmi_add_videomode: adds videomode entry to modelist
- * @mode: videomode to add
- * @head: struct list_head of modelist
- *
- * NOTES:
- * Will only add unmatched mode entries
- */
-int hdmi_add_videomode(const struct fb_videomode *mode, struct list_head *head)
-{
-       struct list_head *pos;
-       struct fb_modelist *modelist, *modelist_new;
-       struct fb_videomode *m;
-       int i, found = 0;
-
-       for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++)
-    {
-       m =(struct fb_videomode*) &hdmi_mode[i];
-       if (fb_mode_is_equal(m, mode)) {
-                       found = 1;
-                       break;
-               }
-    }
-
-       if (found) {
-               list_for_each(pos, head) {
-                       modelist = list_entry(pos, struct fb_modelist, list);
-                       m = &modelist->mode;
-                       if (fb_mode_is_equal(m, mode)) {
-                       // m == mode    
-                               return 0;
-                       }
-                       else
-                       { 
-                               if(hdmi_videomode_compare(m, mode) == -1) {
-                                       break;
-                               }
-                       }
-               }
-
-               modelist_new = kmalloc(sizeof(struct fb_modelist),
-                                 GFP_KERNEL);                                  
-               if (!modelist_new)
-                       return -ENOMEM; 
-               modelist_new->mode = hdmi_mode[i];
-               list_add_tail(&modelist_new->list, pos);
-       }
-       
-       return 0;
-}
-
-/**
- * hdmi_videomode_to_vic: transverse video mode to vic
- * @vmode: videomode to transverse
- * 
- */
-int hdmi_videomode_to_vic(struct fb_videomode *vmode)
-{
-       unsigned char vic = 0;
-       int i = 0;
-       
-       for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++)
-       {
-               if(     vmode->vmode == hdmi_mode[i].vmode &&
-                       vmode->refresh == hdmi_mode[i].refresh &&
-                       vmode->xres == hdmi_mode[i].xres && 
-                       vmode->left_margin == hdmi_mode[i].left_margin &&
-                       vmode->right_margin == hdmi_mode[i].right_margin &&
-                       vmode->upper_margin == hdmi_mode[i].upper_margin &&
-                       vmode->lower_margin == hdmi_mode[i].lower_margin && 
-                       vmode->hsync_len == hdmi_mode[i].hsync_len && 
-                       vmode->vsync_len == hdmi_mode[i].vsync_len)
-               {
-                       if( (vmode->vmode == FB_VMODE_NONINTERLACED && vmode->yres == hdmi_mode[i].yres) || 
-                               (vmode->vmode == FB_VMODE_INTERLACED && vmode->yres == hdmi_mode[i].yres/2))
-                       {                                                               
-                               vic = hdmi_mode[i].flag;
-                               break;
-                       }
-               }
-       }
-       return vic;
-}
-
-/**
- * hdmi_vic_to_videomode: transverse vic mode to video mode
- * @vmode: vic to transverse
- * 
- */
-const struct fb_videomode* hdmi_vic_to_videomode(int vic)
-{
-       int i;
-       
-       if(vic == 0)
-               return NULL;
-       
-       for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++)
-       {
-               if(hdmi_mode[i].flag == vic)
-                       return &hdmi_mode[i];
-       }
-       return NULL;
-}
-
-/**
- * hdmi_find_best_mode: find the video mode nearest to input vic
- * @hdmi: 
- * @vic: input vic
- * 
- * NOTES:
- * If vic is zero, return the high resolution video mode vic.
- */
-int hdmi_find_best_mode(struct hdmi* hdmi, int vic)
-{
-       struct list_head *pos, *head = &hdmi->edid.modelist;
-       struct fb_modelist *modelist;
-       struct fb_videomode *m = NULL;
-       int found = 0;
-       
-       if(vic)
-       {
-               list_for_each(pos, head) {
-                       modelist = list_entry(pos, struct fb_modelist, list);
-                       m = &modelist->mode;
-                       if(m->flag == vic)
-                       {
-                               found = 1;      
-                               break;
-                       }
-               }
-       }
-       if( (vic == 0 || found == 0) && head->next != head)
-       {
-               modelist = list_entry(head->next, struct fb_modelist, list);
-               m = &modelist->mode;
-       }
-       if(m != NULL)
-               return m->flag;
-       else
-               return 0;
-}
-
-const char *hdmi_get_video_mode_name(unsigned char vic)
-{
-       int i;
-       
-       for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++)
-       {
-               if(vic == hdmi_mode[i].flag)
-                       break;
-       }
-       if(i == ARRAY_SIZE(hdmi_mode))
-               return NULL;
-       else
-               return hdmi_mode[i].name;
-}
-
-/**
- * hdmi_switch_fb: switch lcdc mode to required video mode
- * @hdmi: 
- * @type:
- * 
- * NOTES:
- * 
- */
-int hdmi_switch_fb(struct hdmi *hdmi, int vic)
-{
-       int rc = 0;
-
-       if(hdmi->vic == 0)
-               hdmi->vic = HDMI_VIDEO_DEFAULT_MODE;
-               
-       if(hdmi->lcdc == NULL || hdmi->lcdc->screen == NULL) {
-               dev_err(hdmi->dev, "lcdc %d not exist\n", HDMI_SOURCE_DEFAULT);
-               return -1;
-       }
-
-       rc = hdmi_set_info(hdmi->lcdc->screen, hdmi->vic);
-
-       if(rc == 0) {           
-               rk_fb_switch_screen(hdmi->lcdc->screen, 1, HDMI_SOURCE_DEFAULT);
-               rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, HDMI_SOURCE_DEFAULT);
-       }
-       return rc;
-}
-
-/**
- * hdmi_get_status: get hdmi hotplug status
- * 
- * NOTES:
- * 
- */
-int hdmi_get_hotplug(void)
-{
-       if(hdmi)
-               return hdmi->hotplug;
-       else
-               return HDMI_HPD_REMOVED;
-}
\ No newline at end of file
diff --git a/drivers/video/rockchip/hdmi/rk30_hdmi_sysfs.c b/drivers/video/rockchip/hdmi/rk30_hdmi_sysfs.c
deleted file mode 100755 (executable)
index 828b771..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/display-sys.h>
-#include <linux/interrupt.h>
-#include "rk30_hdmi.h"
-
-static int hdmi_get_enable(struct rk_display_device *device)
-{
-       struct hdmi *hdmi = device->priv_data;
-       int enable;
-       
-       mutex_lock(&hdmi->enable_mutex);
-       enable = hdmi->enable;
-       mutex_unlock(&hdmi->enable_mutex);
-       
-       return enable;
-}
-
-static int hdmi_set_enable(struct rk_display_device *device, int enable)
-{
-       struct hdmi *hdmi = device->priv_data;
-       
-       mutex_lock(&hdmi->enable_mutex);
-       if(hdmi->enable == enable) {
-               mutex_unlock(&hdmi->enable_mutex);
-               return 0;
-       }
-       hdmi->enable = enable;
-       
-       if(hdmi->suspend ) {
-               mutex_unlock(&hdmi->enable_mutex);
-               return 0;
-       }
-       
-       if(enable == 0) {
-               disable_irq(hdmi->irq);
-               mutex_unlock(&hdmi->enable_mutex);
-               hdmi->command = HDMI_CONFIG_ENABLE;
-               queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
-       }
-       else {
-               enable_irq(hdmi->irq);
-               mutex_unlock(&hdmi->enable_mutex);
-       }
-       return 0;
-}
-
-static int hdmi_get_status(struct rk_display_device *device)
-{
-       struct hdmi *hdmi = device->priv_data;
-       if(hdmi->hotplug == HDMI_HPD_ACTIVED)
-               return 1;
-       else
-               return 0;
-}
-
-static int hdmi_get_modelist(struct rk_display_device *device, struct list_head **modelist)
-{
-       struct hdmi *hdmi = device->priv_data;
-       if(!hdmi->hotplug)
-               return -1;
-       *modelist = &hdmi->edid.modelist;
-       return 0;
-}
-
-static int hdmi_set_mode(struct rk_display_device *device, struct fb_videomode *mode)
-{
-       struct hdmi *hdmi = device->priv_data;
-       int vic = hdmi_videomode_to_vic(mode);
-       
-       if(!hdmi->hotplug)
-               return -1;
-       hdmi->autoconfig = HDMI_DISABLE;
-       if(vic && hdmi->vic != vic)
-       {
-               hdmi->vic = vic;
-               hdmi->command = HDMI_CONFIG_VIDEO;
-               init_completion(&hdmi->complete);
-               hdmi->wait = 1;
-               queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
-               wait_for_completion_interruptible_timeout(&hdmi->complete,
-                                                               msecs_to_jiffies(10000));
-       }
-       return 0;
-}
-
-static int hdmi_get_mode(struct rk_display_device *device, struct fb_videomode *mode)
-{
-       struct hdmi *hdmi = device->priv_data;
-       struct fb_videomode *vmode;
-       
-       if(!hdmi->hotplug)
-               return -1;
-               
-       vmode = (struct fb_videomode*) hdmi_vic_to_videomode(hdmi->vic);
-       if(unlikely(vmode == NULL))
-               return -1;
-       *mode = *vmode;
-       return 0;
-}
-
-static int hdmi_set_scale(struct rk_display_device *device, int direction, int value)
-{
-       struct hdmi *hdmi = device->priv_data;
-       
-       if(!hdmi || value < 0 || value > 100)
-               return -1;
-                       
-       if(direction == DISPLAY_SCALE_X)
-               hdmi->xscale = value;
-       else if(direction == DISPLAY_SCALE_Y)
-               hdmi->yscale = value;
-       else
-               return -1;
-       rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, HDMI_SOURCE_DEFAULT);
-       return 0;
-}
-
-static int hdmi_get_scale(struct rk_display_device *device, int direction)
-{
-       struct hdmi *hdmi = device->priv_data;
-       
-       if(!hdmi)
-               return -1;
-               
-       if(direction == DISPLAY_SCALE_X)
-               return hdmi->xscale;
-       else if(direction == DISPLAY_SCALE_Y)
-               return hdmi->yscale;
-       else
-               return -1;
-}
-
-struct rk_display_ops hdmi_display_ops = {
-       .setenable = hdmi_set_enable,
-       .getenable = hdmi_get_enable,
-       .getstatus = hdmi_get_status,
-       .getmodelist = hdmi_get_modelist,
-       .setmode = hdmi_set_mode,
-       .getmode = hdmi_get_mode,
-       .setscale = hdmi_set_scale,
-       .getscale = hdmi_get_scale,
-};
-
-#if 1
-static int hdmi_display_probe(struct rk_display_device *device, void *devdata)
-{
-       device->owner = THIS_MODULE;
-       strcpy(device->type, "HDMI");
-       device->priority = DISPLAY_PRIORITY_HDMI;
-//     device->name = kmalloc(strlen(name), GFP_KERNEL);
-//     if(device->name)
-//     {
-//             strcpy(device->name, name);
-//     }
-       device->priv_data = devdata;
-       device->ops = &hdmi_display_ops;
-       return 1;
-}
-
-static struct rk_display_driver display_hdmi = {
-       .probe = hdmi_display_probe,
-};
-
-static struct rk_display_device *display_device_hdmi = NULL;
-
-void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent)
-{
-       display_device_hdmi = rk_display_device_register(&display_hdmi, parent, hdmi);
-}
-
-void hdmi_unregister_display_sysfs(struct hdmi *hdmi)
-{
-       if(display_device_hdmi)
-               rk_display_device_unregister(display_device_hdmi);
-}
-#endif
\ No newline at end of file
diff --git a/drivers/video/rockchip/hdmi/rk30_hdmi_task.c b/drivers/video/rockchip/hdmi/rk30_hdmi_task.c
deleted file mode 100755 (executable)
index cbee83a..0000000
+++ /dev/null
@@ -1,312 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include "rk30_hdmi.h"
-#include "rk30_hdmi_hw.h"
-
-#ifdef CONFIG_HDMI_RK30_CTL_CODEC
-extern void codec_set_spk(bool on);
-#endif
-
-#define HDMI_MAX_TRY_TIMES     1
-
-static char *envp[] = {"INTERFACE=HDMI", NULL};
-
-static void hdmi_sys_show_state(int state)
-{
-       switch(state)
-       {
-               case HDMI_SLEEP:
-                       dev_printk(KERN_INFO, hdmi->dev, "HDMI_SLEEP\n");
-                       break;
-               case HDMI_INITIAL:
-                       dev_printk(KERN_INFO, hdmi->dev, "HDMI_INITIAL\n");
-                       break;
-               case WAIT_HOTPLUG:
-                       dev_printk(KERN_INFO, hdmi->dev, "WAIT_HOTPLUG\n");
-                       break;
-               case READ_PARSE_EDID:
-                       dev_printk(KERN_INFO, hdmi->dev, "READ_PARSE_EDID\n");
-                       break;
-               case WAIT_HDMI_ENABLE:
-                       dev_printk(KERN_INFO, hdmi->dev, "WAIT_HDMI_ENABLE\n");
-                       break;
-               case SYSTEM_CONFIG:
-                       dev_printk(KERN_INFO, hdmi->dev, "SYSTEM_CONFIG\n");
-                       break;
-               case CONFIG_VIDEO:
-                       dev_printk(KERN_INFO, hdmi->dev, "CONFIG_VIDEO\n");
-                       break;
-               case CONFIG_AUDIO:
-                       dev_printk(KERN_INFO, hdmi->dev, "CONFIG_AUDIO\n");
-                       break;
-               case PLAY_BACK:
-                       dev_printk(KERN_INFO, hdmi->dev, "PLAY_BACK\n");
-                       break;
-               default:
-                       dev_printk(KERN_INFO, hdmi->dev, "Unkown State %d\n", state);
-                       break;
-       }
-}
-
-int hdmi_sys_init(void)
-{
-       hdmi->pwr_mode                  = PWR_SAVE_MODE_A;
-       hdmi->hotplug                   = HDMI_HPD_REMOVED;
-       hdmi->state                             = HDMI_SLEEP;
-       hdmi->enable                    = HDMI_ENABLE;
-       hdmi->autoconfig                = HDMI_AUTO_CONFIGURE;
-       hdmi->display                   = HDMI_DISABLE;
-       
-       hdmi->vic                               = HDMI_VIDEO_DEFAULT_MODE;
-       hdmi->audio.channel     = HDMI_AUDIO_DEFAULT_CHANNEL;
-       hdmi->audio.rate                = HDMI_AUDIO_DEFAULT_RATE;
-       hdmi->audio.word_length = HDMI_AUDIO_DEFAULT_WORD_LENGTH;
-       
-       memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
-       INIT_LIST_HEAD(&hdmi->edid.modelist);
-       return 0;
-}
-
-void hdmi_sys_remove(void)
-{
-       fb_destroy_modelist(&hdmi->edid.modelist);
-       if(hdmi->edid.audio)
-               kfree(hdmi->edid.audio);
-       if(hdmi->edid.specs)
-       {
-               if(hdmi->edid.specs->modedb)
-                       kfree(hdmi->edid.specs->modedb);
-               kfree(hdmi->edid.specs);
-       }
-       memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
-       INIT_LIST_HEAD(&hdmi->edid.modelist);
-       hdmi->display   = HDMI_DISABLE;
-       rk_fb_switch_screen(hdmi->lcdc->screen, 0, HDMI_SOURCE_DEFAULT);
-       kobject_uevent_env(&hdmi->dev->kobj, KOBJ_REMOVE, envp);
-       #ifdef CONFIG_SWITCH
-       switch_set_state(&(hdmi->switch_hdmi), 0);
-       #endif
-       #ifdef CONFIG_HDMI_RK30_CTL_CODEC
-       codec_set_spk(1);
-       #endif
-}
-
-static void hdmi_sys_sleep(void)
-{
-       mutex_lock(&hdmi->enable_mutex);
-       if(hdmi->enable)
-               disable_irq(hdmi->irq);                         
-       hdmi->state = HDMI_SLEEP;
-       rk30_hdmi_removed();
-       if(hdmi->enable)
-               enable_irq(hdmi->irq);
-       mutex_unlock(&hdmi->enable_mutex);
-}
-
-static int hdmi_process_command(void)
-{
-       int change, state = hdmi->state;
-       
-       change = hdmi->command;
-       if(change != HDMI_CONFIG_NONE)  
-       {               
-               hdmi->command = HDMI_CONFIG_NONE;
-               switch(change)
-               {       
-                       case HDMI_CONFIG_ENABLE:
-                               /* disable HDMI */
-                               mutex_lock(&hdmi->enable_mutex);
-                               if(!hdmi->enable || hdmi->suspend)
-                               {
-                                       if(hdmi->hotplug == HDMI_HPD_ACTIVED)
-                                               hdmi_sys_remove();
-                                       hdmi->state = HDMI_SLEEP;
-                                       hdmi->hotplug = HDMI_HPD_REMOVED;
-                                       rk30_hdmi_removed();
-                                       state = HDMI_SLEEP;
-                               }
-                               mutex_unlock(&hdmi->enable_mutex);
-                               if(hdmi->wait == 1) {
-                                       complete(&hdmi->complete);
-                                       hdmi->wait = 0; 
-                               }
-                               break;  
-                       case HDMI_CONFIG_COLOR:
-                               if(state > CONFIG_VIDEO)
-                                       state = CONFIG_VIDEO;   
-                               break;
-                       case HDMI_CONFIG_HDCP:
-                               break;
-                       case HDMI_CONFIG_DISPLAY:
-                               break;
-                       case HDMI_CONFIG_AUDIO:
-                               if(state > CONFIG_AUDIO)
-                                       state = CONFIG_AUDIO;
-                               break;
-                       case HDMI_CONFIG_VIDEO:
-                       default:
-                               if(state > SYSTEM_CONFIG)
-                                       state = SYSTEM_CONFIG;
-                               else
-                               {
-                                       if(hdmi->wait == 1) {
-                                               complete(&hdmi->complete);
-                                               hdmi->wait = 0; 
-                                       }                                       
-                               }
-                               break;
-               }
-       }
-       else if(state == HDMI_SLEEP)
-               state = WAIT_HOTPLUG;
-       return state;
-}
-
-static DEFINE_MUTEX(work_mutex);
-
-void hdmi_work(struct work_struct *work)
-{
-       int hotplug, state_last;
-       int rc = HDMI_ERROR_SUCESS, trytimes = 0;
-       struct rk30_hdmi_video_para video;
-       
-       mutex_lock(&work_mutex);
-       /* Process hdmi command */
-       hdmi->state = hdmi_process_command();
-       
-       if(!hdmi->enable || hdmi->suspend) {
-               mutex_unlock(&work_mutex);
-               return;
-       }
-       hotplug = rk30_hdmi_detect_hotplug();
-       hdmi_dbg(hdmi->dev, "[%s] hotplug %02x curvalue %d\n", __FUNCTION__, hotplug, hdmi->hotplug);
-       
-       if(hotplug != hdmi->hotplug)
-       {
-               if(hotplug  == HDMI_HPD_ACTIVED){
-                       hdmi->state = READ_PARSE_EDID;
-               }
-               else if(hdmi->hotplug == HDMI_HPD_ACTIVED) {
-                       hdmi_sys_remove();
-                       hdmi->hotplug = hotplug;
-                       if(hotplug == HDMI_HPD_REMOVED)
-                               hdmi_sys_sleep();
-                       else {
-                               hdmi->state = WAIT_HOTPLUG;
-                               rk30_hdmi_removed();
-                       }
-                       if(hdmi->wait == 1) {
-                               complete(&hdmi->complete);
-                               hdmi->wait = 0; 
-                       }
-                       mutex_unlock(&work_mutex);
-                       return;
-               }
-               else if(hotplug == HDMI_HPD_REMOVED) {
-                       hdmi->state = HDMI_SLEEP;
-                       rk30_hdmi_removed();
-               }
-               hdmi->hotplug  = hotplug;
-       }
-       else if(hotplug == HDMI_HPD_REMOVED)
-               hdmi_sys_sleep();
-       
-       do {
-               hdmi_sys_show_state(hdmi->state);
-               state_last = hdmi->state;
-               switch(hdmi->state)
-               {
-                       case READ_PARSE_EDID:
-                               rc = hdmi_sys_parse_edid(hdmi);
-                               if(rc == HDMI_ERROR_SUCESS)
-                               {
-                                       hdmi->state = SYSTEM_CONFIG;    
-                                       kobject_uevent_env(&hdmi->dev->kobj, KOBJ_ADD, envp);
-                                       #ifdef CONFIG_SWITCH
-                                       switch_set_state(&(hdmi->switch_hdmi), 1);
-                                       #endif
-                                       #ifdef CONFIG_HDMI_RK30_CTL_CODEC
-                                       codec_set_spk(0);
-                                       #endif
-                               }
-                               break;
-                       case SYSTEM_CONFIG:
-                               if(hdmi->autoconfig)    
-                                       hdmi->vic = hdmi_find_best_mode(hdmi, 0);
-                               else
-                                       hdmi->vic = hdmi_find_best_mode(hdmi, hdmi->vic);
-                               rc = hdmi_switch_fb(hdmi, hdmi->vic);
-                               if(rc == HDMI_ERROR_SUCESS)
-                                       hdmi->state = CONFIG_VIDEO;
-                               break;
-                       case CONFIG_VIDEO:
-                               hdmi->display = HDMI_DISABLE;
-                               video.vic = hdmi->vic;
-                               video.input_mode = VIDEO_INPUT_RGB_YCBCR_444;
-                               video.input_color = VIDEO_INPUT_COLOR_RGB;//VIDEO_INPUT_COLOR_YCBCR
-                               video.output_mode = hdmi->edid.sink_hdmi;
-                               
-                               if(hdmi->edid.ycbcr444)
-                                       video.output_color = VIDEO_OUTPUT_YCBCR444;
-                               else if(hdmi->edid.ycbcr422)
-                                       video.output_color = VIDEO_OUTPUT_YCBCR422;
-                               else
-                                       video.output_color = VIDEO_OUTPUT_RGB444;
-                               // For DVI, output RGB
-                               if(hdmi->edid.sink_hdmi == 0)
-                                       video.output_color = VIDEO_OUTPUT_RGB444;
-                               
-                               rc = rk30_hdmi_config_video(&video);
-                               if(rc == HDMI_ERROR_SUCESS)
-                               {
-                                       if(hdmi->edid.sink_hdmi)
-                                               hdmi->state = CONFIG_AUDIO;
-                                       else
-                                               hdmi->state = PLAY_BACK;
-                               }
-                               break;
-                       case CONFIG_AUDIO:
-                               rc = rk30_hdmi_config_audio(&(hdmi->audio));
-                                                       
-                               if(rc == HDMI_ERROR_SUCESS)
-                                       hdmi->state = PLAY_BACK;
-                               break;
-                       case PLAY_BACK:
-                               if(hdmi->display != HDMI_ENABLE) {
-                                       rk30_hdmi_control_output(HDMI_ENABLE);
-                                       hdmi->display = HDMI_ENABLE;
-                                       if(hdmi->hdcp_cb) {
-                                               hdmi->hdcp_cb();
-                                       }
-                               }
-                               
-                               if(hdmi->wait == 1) {   
-                                       complete(&hdmi->complete);
-                                       hdmi->wait = 0;                                         
-                               }
-                               break;
-                       default:
-                               break;
-               }
-               if(rc != HDMI_ERROR_SUCESS)
-               {
-                       trytimes++;
-                       msleep(10);
-               }
-               if(hdmi->state != state_last) 
-                       trytimes = 0;
-       
-       }while((hdmi->state != state_last || (rc != HDMI_ERROR_SUCESS) ) && trytimes < HDMI_MAX_TRY_TIMES);
-       
-//     if(trytimes == HDMI_MAX_TRY_TIMES)
-//     {
-//             if(hdmi->hotplug) {
-//                     hdmi_sys_remove();
-//                     hdmi->hotplug = HDMI_HPD_REMOVED;
-//                     hdmi_sys_sleep();
-//
-//             }
-//     }
-       hdmi_dbg(hdmi->dev, "[%s] done\n", __FUNCTION__);
-       mutex_unlock(&work_mutex);
-}
\ No newline at end of file
index 534ba51ab5bd5e2e1111ffe24b7b578ea3aea106..cf6d34c6ce809da1adeda0829799686cb1fb011f 100755 (executable)
@@ -1,6 +1,61 @@
 #ifndef __RK_HDMI_H__
 #define __RK_HDMI_H__
 
+#include <linux/kernel.h>
+#include <linux/fb.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/display-sys.h>
+#ifdef CONFIG_SWITCH
+#include <linux/switch.h>
+#endif
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <asm/atomic.h>
+#include<linux/rk_screen.h>
+#include <linux/rk_fb.h>
+
+/* default HDMI output video mode */
+#define HDMI_VIDEO_DEFAULT_MODE                        HDMI_1280x720p_60Hz//HDMI_1920x1080p_60Hz
+
+// HDMI video source
+enum {
+       HDMI_SOURCE_LCDC0 = 0,
+       HDMI_SOURCE_LCDC1 = 1
+};
+
+/* default HDMI video source */
+#define HDMI_SOURCE_DEFAULT            HDMI_SOURCE_LCDC1
+/* If HDMI_ENABLE, system will auto configure output mode according to EDID 
+ * If HDMI_DISABLE, system will output mode according to macro HDMI_VIDEO_DEFAULT_MODE
+ */
+#define HDMI_AUTO_CONFIGURE                    HDMI_ENABLE
+
+/* default HDMI output audio mode */
+#define HDMI_AUDIO_DEFAULT_CHANNEL             2
+#define HDMI_AUDIO_DEFAULT_RATE                        HDMI_AUDIO_FS_44100
+#define HDMI_AUDIO_DEFAULT_WORD_LENGTH HDMI_AUDIO_WORD_LENGTH_16bit
+enum {
+       VIDEO_INPUT_RGB_YCBCR_444 = 0,
+       VIDEO_INPUT_YCBCR422,
+       VIDEO_INPUT_YCBCR422_EMBEDDED_SYNC,
+       VIDEO_INPUT_2X_CLOCK,
+       VIDEO_INPUT_2X_CLOCK_EMBEDDED_SYNC,
+       VIDEO_INPUT_RGB444_DDR,
+       VIDEO_INPUT_YCBCR422_DDR
+};
+enum {
+       VIDEO_OUTPUT_RGB444 = 0,
+       VIDEO_OUTPUT_YCBCR444,
+       VIDEO_OUTPUT_YCBCR422
+};
+enum {
+       VIDEO_INPUT_COLOR_RGB = 0,
+       VIDEO_INPUT_COLOR_YCBCR
+};
 /********************************************************************
 **                          Â½Ã¡Â¹Â¹Â¶Â¨Ã’Ã¥                                *
 ********************************************************************/
@@ -186,6 +241,72 @@ struct hdmi_edid {
 };
 
 extern const struct fb_videomode hdmi_mode[];
+/* RK HDMI Video Configure Parameters */
+struct hdmi_video_para {
+       int vic;
+       int input_mode;         //input video data interface
+       int input_color;        //input video color mode
+       int output_mode;        //output hdmi or dvi
+       int output_color;       //output video color mode
+};
+struct hdmi {
+       struct device   *dev;
+       struct clk              *hclk;                          //HDMI AHP clk
+       int             id;
+       int                     regbase;
+       int                             irq;
+       int                             regbase_phy;
+       int                             regsize_phy;
+       struct rk_lcdc_device_driver *lcdc;
+       
+       #ifdef CONFIG_SWITCH
+       struct switch_dev       switch_hdmi;
+       #endif
+       
+       struct workqueue_struct *workqueue;
+       struct delayed_work delay_work;
+       
+       spinlock_t      irq_lock;
+       struct mutex enable_mutex;
+       
+       int wait;
+       struct completion       complete;
+       
+       int suspend;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       struct early_suspend    early_suspend;
+#endif
+       
+       struct hdmi_edid edid;
+       int enable;                                     // Enable HDMI output or not
+       int vic;                                        // HDMI output video mode code
+       struct hdmi_audio audio;        // HDMI output audio type.
+       
+       int pwr_mode;                           // power mode
+       int hotplug;                            // hot plug status
+       int state;                                      // hdmi state machine status
+       int autoconfig;                         // if true, auto config hdmi output mode according to EDID.
+       int command;                            // HDMI configuration command
+       int display;                            // HDMI display status
+       int xscale;                                     // x direction scale value
+       int yscale;                                     // y directoon scale value
+       int tmdsclk;                            // TDMS Clock frequency
+       
+
+       int (*hdmi_removed)(void);
+       void (*control_output)(int enable);
+       int (*config_video)(struct hdmi_video_para *vpara);
+       int (*config_audio)(struct hdmi_audio *audio);
+       int (*detect_hotplug)(void);
+       // call back for edid
+       int (*read_edid)(int block, unsigned char *buff);
+
+       // call back for hdcp operatoion
+       void (*hdcp_cb)(void);
+       void (*hdcp_irq_cb)(int);
+       int (*hdcp_power_on_cb)(void);
+       void (*hdcp_power_off_cb)(void);
+};
 
 #define hdmi_err(dev, format, arg...)          \
        dev_printk(KERN_ERR , dev , format , ## arg)
@@ -197,7 +318,22 @@ extern const struct fb_videomode hdmi_mode[];
 #define hdmi_dbg(dev, format, arg...)  
 #endif
 
+extern struct hdmi *hdmi;
+extern struct hdmi *hdmi_register(int extra);
+extern void hdmi_unregister(struct hdmi *hdmi);
 extern int hdmi_get_hotplug(void);
 extern int hdmi_set_info(struct rk29fb_screen *screen, unsigned int vic);
 extern void hdmi_init_lcdc(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info);
+extern int hdmi_sys_init(void);
+extern int hdmi_sys_parse_edid(struct hdmi* hdmi);
+extern const char *hdmi_get_video_mode_name(unsigned char vic);
+extern int hdmi_videomode_to_vic(struct fb_videomode *vmode);
+extern const struct fb_videomode* hdmi_vic_to_videomode(int vic);
+extern int hdmi_add_videomode(const struct fb_videomode *mode, struct list_head *head);
+extern struct hdmi_video_timing * hdmi_find_mode(int vic);
+extern int hdmi_find_best_mode(struct hdmi* hdmi, int vic);
+extern int hdmi_ouputmode_select(struct hdmi *hdmi, int edid_ok);
+extern int hdmi_switch_fb(struct hdmi *hdmi, int vic);
+extern void hdmi_sys_remove(void);
+
 #endif
diff --git a/drivers/video/rockchip/hdmi/rk_hdmi_core.c b/drivers/video/rockchip/hdmi/rk_hdmi_core.c
new file mode 100755 (executable)
index 0000000..1b17185
--- /dev/null
@@ -0,0 +1,254 @@
+#include <linux/kernel.h>\r
+#include <linux/delay.h>\r
+#include <linux/module.h>\r
+#include <linux/err.h>\r
+#include <linux/slab.h>\r
+#include <linux/hdmi.h>\r
+#include <linux/input.h>\r
+\r
+\r
+struct class *hdmi_class;\r
+struct hdmi_id_ref_info {\r
+       struct hdmi *hdmi;\r
+       int id;\r
+       int ref;\r
+}ref_info[HDMI_MAX_ID];\r
+#ifdef CONFIG_SYSFS\r
+\r
+extern int hdmi_create_attrs(struct hdmi *hdmi);\r
+extern void hdmi_remove_attrs(struct hdmi *hdmi);\r
+\r
+#else\r
+\r
+static inline int hdmi_create_attrs(struct hdmi *hdmi)\r
+{ return 0; }\r
+static inline void hdmi_remove_attrs(struct hdmi *hdmi) {}\r
+\r
+#endif /* CONFIG_SYSFS */\r
+static void __hdmi_changed(struct hdmi *hdmi)\r
+{\r
+       int precent;\r
+       \r
+       mutex_lock(&hdmi->lock);\r
+       precent = hdmi->ops->hdmi_precent(hdmi);\r
+       if(precent && (hdmi->mode == DISP_ON_LCD) && hdmi->display_on){\r
+               if(hdmi->ops->insert(hdmi) == 0){\r
+                       hdmi->mode = hdmi->display_on;\r
+                       kobject_uevent(&hdmi->dev->kobj, KOBJ_CHANGE);\r
+               }\r
+               else\r
+                       hdmi_dbg(hdmi->dev, "insert error\n");\r
+        hdmi_set_backlight(hdmi->display_on==DISP_ON_HDMI?HDMI_DISABLE: HDMI_ENABLE);\r
+\r
+       }\r
+       else if(precent &&(hdmi->mode != hdmi->display_on)&& hdmi->display_on){\r
+           hdmi->mode = hdmi->display_on;\r
+        hdmi_set_backlight(hdmi->display_on==DISP_ON_HDMI?HDMI_DISABLE: HDMI_ENABLE); \r
+       }\r
+       else if((!precent || !hdmi->display_on) && hdmi->mode != DISP_ON_LCD){\r
+               if(hdmi->ops->remove(hdmi) == 0){\r
+                       hdmi->mode = DISP_ON_LCD;\r
+                       hdmi_set_backlight(HDMI_ENABLE);\r
+                       kobject_uevent(&hdmi->dev->kobj, KOBJ_CHANGE);\r
+               }\r
+               else\r
+                       hdmi_dbg(hdmi->dev, "remove error\n");\r
+       }\r
+       mutex_unlock(&hdmi->lock);\r
+       return;\r
+}\r
+\r
+void hdmi_changed(struct hdmi *hdmi, int msec)\r
+{      \r
+       schedule_delayed_work(&hdmi->work, msecs_to_jiffies(msec));\r
+       return;\r
+}\r
+void hdmi_suspend(struct hdmi *hdmi)\r
+{\r
+       del_timer(&hdmi->timer);\r
+       flush_delayed_work(&hdmi->work);\r
+       if(hdmi->mode != DISP_ON_LCD){\r
+               hdmi->ops->remove(hdmi);\r
+               hdmi->mode = DISP_ON_LCD;\r
+       }\r
+       return;\r
+}\r
+void hdmi_resume(struct hdmi *hdmi)\r
+{\r
+       mod_timer(&hdmi->timer, jiffies + msecs_to_jiffies(10));\r
+       return;\r
+}\r
+\r
+static void hdmi_changed_work(struct work_struct *work)\r
+{\r
+       struct hdmi *hdmi = container_of(work, struct hdmi,\r
+                                               work.work);\r
+       \r
+       __hdmi_changed(hdmi);\r
+       return;\r
+}\r
+\r
+void *hdmi_priv(struct hdmi *hdmi)\r
+{\r
+       return (void *)hdmi->priv;\r
+}\r
+static void hdmi_detect_timer(unsigned long data)\r
+{\r
+       struct hdmi *hdmi = (struct hdmi*)data;\r
+       \r
+       int precent =  hdmi->ops->hdmi_precent(hdmi);\r
+\r
+       if((precent && hdmi->mode == DISP_ON_LCD) ||\r
+                       (!precent && hdmi->mode != DISP_ON_LCD))\r
+               hdmi_changed(hdmi, 100);\r
+       mod_timer(&hdmi->timer, jiffies + msecs_to_jiffies(200));\r
+}\r
+struct hdmi *hdmi_register(int extra, struct device *parent)\r
+{\r
+       int rc = 0, i;\r
+       char name[8];\r
+       struct hdmi *hdmi = kzalloc(sizeof(struct hdmi)+ extra, GFP_KERNEL);\r
+\r
+       if(!hdmi)\r
+               return NULL;\r
+       for(i = 0; i < HDMI_MAX_ID; i++) \r
+       {\r
+               if(ref_info[i].ref == 0)\r
+               {\r
+                       ref_info[i].ref = 1;\r
+                       hdmi->id = i;\r
+                       break;\r
+               }\r
+       }\r
+       if(i == HDMI_MAX_ID)\r
+       {\r
+               kfree(hdmi);\r
+               return NULL;\r
+       }\r
+       sprintf(name, "hdmi-%d", hdmi->id);\r
+       \r
+       hdmi->dev = device_create(hdmi_class, parent, 0,\r
+                                "%s", name);\r
+       if (IS_ERR(hdmi->dev)) {\r
+               rc = PTR_ERR(hdmi->dev);\r
+               goto dev_create_failed;\r
+       }\r
+\r
+       dev_set_drvdata(hdmi->dev, hdmi);\r
+       ref_info[i].hdmi = hdmi;\r
+\r
+       INIT_DELAYED_WORK(&hdmi->work, hdmi_changed_work);\r
+\r
+       rc = hdmi_create_attrs(hdmi);\r
+       if (rc)\r
+               goto create_attrs_failed;\r
+\r
+       goto success;\r
+\r
+create_attrs_failed:\r
+       device_unregister(hdmi->dev);\r
+dev_create_failed:\r
+       hdmi_remove_attrs(hdmi);\r
+       kfree(hdmi);\r
+       return NULL;\r
+success:\r
+       mutex_init(&hdmi->lock);\r
+       setup_timer(&hdmi->timer, hdmi_detect_timer,(unsigned long)hdmi);\r
+       mod_timer(&hdmi->timer, jiffies + msecs_to_jiffies(200));\r
+       return hdmi;\r
+}\r
+void hdmi_unregister(struct hdmi *hdmi)\r
+{\r
+       int id;\r
+\r
+       if(!hdmi)\r
+               return;\r
+       id = hdmi->id;\r
+       del_timer(&hdmi->timer);\r
+       flush_scheduled_work();\r
+       hdmi_remove_attrs(hdmi);\r
+       device_unregister(hdmi->dev);\r
+\r
+       kfree(hdmi);\r
+       hdmi = NULL;\r
+       ref_info[id].ref = 0;\r
+       ref_info[id].hdmi = NULL;\r
+}\r
+struct hdmi *get_hdmi_struct(int nr)\r
+{\r
+       if(ref_info[nr].ref == 0)\r
+               return NULL;\r
+       else\r
+               return ref_info[nr].hdmi;\r
+}\r
+int hdmi_is_insert(void)\r
+{\r
+       struct hdmi *hdmi = get_hdmi_struct(0);\r
+\r
+       if(hdmi && hdmi->ops && hdmi->ops->hdmi_precent)\r
+               return hdmi->ops->hdmi_precent(hdmi);\r
+       else\r
+               return 0;\r
+}\r
+int hdmi_get_scale(void)\r
+{\r
+       struct hdmi* hdmi = get_hdmi_struct(0);\r
+       if(!hdmi)\r
+               return 100;\r
+       else if(hdmi->mode != DISP_ON_LCD)\r
+               return hdmi->scale;\r
+       else\r
+           return 100;\r
+}\r
+\r
+int hdmi_set_scale(int event, char *data, int len)\r
+{\r
+       int result;\r
+       struct hdmi* hdmi = get_hdmi_struct(0);\r
+\r
+       if(!hdmi)\r
+               return -1;\r
+       if(len != 4)\r
+               return -1;\r
+       if(fb_get_video_mode() || hdmi->mode == DISP_ON_LCD)\r
+               return -1;\r
+\r
+       result = data[0] | data[1]<<1 | data[2]<<2;\r
+       if(event != MOUSE_NONE && (result & event) != event)\r
+               return -1;\r
+\r
+       hdmi->scale += data[3];\r
+       \r
+       hdmi->scale = (hdmi->scale>100)?100:hdmi->scale;\r
+       hdmi->scale = (hdmi->scale<MIN_SCALE)?MIN_SCALE:hdmi->scale;\r
+       return 0;       \r
+}\r
+\r
+static int __init hdmi_class_init(void)\r
+{\r
+       int i;\r
+       \r
+       hdmi_class = class_create(THIS_MODULE, "hdmi");\r
+\r
+       if (IS_ERR(hdmi_class))\r
+               return PTR_ERR(hdmi_class);\r
+       for(i = 0; i < HDMI_MAX_ID; i++) {\r
+               ref_info[i].id = i;\r
+               ref_info[i].ref = 0;\r
+               ref_info[i].hdmi = NULL;\r
+       }\r
+       return 0;\r
+}\r
+\r
+static void __exit hdmi_class_exit(void)\r
+{\r
+       class_destroy(hdmi_class);\r
+}\r
+EXPORT_SYMBOL(hdmi_changed);\r
+EXPORT_SYMBOL(hdmi_register);\r
+EXPORT_SYMBOL(hdmi_unregister);\r
+EXPORT_SYMBOL(get_hdmi_struct);\r
+\r
+subsys_initcall(hdmi_class_init);\r
+module_exit(hdmi_class_exit);\r
+\r
diff --git a/drivers/video/rockchip/hdmi/rk_hdmi_edid.c b/drivers/video/rockchip/hdmi/rk_hdmi_edid.c
new file mode 100755 (executable)
index 0000000..ff44f48
--- /dev/null
@@ -0,0 +1,409 @@
+#include "rk_hdmi.h"\r
+#include "../../edid.h"\r
+\r
+#define hdmi_edid_error(fmt, ...) \\r
+        printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)\r
+\r
+#if 0\r
+#define hdmi_edid_debug(fmt, ...) \\r
+        printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)\r
+#else\r
+#define hdmi_edid_debug(fmt, ...)      \r
+#endif\r
+\r
+typedef enum HDMI_EDID_ERRORCODE\r
+{\r
+       E_HDMI_EDID_SUCCESS = 0,\r
+       E_HDMI_EDID_PARAM,\r
+       E_HDMI_EDID_HEAD,\r
+       E_HDMI_EDID_CHECKSUM,\r
+       E_HDMI_EDID_VERSION,\r
+       E_HDMI_EDID_UNKOWNDATA,\r
+       E_HDMI_EDID_NOMEMORY\r
+}HDMI_EDID_ErrorCode;\r
+\r
+static const unsigned int double_aspect_vic[] = {3, 7, 9, 11, 13, 15, 18, 22, 24, 26, 28, 30, 36, 38, 43, 45, 49, 51, 53, 55, 57, 59};\r
+static int hdmi_edid_checksum(unsigned char *buf)\r
+{\r
+       int i;\r
+       int checksum = 0;\r
+       \r
+       for(i = 0; i < HDMI_EDID_BLOCK_SIZE; i++)\r
+               checksum += buf[i];     \r
+       \r
+       checksum &= 0xff;\r
+       \r
+       if(checksum == 0)\r
+               return E_HDMI_EDID_SUCCESS;\r
+       else\r
+               return E_HDMI_EDID_CHECKSUM;\r
+}\r
+\r
+/*\r
+       @Des    Parse Detail Timing Descriptor.\r
+       @Param  buf     :       pointer to DTD data.\r
+       @Param  pvic:   VIC of DTD descripted.\r
+ */\r
+static int hdmi_edid_parse_dtd(unsigned char *block, struct fb_videomode *mode)\r
+{\r
+       mode->xres = H_ACTIVE;\r
+       mode->yres = V_ACTIVE;\r
+       mode->pixclock = PIXEL_CLOCK;\r
+//     mode->pixclock /= 1000;\r
+//     mode->pixclock = KHZ2PICOS(mode->pixclock);\r
+       mode->right_margin = H_SYNC_OFFSET;\r
+       mode->left_margin = (H_ACTIVE + H_BLANKING) -\r
+               (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);\r
+       mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -\r
+               V_SYNC_WIDTH;\r
+       mode->lower_margin = V_SYNC_OFFSET;\r
+       mode->hsync_len = H_SYNC_WIDTH;\r
+       mode->vsync_len = V_SYNC_WIDTH;\r
+       if (HSYNC_POSITIVE)\r
+               mode->sync |= FB_SYNC_HOR_HIGH_ACT;\r
+       if (VSYNC_POSITIVE)\r
+               mode->sync |= FB_SYNC_VERT_HIGH_ACT;\r
+       mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *\r
+                                    (V_ACTIVE + V_BLANKING));\r
+       if (INTERLACED) {\r
+               mode->yres *= 2;\r
+               mode->upper_margin *= 2;\r
+               mode->lower_margin *= 2;\r
+               mode->vsync_len *= 2;\r
+               mode->vmode |= FB_VMODE_INTERLACED;\r
+       }\r
+       mode->flag = FB_MODE_IS_DETAILED;\r
+\r
+       hdmi_edid_debug("<<<<<<<<Detailed Time>>>>>>>>>\n");\r
+       hdmi_edid_debug("%d KHz Refresh %d Hz",  PIXEL_CLOCK/1000, mode->refresh);\r
+       hdmi_edid_debug("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,\r
+              H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);\r
+       hdmi_edid_debug("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,\r
+              V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);\r
+       hdmi_edid_debug("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",\r
+              (VSYNC_POSITIVE) ? "+" : "-");\r
+       return E_HDMI_EDID_SUCCESS;\r
+}\r
+\r
+static int hdmi_edid_parse_base(unsigned char *buf, int *extend_num, struct hdmi_edid *pedid)\r
+{\r
+       int rc, i;\r
+       \r
+       if(buf == NULL || extend_num == NULL)\r
+               return E_HDMI_EDID_PARAM;\r
+               \r
+       #ifdef DEBUG    \r
+       for(i = 0; i < HDMI_EDID_BLOCK_SIZE; i++)\r
+       {\r
+               hdmi_edid_debug("%02x ", buf[i]&0xff);\r
+               if((i+1) % 16 == 0)\r
+                       hdmi_edid_debug("\n");\r
+       }\r
+       #endif\r
+       \r
+       // Check first 8 byte to ensure it is an edid base block.\r
+       if( buf[0] != 0x00 ||\r
+           buf[1] != 0xFF ||\r
+           buf[2] != 0xFF ||\r
+           buf[3] != 0xFF ||\r
+           buf[4] != 0xFF ||\r
+           buf[5] != 0xFF ||\r
+           buf[6] != 0xFF ||\r
+           buf[7] != 0x00)\r
+    {\r
+        hdmi_edid_error("[EDID] check header error\n");\r
+        return E_HDMI_EDID_HEAD;\r
+    }\r
+    \r
+    *extend_num = buf[0x7e];\r
+    #ifdef DEBUG\r
+    hdmi_edid_debug("[EDID] extend block num is %d\n", buf[0x7e]);\r
+    #endif\r
+    \r
+    // Checksum\r
+    rc = hdmi_edid_checksum(buf);\r
+    if( rc != E_HDMI_EDID_SUCCESS)\r
+    {\r
+       hdmi_edid_error("[EDID] base block checksum error\n");\r
+       return E_HDMI_EDID_CHECKSUM;\r
+    }\r
+\r
+       pedid->specs = kzalloc(sizeof(struct fb_monspecs), GFP_KERNEL);\r
+       if(pedid->specs == NULL)\r
+               return E_HDMI_EDID_NOMEMORY;\r
+               \r
+       fb_edid_to_monspecs(buf, pedid->specs);\r
+       \r
+    return E_HDMI_EDID_SUCCESS;\r
+}\r
+\r
+// Parse CEA Short Video Descriptor\r
+static int hdmi_edid_get_cea_svd(unsigned char *buf, struct hdmi_edid *pedid)\r
+{\r
+       const struct fb_videomode *mode;\r
+       int count, i, j, vic;\r
+\r
+       count = buf[0] & 0x1F;\r
+       for(i = 0; i < count; i++)\r
+       {\r
+               hdmi_edid_debug("[EDID-CEA] %02x VID %d native %d\n", buf[1 + i], buf[1 + i] & 0x7f, buf[1 + i] >> 7);\r
+               vic = buf[1 + i] & 0x7f;\r
+               for(j = 0; j < ARRAY_SIZE(double_aspect_vic); j++)\r
+               {\r
+                       if(vic == double_aspect_vic[j])\r
+                       {       \r
+                               vic--;\r
+                               break;\r
+                       }\r
+               }\r
+               if(vic)\r
+               {\r
+                       mode = hdmi_vic_to_videomode(vic);\r
+                       if(mode)\r
+                       {       \r
+                               hdmi_add_videomode(mode, &pedid->modelist);\r
+                       }\r
+               }\r
+       }\r
+       return 0;\r
+}\r
+\r
+// Parse CEA Short Audio Descriptor\r
+static int hdmi_edid_parse_cea_sad(unsigned char *buf, struct hdmi_edid *pedid)\r
+{\r
+       int i, count;\r
+       \r
+       count = buf[0] & 0x1F;\r
+       pedid->audio = kmalloc((count/3)*sizeof(struct hdmi_audio), GFP_KERNEL);\r
+       if(pedid->audio == NULL)\r
+               return E_HDMI_EDID_NOMEMORY;\r
+       pedid->audio_num = count/3;\r
+       for(i = 0; i < pedid->audio_num; i++)\r
+       {\r
+               pedid->audio[i].type = (buf[1 + i*3] >> 3) & 0x0F;\r
+               pedid->audio[i].channel = (buf[1 + i*3] & 0x07) + 1;\r
+               pedid->audio[i].rate = buf[1 + i*3 + 1];\r
+               if(pedid->audio[i].type == HDMI_AUDIO_LPCM)//LPCM \r
+               {\r
+                       pedid->audio[i].word_length = buf[1 + i*3 + 2];\r
+               }\r
+//             printk("[EDID-CEA] type %d channel %d rate %d word length %d\n", \r
+//                     pedid->audio[i].type, pedid->audio[i].channel, pedid->audio[i].rate, pedid->audio[i].word_length);\r
+       }\r
+       return E_HDMI_EDID_SUCCESS;\r
+}\r
+// Parse CEA 861 Serial Extension.\r
+static int hdmi_edid_parse_extensions_cea(unsigned char *buf, struct hdmi_edid *pedid)\r
+{\r
+       unsigned int ddc_offset, native_dtd_num, cur_offset = 4;\r
+       unsigned int underscan_support, baseaudio_support;\r
+       unsigned int tag, IEEEOUI = 0;\r
+//     unsigned int supports_ai,  dc_48bit, dc_36bit, dc_30bit, dc_y444;\r
+//     unsigned char vic;\r
+       \r
+       if(buf == NULL)\r
+               return E_HDMI_EDID_PARAM;\r
+               \r
+       // Check ces extension version\r
+       if(buf[1] != 3)\r
+       {\r
+               hdmi_edid_error("[EDID-CEA] error version.\n");\r
+               return E_HDMI_EDID_VERSION;\r
+       }\r
+       \r
+       ddc_offset = buf[2];\r
+       underscan_support = (buf[3] >> 7) & 0x01;\r
+       baseaudio_support = (buf[3] >> 6) & 0x01;\r
+       pedid->ycbcr444 = (buf[3] >> 5) & 0x01;\r
+       pedid->ycbcr422 = (buf[3] >> 4) & 0x01;\r
+       native_dtd_num = buf[3] & 0x0F;\r
+//     hdmi_edid_debug("[EDID-CEA] ddc_offset %d underscan_support %d baseaudio_support %d yuv_support %d native_dtd_num %d\n", ddc_offset, underscan_support, baseaudio_support, yuv_support, native_dtd_num);\r
+       // Parse data block\r
+       while(cur_offset < ddc_offset)\r
+       {\r
+               tag = buf[cur_offset] >> 5;\r
+               switch(tag)\r
+               {\r
+                       case 0x02:      // Video Data Block\r
+                               hdmi_edid_debug("[EDID-CEA] It is a Video Data Block.\n");\r
+                               hdmi_edid_get_cea_svd(buf + cur_offset, pedid);\r
+                               break;\r
+                       case 0x01:      // Audio Data Block\r
+                               hdmi_edid_debug("[EDID-CEA] It is a Audio Data Block.\n");\r
+                               hdmi_edid_parse_cea_sad(buf + cur_offset, pedid);\r
+                               break;\r
+                       case 0x04:      // Speaker Allocation Data Block\r
+                               hdmi_edid_debug("[EDID-CEA] It is a Speaker Allocatio Data Block.\n");\r
+                               break;\r
+                       case 0x03:      // Vendor Specific Data Block\r
+                               hdmi_edid_debug("[EDID-CEA] It is a Vendor Specific Data Block.\n");\r
+\r
+                               IEEEOUI = buf[cur_offset + 2 + 1];\r
+                               IEEEOUI <<= 8;\r
+                               IEEEOUI += buf[cur_offset + 1 + 1];\r
+                               IEEEOUI <<= 8;\r
+                               IEEEOUI += buf[cur_offset + 1];\r
+                               hdmi_edid_debug("[EDID-CEA] IEEEOUI is 0x%08x.\n", IEEEOUI);\r
+                               if(IEEEOUI == 0x0c03)\r
+                                       pedid->sink_hdmi = 1;\r
+//                             if(count > 5)\r
+//                             {\r
+//                                     pedid->deepcolor = (buf[cur_offset + 5] >> 3) & 0x0F;\r
+//                                     supports_ai = buf[cur_offset + 5] >> 7;\r
+//                                     dc_48bit = (buf[cur_offset + 5] >> 6) & 0x1;\r
+//                                     dc_36bit = (buf[cur_offset + 5] >> 5) & 0x1;\r
+//                                     dc_30bit = (buf[cur_offset + 5] >> 4) & 0x1;\r
+//                                     dc_y444 = (buf[cur_offset + 5] >> 3) & 0x1;\r
+//                                     hdmi_edid_debug("[EDID-CEA] supports_ai %d dc_48bit %d dc_36bit %d dc_30bit %d dc_y444 %d \n", supports_ai, dc_48bit, dc_36bit, dc_30bit, dc_y444);\r
+//                             }\r
+//                             if(count > 6)\r
+//                                     pedid->maxtmdsclock = buf[cur_offset + 6] * 5000000;\r
+//                             if(count > 7)\r
+//                             {\r
+//                                     pedid->latency_fields_present = (buf[cur_offset + 7] & 0x80) ? 1:0;\r
+//                                     pedid->i_latency_fields_present = (buf[cur_offset + 7] & 0x40) ? 1:0;\r
+//                             }\r
+//                             if(count > 9 && pedid->latency_fields_present)\r
+//                             {\r
+//                                     pedid->video_latency = buf[cur_offset + 8];\r
+//                                     pedid->audio_latency = buf[cur_offset + 9];\r
+//                             }\r
+//                             if(count > 11 && pedid->i_latency_fields_present)\r
+//                             {\r
+//                                     pedid->interlaced_video_latency = buf[cur_offset + 10];\r
+//                                     pedid->interlaced_audio_latency = buf[cur_offset + 11];\r
+//                             }\r
+                               break;          \r
+                       case 0x05:      // VESA DTC Data Block\r
+                               hdmi_edid_debug("[EDID-CEA] It is a VESA DTC Data Block.\n");\r
+                               break;\r
+                       case 0x07:      // Use Extended Tag\r
+                               hdmi_edid_debug("[EDID-CEA] It is a Use Extended Tag Data Block.\n");\r
+                               break;\r
+                       default:\r
+                               hdmi_edid_error("[EDID-CEA] unkowned data block tag.\n");\r
+                               break;\r
+               }\r
+               cur_offset += (buf[cur_offset] & 0x1F) + 1;\r
+       }\r
+#if 1  \r
+{\r
+       // Parse DTD\r
+       struct fb_videomode *vmode = kmalloc(sizeof(struct fb_videomode), GFP_KERNEL);\r
+       if(vmode == NULL)\r
+               return E_HDMI_EDID_SUCCESS; \r
+       while(ddc_offset < HDMI_EDID_BLOCK_SIZE - 2)    //buf[126] = 0 and buf[127] = checksum\r
+       {\r
+               if(!buf[ddc_offset] && !buf[ddc_offset + 1])\r
+                       break;\r
+               memset(vmode, 0, sizeof(struct fb_videomode));\r
+               hdmi_edid_parse_dtd(buf + ddc_offset, vmode);\r
+               hdmi_add_videomode(vmode, &pedid->modelist);\r
+               ddc_offset += 18;\r
+       }\r
+       kfree(vmode);\r
+}\r
+#endif\r
+       return E_HDMI_EDID_SUCCESS;\r
+}\r
+\r
+static int hdmi_edid_parse_extensions(unsigned char *buf, struct hdmi_edid *pedid)\r
+{\r
+       int rc;\r
+       \r
+       if(buf == NULL || pedid == NULL)\r
+               return E_HDMI_EDID_PARAM;\r
+               \r
+       // Checksum\r
+    rc = hdmi_edid_checksum(buf);\r
+    if( rc != E_HDMI_EDID_SUCCESS)\r
+    {\r
+       hdmi_edid_error("[EDID] extensions block checksum error\n");\r
+       return E_HDMI_EDID_CHECKSUM;\r
+    }\r
+    \r
+    switch(buf[0])\r
+    {\r
+       case 0xF0:\r
+               hdmi_edid_debug("[EDID-EXTEND] It is a extensions block map.\n");\r
+               break;\r
+       case 0x02:\r
+               hdmi_edid_debug("[EDID-EXTEND] It is a  CEA 861 Series Extension.\n");\r
+               hdmi_edid_parse_extensions_cea(buf, pedid);\r
+               break;\r
+       case 0x10:\r
+               hdmi_edid_debug("[EDID-EXTEND] It is a Video Timing Block Extension.\n");\r
+               break;\r
+       case 0x40:\r
+               hdmi_edid_debug("[EDID-EXTEND] It is a Display Information Extension.\n");\r
+               break;\r
+       case 0x50:\r
+               hdmi_edid_debug("[EDID-EXTEND] It is a Localized String Extension.\n");\r
+               break;\r
+       case 0x60:\r
+               hdmi_edid_debug("[EDID-EXTEND] It is a Digital Packet Video Link Extension.\n");\r
+               break;\r
+       default:\r
+               hdmi_edid_debug("[EDID-EXTEND] Unkowned extension.\n");\r
+               break;\r
+    }\r
+    \r
+    return E_HDMI_EDID_SUCCESS;\r
+}\r
+\r
+\r
+int hdmi_sys_parse_edid(struct hdmi* hdmi)\r
+{\r
+       struct hdmi_edid *pedid;\r
+       unsigned char *buff = NULL;\r
+       int rc = HDMI_ERROR_SUCESS, extendblock = 0, i;\r
+       \r
+       if(hdmi == NULL)\r
+               return HDMI_ERROR_FALSE;\r
+\r
+       pedid = &(hdmi->edid);\r
+       memset(pedid, 0, sizeof(struct hdmi_edid));\r
+       INIT_LIST_HEAD(&pedid->modelist);\r
+       \r
+       buff = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);\r
+       if(buff == NULL)\r
+       {               \r
+               hdmi_dbg(hdmi->dev, "[%s] can not allocate memory for edid buff.\n", __FUNCTION__);\r
+               return -1;\r
+       }\r
+       // Read base block edid.\r
+       memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);\r
+       rc = hdmi->read_edid(0, buff);\r
+       if(rc)\r
+       {\r
+               dev_err(hdmi->dev, "[HDMI] read edid base block error\n");\r
+               goto out;\r
+       }\r
+       rc = hdmi_edid_parse_base(buff, &extendblock, pedid);\r
+       if(rc)\r
+       {\r
+               dev_err(hdmi->dev, "[HDMI] parse edid base block error\n");\r
+               goto out;\r
+       }\r
+       for(i = 1; i < extendblock + 1; i++)\r
+       {\r
+               memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);\r
+               rc = hdmi->read_edid(i, buff);\r
+               if(rc)\r
+               {\r
+                       printk("[HDMI] read edid block %d error\n", i); \r
+                       goto out;\r
+               }\r
+               rc = hdmi_edid_parse_extensions(buff, pedid);\r
+               if(rc)\r
+               {\r
+                       dev_err(hdmi->dev, "[HDMI] parse edid block %d error\n", i);\r
+                       continue;\r
+               }\r
+       }\r
+out:\r
+       if(buff)\r
+               kfree(buff);\r
+       rc = hdmi_ouputmode_select(hdmi, rc);\r
+       return rc;\r
+}\r
diff --git a/drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c b/drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c
new file mode 100755 (executable)
index 0000000..da445b9
--- /dev/null
@@ -0,0 +1,526 @@
+#include <linux/console.h>
+#include<linux/rk_fb.h>
+#include "rk_hdmi.h"
+
+#define OUT_TYPE               SCREEN_HDMI
+#define OUT_FACE               OUT_P888
+#define DCLK_POL               1
+#define SWAP_RB                        0
+#define LCD_ACLK               800000000
+
+const struct fb_videomode hdmi_mode [] = {
+       //name                          refresh         xres    yres    pixclock        h_bp    h_fp    v_bp    v_fp    h_pw    v_pw    polariry        PorI    flag(used for vic)
+//{    "640x480p@60Hz",        60,                     640,    480,    25175000,       48,             16,             33,             10,             96,             2,              0,                      0,              1       },
+//{    "720x480i@60Hz",        60,                     720,    480,    27000000,       114,    38,             15,             4,              124,    3,              0,                      1,              6       },
+//{    "720x576i@50Hz",        50,                     720,    576,    27000000,       138,    24,             19,             2,              126,    3,              0,                      1,              21      },
+{      "720x480p@60Hz",        60,                     720,    480,    27000000,       60,             16,             30,             9,              62,             6,              0,                      0,              2       },
+{      "720x576p@50Hz",        50,                     720,    576,    27000000,       68,             12,             39,             5,              64,             5,              0,                      0,              17      },
+//{    "1280x720p@24Hz",       24,                     1280,   720,    59400000,       220,    1760,   20,             5,              40,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              60      },
+//{    "1280x720p@25Hz",       25,                     1280,   720,    74250000,       220,    2420,   20,             5,              40,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              61      },
+//{    "1280x720p@30Hz",       30,                     1280,   720,    74250000,       220,    1760,   20,             5,              40,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              62      },
+{      "1280x720p@50Hz",       50,                     1280,   720,    74250000,       220,    440,    20,             5,              40,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              19      },
+{      "1280x720p@60Hz",       60,                     1280,   720,    74250000,       220,    110,    20,             5,              40,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              4       },
+//{    "1920x1080p@24Hz",      24,                     1920,   1080,   74250000,       148,    638,    36,             4,              44,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              32      },
+//{    "1920x1080p@25Hz",      25,                     1920,   1080,   74250000,       148,    528,    36,             4,              44,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              33      },
+//{    "1920x1080p@30Hz",      30,                     1920,   1080,   74250000,       148,    88,             36,             4,              44,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              34      },      
+//{    "1920x1080i@50Hz_2",50,                 1920,   1080,   72000000,       184,    32,             57,             23,             168,    5,              FB_SYNC_HOR_HIGH_ACT,                   1,              39      },
+//{    "1920x1080i@50Hz",      50,                     1920,   1080,   74250000,       148,    528,    15,             2,              44,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   1,              20      },
+//{    "1920x1080i@60Hz",      60,                     1920,   1080,   74250000,       148,    88,             15,             2,              44,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   1,              5       },
+{      "1920x1080p@50Hz",      50,                     1920,   1080,   148500000,      148,    528,    36,             4,              44,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              31      },
+{      "1920x1080p@60Hz",      60,                     1920,   1080,   148500000,      148,    88,             36,             4,              44,             5,              FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              16      },
+/*
+{      "1440x288p@50Hz",       50,                     720,    480,    27000000,       138,    24,             19,             2,              126,    3,              0,                      0,              23      },
+{      "2880x576i@50Hz",       50,                     1440,   240,    54000000,       276,    48,             19,             2,              252,    3,              0,                      1,              25      },
+{      "2880x288p@50Hz",       50,                     2880,   480,    54000000,       276,    48,             19,             3,              252,    3,              0,                      0,              27      },
+{      "1440x576p@50Hz",       50,                     2880,   480,    54000000,       136,    24,             39,             5,              128,    5,              0,                      0,              29      },
+{      "2880x576p@50Hz",       50,                     1920,   1080,   108000000,      272,    48,             39,             5,              256,    5,              0,                      0,              37      },
+{      "1440x240p@60Hz",       60,                     1440,   240,    27000000,       114,    38,             15,             4,              124,    3,              0,                      0,              8       },
+{      "2880x480i@60Hz",       60,                     2880,   480,    54000000,       228,    76,             15,             4,              248,    3,              0,                      1,              10      },
+{      "2880x480p@60Hz",       60,                     2880,   480,    54000000,       228,    76,             15,             4,              248,    3,              0,                      0,              12      },
+{      "1440x480p@60Hz",       60,                     1440,   480,    54000000,       120,    32,             30,             9,              124,    6,              0,                      0,              14      },
+{      "2880x480p@60Hz",       60,                     2880,   480,    54000000,       240,    64,             30,             9,              248,    6,              0,                      0,              35      },
+
+{      "1920x1080i@100Hz",     100,            1920,   1080,   148500000,      148,    528,    15,             2,              44,             5,              1,                      1,              40      },
+{      "1280x720p@100Hz",      100,            1280,   720,    148500000,      220,    440,    20,             5,              40,             5,              1,                      0,              41      },
+{      "720x576p@100Hz",       100,            720,    576,    54000000,       68,             12,             39,             5,              64,             5,              0,                      0,              42      },
+{      "1440x576i@100Hz",      100,            1440,   576,    54000000,       138,    24,             19,             2,              12,             3,              0,                      1,              44      },
+{      "1920x1080p@100Hz",     100,            1920,   1080,   297000000,      148,    528,    36,             4,              44,             5,              1,                      0,              64      },
+
+{      "1920x1080i@120Hz",     120,            1920,   1080,   148500000,      148,    88,             15,             2,              44,             5,              1,                      1,              46      },
+{      "1280x720p@120Hz",      120,            1280,   720,    148500000,      220,    110,    20,             5,              40,             5,              1,                      0,              47      },
+{      "720x480p@120Hz",       120,            720,    480,    54000000,       60,             16,             30,             9,              62,             6,              0,                      0,              48      },
+{      "1440x480i@120Hz",      120,            1440,   480,    54000000,       114,    38,             15,             4,              12,             3,              0,                      1,              50      },
+{      "1920x1080p@120Hz",     120,            1920,   1080,   297000000,      148,    88,             36,             4,              44,             5,              1,                      0,              63      },
+
+{      "720x576p@200Hz",       200,            720,    576,    108000000,      68,             12,             39,             5,              64,             5,              0,                      0,              52      },
+{      "1440x576i@200Hz",      200,            1920,   1080,   108000000,      138,    24,             19,             2,              12,             3,              0,                      1,              54      },
+
+{      "720x480p@240Hz",       240,            720,    480,    108000000,      60,             16,             30,             9,              62,             6,              0,                      0,              56      },
+{      "1440x480i@240Hz",      240,            1440,   480,    108000000,      114,    38,             15,             4,              12,             3,              0,                      1,              58      },
+*/
+
+};
+
+void hdmi_init_lcdc(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info)
+{
+       hdmi_set_info(screen, HDMI_VIDEO_DEFAULT_MODE);
+}
+
+int hdmi_set_info(struct rk29fb_screen *screen, unsigned int vic)
+{
+    int i;
+    
+    if(screen == NULL)
+       return -1;
+    
+    if(vic == 0)
+       vic = HDMI_VIDEO_DEFAULT_MODE;
+       
+    for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++)
+    {
+       if(hdmi_mode[i].flag == vic)
+               break;
+    }
+    if(i == ARRAY_SIZE(hdmi_mode))
+       return -1;
+    
+    memset(screen, 0, sizeof(struct rk29fb_screen));
+    
+    /* screen type & face */
+    screen->type = OUT_TYPE;
+    screen->face = OUT_FACE;
+
+    /* Screen size */
+    screen->x_res = hdmi_mode[i].xres;
+    screen->y_res = hdmi_mode[i].yres;
+    
+    /* Timing */
+    screen->pixclock = hdmi_mode[i].pixclock;
+       screen->lcdc_aclk = LCD_ACLK;
+       screen->left_margin = hdmi_mode[i].left_margin;
+       screen->right_margin = hdmi_mode[i].right_margin;
+       screen->hsync_len = hdmi_mode[i].hsync_len;
+       screen->upper_margin = hdmi_mode[i].upper_margin;
+       screen->lower_margin = hdmi_mode[i].lower_margin;
+       screen->vsync_len = hdmi_mode[i].vsync_len;
+
+       /* Pin polarity */
+       if(FB_SYNC_HOR_HIGH_ACT & hdmi_mode[i].sync)
+               screen->pin_hsync = 1;
+       else
+               screen->pin_hsync = 0;
+       if(FB_SYNC_VERT_HIGH_ACT & hdmi_mode[i].sync)
+               screen->pin_vsync = 1;
+       else
+               screen->pin_vsync = 0;
+       screen->pin_den = 0;
+       screen->pin_dclk = DCLK_POL;
+
+       /* Swap rule */
+    screen->swap_rb = SWAP_RB;
+    screen->swap_rg = 0;
+    screen->swap_gb = 0;
+    screen->swap_delta = 0;
+    screen->swap_dumy = 0;
+
+    /* Operation function*/
+    screen->init = NULL;
+    screen->standby = NULL;
+    
+    return 0;
+}
+
+static void hdmi_show_sink_info(struct hdmi *hdmi)
+{
+       struct list_head *pos, *head = &hdmi->edid.modelist;
+       struct fb_modelist *modelist;
+       struct fb_videomode *m;
+       int i;
+       struct hdmi_audio *audio;
+
+       hdmi_dbg(hdmi->dev, "******** Show Sink Info ********\n");
+       hdmi_dbg(hdmi->dev, "Support video mode: \n");
+       list_for_each(pos, head) {
+               modelist = list_entry(pos, struct fb_modelist, list);
+               m = &modelist->mode;
+               hdmi_dbg(hdmi->dev, "   %s.\n", m->name);
+       }
+       
+       for(i = 0; i < hdmi->edid.audio_num; i++)
+       {
+               audio = &(hdmi->edid.audio[i]);
+               switch(audio->type)
+               {
+                       case HDMI_AUDIO_LPCM:
+                               hdmi_dbg(hdmi->dev, "Support audio type: LPCM\n");
+                               break;
+                       case HDMI_AUDIO_AC3:
+                               hdmi_dbg(hdmi->dev, "Support audio type: AC3\n");
+                               break;
+                       case HDMI_AUDIO_MPEG1:
+                               hdmi_dbg(hdmi->dev, "Support audio type: MPEG1\n");
+                               break;
+                       case HDMI_AUDIO_MP3:
+                               hdmi_dbg(hdmi->dev, "Support audio type: MP3\n");
+                               break;
+                       case HDMI_AUDIO_MPEG2:
+                               hdmi_dbg(hdmi->dev, "Support audio type: MPEG2\n");
+                               break;
+                       case HDMI_AUDIO_AAC_LC:
+                               hdmi_dbg(hdmi->dev, "Support audio type: AAC\n");
+                               break;
+                       case HDMI_AUDIO_DTS:
+                               hdmi_dbg(hdmi->dev, "Support audio type: DTS\n");
+                               break;
+                       case HDMI_AUDIO_ATARC:
+                               hdmi_dbg(hdmi->dev, "Support audio type: ATARC\n");
+                               break;
+                       case HDMI_AUDIO_DSD:
+                               hdmi_dbg(hdmi->dev, "Support audio type: DSD\n");
+                               break;
+                       case HDMI_AUDIO_E_AC3:
+                               hdmi_dbg(hdmi->dev, "Support audio type: E-AC3\n");
+                               break;
+                       case HDMI_AUDIO_DTS_HD:
+                               hdmi_dbg(hdmi->dev, "Support audio type: DTS-HD\n");
+                               break;
+                       case HDMI_AUDIO_MLP:
+                               hdmi_dbg(hdmi->dev, "Support audio type: MLP\n");
+                               break;
+                       case HDMI_AUDIO_DST:
+                               hdmi_dbg(hdmi->dev, "Support audio type: DST\n");
+                               break;
+                       case HDMI_AUDIO_WMA_PRO:
+                               hdmi_dbg(hdmi->dev, "Support audio type: WMP-PRO\n");
+                               break;
+                       default:
+                               hdmi_dbg(hdmi->dev, "Support audio type: Unkown\n");
+                               break;
+               }
+               
+               hdmi_dbg(hdmi->dev, "Support audio sample rate: \n");
+               if(audio->rate & HDMI_AUDIO_FS_32000)
+                       hdmi_dbg(hdmi->dev, "   32000\n");
+               if(audio->rate & HDMI_AUDIO_FS_44100)
+                       hdmi_dbg(hdmi->dev, "   44100\n");
+               if(audio->rate & HDMI_AUDIO_FS_48000)
+                       hdmi_dbg(hdmi->dev, "   48000\n");
+               if(audio->rate & HDMI_AUDIO_FS_88200)
+                       hdmi_dbg(hdmi->dev, "   88200\n");
+               if(audio->rate & HDMI_AUDIO_FS_96000)
+                       hdmi_dbg(hdmi->dev, "   96000\n");
+               if(audio->rate & HDMI_AUDIO_FS_176400)
+                       hdmi_dbg(hdmi->dev, "   176400\n");
+               if(audio->rate & HDMI_AUDIO_FS_192000)
+                       hdmi_dbg(hdmi->dev, "   192000\n");
+               
+               hdmi_dbg(hdmi->dev, "Support audio word lenght: \n");
+               if(audio->rate & HDMI_AUDIO_WORD_LENGTH_16bit)
+                       hdmi_dbg(hdmi->dev, "   16bit\n");
+               if(audio->rate & HDMI_AUDIO_WORD_LENGTH_20bit)
+                       hdmi_dbg(hdmi->dev, "   20bit\n");
+               if(audio->rate & HDMI_AUDIO_WORD_LENGTH_24bit)
+                       hdmi_dbg(hdmi->dev, "   24bit\n");
+       }
+       hdmi_dbg(hdmi->dev, "******** Show Sink Info ********\n");
+}
+
+/**
+ * hdmi_ouputmode_select - select hdmi transmitter output mode: hdmi or dvi?
+ * @hdmi: handle of hdmi
+ * @edid_ok: get EDID data success or not, HDMI_ERROR_SUCESS means success.
+ */
+int hdmi_ouputmode_select(struct hdmi *hdmi, int edid_ok)
+{
+       struct list_head *head = &hdmi->edid.modelist;
+       struct fb_monspecs      *specs = hdmi->edid.specs;
+       struct fb_videomode *modedb = NULL;
+       int i, pixclock;
+       
+       if(edid_ok != HDMI_ERROR_SUCESS) {
+               dev_err(hdmi->dev, "warning: EDID error, assume sink as HDMI !!!!");
+               hdmi->edid.sink_hdmi = 1;
+       }
+
+       if(edid_ok != HDMI_ERROR_SUCESS) {
+               hdmi->edid.ycbcr444 = 0;
+               hdmi->edid.ycbcr422 = 0;
+               hdmi->autoconfig = HDMI_DISABLE;
+       }
+       if(head->next == head) {
+               dev_info(hdmi->dev, "warning: no CEA video mode parsed from EDID !!!!");
+               // If EDID get error, list all system supported mode.
+               // If output mode is set to DVI and EDID is ok, check
+               // the output timing.
+               
+               if(hdmi->edid.sink_hdmi == 0 && specs && specs->modedb_len) {
+                       /* Get max resolution timing */
+                       modedb = &specs->modedb[0];
+                       for (i = 0; i < specs->modedb_len; i++) {
+                               if(specs->modedb[i].xres > modedb->xres)
+                                       modedb = &specs->modedb[i];
+                               else if(specs->modedb[i].yres > modedb->yres)
+                                       modedb = &specs->modedb[i];
+                       }
+                       // For some monitor, the max pixclock read from EDID is smaller
+                       // than the clock of max resolution mode supported. We fix it.
+                       pixclock = PICOS2KHZ(modedb->pixclock);
+                       pixclock /= 250;
+                       pixclock *= 250;
+                       pixclock *= 1000;
+                       if(pixclock == 148250000)
+                               pixclock = 148500000;
+                       if(pixclock > specs->dclkmax)
+                               specs->dclkmax = pixclock;
+               }
+               
+               for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++) {
+                       if(modedb) {
+                               if( (hdmi_mode[i].pixclock < specs->dclkmin) || 
+                                       (hdmi_mode[i].pixclock > specs->dclkmax) || 
+                                       (hdmi_mode[i].refresh < specs->vfmin) ||
+                                       (hdmi_mode[i].refresh > specs->vfmax) ||
+                                       (hdmi_mode[i].xres > modedb->xres) ||
+                                       (hdmi_mode[i].yres > modedb->yres) )
+                               continue;
+                       }
+                       hdmi_add_videomode(&hdmi_mode[i], head);
+               }
+       }
+       
+       #ifdef HDMI_DEBUG
+       hdmi_show_sink_info(hdmi);
+       #endif
+       return HDMI_ERROR_SUCESS;
+}
+/**
+ * hdmi_videomode_compare - compare 2 videomodes
+ * @mode1: first videomode
+ * @mode2: second videomode
+ *
+ * RETURNS:
+ * 1 if mode1 > mode2, 0 if mode1 = mode2, -1 mode1 < mode2
+ */
+static int hdmi_videomode_compare(const struct fb_videomode *mode1,
+                    const struct fb_videomode *mode2)
+{
+       if(mode1->xres > mode2->xres)
+               return 1;
+       else if(mode1->xres == mode2->xres)
+       { 
+               if(mode1->yres > mode2->yres)
+                       return 1;
+               else if(mode1->yres == mode2->yres)
+               {
+                       if(mode1->pixclock > mode2->pixclock)   
+                               return 1;
+                       else if(mode1->pixclock == mode2->pixclock)
+                       {       
+                               if(mode1->refresh > mode2->refresh)
+                                       return 1;
+                               else if(mode1->refresh == mode2->refresh) 
+                                       return 0;
+                       }
+               }
+       }
+       return -1;              
+}
+/**
+ * hdmi_add_videomode: adds videomode entry to modelist
+ * @mode: videomode to add
+ * @head: struct list_head of modelist
+ *
+ * NOTES:
+ * Will only add unmatched mode entries
+ */
+int hdmi_add_videomode(const struct fb_videomode *mode, struct list_head *head)
+{
+       struct list_head *pos;
+       struct fb_modelist *modelist, *modelist_new;
+       struct fb_videomode *m;
+       int i, found = 0;
+
+       for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++)
+    {
+       m =(struct fb_videomode*) &hdmi_mode[i];
+       if (fb_mode_is_equal(m, mode)) {
+                       found = 1;
+                       break;
+               }
+    }
+
+       if (found) {
+               list_for_each(pos, head) {
+                       modelist = list_entry(pos, struct fb_modelist, list);
+                       m = &modelist->mode;
+                       if (fb_mode_is_equal(m, mode)) {
+                       // m == mode    
+                               return 0;
+                       }
+                       else
+                       { 
+                               if(hdmi_videomode_compare(m, mode) == -1) {
+                                       break;
+                               }
+                       }
+               }
+
+               modelist_new = kmalloc(sizeof(struct fb_modelist),
+                                 GFP_KERNEL);                                  
+               if (!modelist_new)
+                       return -ENOMEM; 
+               modelist_new->mode = hdmi_mode[i];
+               list_add_tail(&modelist_new->list, pos);
+       }
+       
+       return 0;
+}
+
+/**
+ * hdmi_videomode_to_vic: transverse video mode to vic
+ * @vmode: videomode to transverse
+ * 
+ */
+int hdmi_videomode_to_vic(struct fb_videomode *vmode)
+{
+       unsigned char vic = 0;
+       int i = 0;
+       
+       for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++)
+       {
+               if(     vmode->vmode == hdmi_mode[i].vmode &&
+                       vmode->refresh == hdmi_mode[i].refresh &&
+                       vmode->xres == hdmi_mode[i].xres && 
+                       vmode->left_margin == hdmi_mode[i].left_margin &&
+                       vmode->right_margin == hdmi_mode[i].right_margin &&
+                       vmode->upper_margin == hdmi_mode[i].upper_margin &&
+                       vmode->lower_margin == hdmi_mode[i].lower_margin && 
+                       vmode->hsync_len == hdmi_mode[i].hsync_len && 
+                       vmode->vsync_len == hdmi_mode[i].vsync_len)
+               {
+                       if( (vmode->vmode == FB_VMODE_NONINTERLACED && vmode->yres == hdmi_mode[i].yres) || 
+                               (vmode->vmode == FB_VMODE_INTERLACED && vmode->yres == hdmi_mode[i].yres/2))
+                       {                                                               
+                               vic = hdmi_mode[i].flag;
+                               break;
+                       }
+               }
+       }
+       return vic;
+}
+
+/**
+ * hdmi_vic_to_videomode: transverse vic mode to video mode
+ * @vmode: vic to transverse
+ * 
+ */
+const struct fb_videomode* hdmi_vic_to_videomode(int vic)
+{
+       int i;
+       
+       if(vic == 0)
+               return NULL;
+       
+       for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++)
+       {
+               if(hdmi_mode[i].flag == vic)
+                       return &hdmi_mode[i];
+       }
+       return NULL;
+}
+
+/**
+ * hdmi_find_best_mode: find the video mode nearest to input vic
+ * @hdmi: 
+ * @vic: input vic
+ * 
+ * NOTES:
+ * If vic is zero, return the high resolution video mode vic.
+ */
+int hdmi_find_best_mode(struct hdmi* hdmi, int vic)
+{
+       struct list_head *pos, *head = &hdmi->edid.modelist;
+       struct fb_modelist *modelist;
+       struct fb_videomode *m = NULL;
+       int found = 0;
+       
+       if(vic)
+       {
+               list_for_each(pos, head) {
+                       modelist = list_entry(pos, struct fb_modelist, list);
+                       m = &modelist->mode;
+                       if(m->flag == vic)
+                       {
+                               found = 1;      
+                               break;
+                       }
+               }
+       }
+       if( (vic == 0 || found == 0) && head->next != head)
+       {
+               modelist = list_entry(head->next, struct fb_modelist, list);
+               m = &modelist->mode;
+       }
+       if(m != NULL)
+               return m->flag;
+       else
+               return 0;
+}
+
+const char *hdmi_get_video_mode_name(unsigned char vic)
+{
+       int i;
+       
+       for(i = 0; i < ARRAY_SIZE(hdmi_mode); i++)
+       {
+               if(vic == hdmi_mode[i].flag)
+                       break;
+       }
+       if(i == ARRAY_SIZE(hdmi_mode))
+               return NULL;
+       else
+               return hdmi_mode[i].name;
+}
+
+/**
+ * hdmi_switch_fb: switch lcdc mode to required video mode
+ * @hdmi: 
+ * @type:
+ * 
+ * NOTES:
+ * 
+ */
+int hdmi_switch_fb(struct hdmi *hdmi, int vic)
+{
+       int rc = 0;
+
+       if(hdmi->vic == 0)
+               hdmi->vic = HDMI_VIDEO_DEFAULT_MODE;
+               
+       if(hdmi->lcdc == NULL || hdmi->lcdc->screen == NULL) {
+               dev_err(hdmi->dev, "lcdc %d not exist\n", HDMI_SOURCE_DEFAULT);
+               return -1;
+       }
+
+       rc = hdmi_set_info(hdmi->lcdc->screen, hdmi->vic);
+
+       if(rc == 0) {           
+               rk_fb_switch_screen(hdmi->lcdc->screen, 1, HDMI_SOURCE_DEFAULT);
+               rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, HDMI_SOURCE_DEFAULT);
+       }
+       return rc;
+}
+
+/**
+ * hdmi_get_status: get hdmi hotplug status
+ * 
+ * NOTES:
+ * 
+ */
+int hdmi_get_hotplug(void)
+{
+       if(hdmi)
+               return hdmi->hotplug;
+       else
+               return HDMI_HPD_REMOVED;
+}
diff --git a/drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c b/drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c
new file mode 100755 (executable)
index 0000000..45d28ee
--- /dev/null
@@ -0,0 +1,177 @@
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/display-sys.h>
+#include <linux/interrupt.h>
+#include "rk_hdmi.h"
+
+static int hdmi_get_enable(struct rk_display_device *device)
+{
+       struct hdmi *hdmi = device->priv_data;
+       int enable;
+       
+       mutex_lock(&hdmi->enable_mutex);
+       enable = hdmi->enable;
+       mutex_unlock(&hdmi->enable_mutex);
+       
+       return enable;
+}
+
+static int hdmi_set_enable(struct rk_display_device *device, int enable)
+{
+       struct hdmi *hdmi = device->priv_data;
+       
+       mutex_lock(&hdmi->enable_mutex);
+       if(hdmi->enable == enable) {
+               mutex_unlock(&hdmi->enable_mutex);
+               return 0;
+       }
+       hdmi->enable = enable;
+       
+       if(hdmi->suspend ) {
+               mutex_unlock(&hdmi->enable_mutex);
+               return 0;
+       }
+       
+       if(enable == 0) {
+               disable_irq(hdmi->irq);
+               mutex_unlock(&hdmi->enable_mutex);
+               hdmi->command = HDMI_CONFIG_ENABLE;
+               queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
+       }
+       else {
+               enable_irq(hdmi->irq);
+               mutex_unlock(&hdmi->enable_mutex);
+       }
+       return 0;
+}
+
+static int hdmi_get_status(struct rk_display_device *device)
+{
+       struct hdmi *hdmi = device->priv_data;
+       if(hdmi->hotplug == HDMI_HPD_ACTIVED)
+               return 1;
+       else
+               return 0;
+}
+
+static int hdmi_get_modelist(struct rk_display_device *device, struct list_head **modelist)
+{
+       struct hdmi *hdmi = device->priv_data;
+       if(!hdmi->hotplug)
+               return -1;
+       *modelist = &hdmi->edid.modelist;
+       return 0;
+}
+
+static int hdmi_set_mode(struct rk_display_device *device, struct fb_videomode *mode)
+{
+       struct hdmi *hdmi = device->priv_data;
+       int vic = hdmi_videomode_to_vic(mode);
+       
+       if(!hdmi->hotplug)
+               return -1;
+       hdmi->autoconfig = HDMI_DISABLE;
+       if(vic && hdmi->vic != vic)
+       {
+               hdmi->vic = vic;
+               hdmi->command = HDMI_CONFIG_VIDEO;
+               init_completion(&hdmi->complete);
+               hdmi->wait = 1;
+               queue_delayed_work(hdmi->workqueue, &hdmi->delay_work, 0);
+               wait_for_completion_interruptible_timeout(&hdmi->complete,
+                                                               msecs_to_jiffies(10000));
+       }
+       return 0;
+}
+
+static int hdmi_get_mode(struct rk_display_device *device, struct fb_videomode *mode)
+{
+       struct hdmi *hdmi = device->priv_data;
+       struct fb_videomode *vmode;
+       
+       if(!hdmi->hotplug)
+               return -1;
+               
+       vmode = (struct fb_videomode*) hdmi_vic_to_videomode(hdmi->vic);
+       if(unlikely(vmode == NULL))
+               return -1;
+       *mode = *vmode;
+       return 0;
+}
+
+static int hdmi_set_scale(struct rk_display_device *device, int direction, int value)
+{
+       struct hdmi *hdmi = device->priv_data;
+       
+       if(!hdmi || value < 0 || value > 100)
+               return -1;
+                       
+       if(direction == DISPLAY_SCALE_X)
+               hdmi->xscale = value;
+       else if(direction == DISPLAY_SCALE_Y)
+               hdmi->yscale = value;
+       else
+               return -1;
+       rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, HDMI_SOURCE_DEFAULT);
+       return 0;
+}
+
+static int hdmi_get_scale(struct rk_display_device *device, int direction)
+{
+       struct hdmi *hdmi = device->priv_data;
+       
+       if(!hdmi)
+               return -1;
+               
+       if(direction == DISPLAY_SCALE_X)
+               return hdmi->xscale;
+       else if(direction == DISPLAY_SCALE_Y)
+               return hdmi->yscale;
+       else
+               return -1;
+}
+
+struct rk_display_ops hdmi_display_ops = {
+       .setenable = hdmi_set_enable,
+       .getenable = hdmi_get_enable,
+       .getstatus = hdmi_get_status,
+       .getmodelist = hdmi_get_modelist,
+       .setmode = hdmi_set_mode,
+       .getmode = hdmi_get_mode,
+       .setscale = hdmi_set_scale,
+       .getscale = hdmi_get_scale,
+};
+
+#if 1
+static int hdmi_display_probe(struct rk_display_device *device, void *devdata)
+{
+       device->owner = THIS_MODULE;
+       strcpy(device->type, "HDMI");
+       device->priority = DISPLAY_PRIORITY_HDMI;
+//     device->name = kmalloc(strlen(name), GFP_KERNEL);
+//     if(device->name)
+//     {
+//             strcpy(device->name, name);
+//     }
+       device->priv_data = devdata;
+       device->ops = &hdmi_display_ops;
+       return 1;
+}
+
+static struct rk_display_driver display_hdmi = {
+       .probe = hdmi_display_probe,
+};
+
+static struct rk_display_device *display_device_hdmi = NULL;
+
+void hdmi_register_display_sysfs(struct hdmi *hdmi, struct device *parent)
+{
+       display_device_hdmi = rk_display_device_register(&display_hdmi, parent, hdmi);
+}
+
+void hdmi_unregister_display_sysfs(struct hdmi *hdmi)
+{
+       if(display_device_hdmi)
+               rk_display_device_unregister(display_device_hdmi);
+}
+#endif
diff --git a/drivers/video/rockchip/hdmi/rk_hdmi_task.c b/drivers/video/rockchip/hdmi/rk_hdmi_task.c
new file mode 100755 (executable)
index 0000000..233d175
--- /dev/null
@@ -0,0 +1,312 @@
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include "rk_hdmi.h"
+
+#ifdef CONFIG_HDMI_RK30_CTL_CODEC
+extern void codec_set_spk(bool on);
+#endif
+
+#define HDMI_MAX_TRY_TIMES     1
+#define HDMI_MAX_ID 1
+
+static char *envp[] = {"INTERFACE=HDMI", NULL};
+
+static void hdmi_sys_show_state(int state)
+{
+       switch(state)
+       {
+               case HDMI_SLEEP:
+                       dev_printk(KERN_INFO, hdmi->dev, "HDMI_SLEEP\n");
+                       break;
+               case HDMI_INITIAL:
+                       dev_printk(KERN_INFO, hdmi->dev, "HDMI_INITIAL\n");
+                       break;
+               case WAIT_HOTPLUG:
+                       dev_printk(KERN_INFO, hdmi->dev, "WAIT_HOTPLUG\n");
+                       break;
+               case READ_PARSE_EDID:
+                       dev_printk(KERN_INFO, hdmi->dev, "READ_PARSE_EDID\n");
+                       break;
+               case WAIT_HDMI_ENABLE:
+                       dev_printk(KERN_INFO, hdmi->dev, "WAIT_HDMI_ENABLE\n");
+                       break;
+               case SYSTEM_CONFIG:
+                       dev_printk(KERN_INFO, hdmi->dev, "SYSTEM_CONFIG\n");
+                       break;
+               case CONFIG_VIDEO:
+                       dev_printk(KERN_INFO, hdmi->dev, "CONFIG_VIDEO\n");
+                       break;
+               case CONFIG_AUDIO:
+                       dev_printk(KERN_INFO, hdmi->dev, "CONFIG_AUDIO\n");
+                       break;
+               case PLAY_BACK:
+                       dev_printk(KERN_INFO, hdmi->dev, "PLAY_BACK\n");
+                       break;
+               default:
+                       dev_printk(KERN_INFO, hdmi->dev, "Unkown State %d\n", state);
+                       break;
+       }
+}
+
+int hdmi_sys_init(void)
+{
+       hdmi->hotplug                   = HDMI_HPD_REMOVED;
+       hdmi->state                             = HDMI_SLEEP;
+       hdmi->enable                    = HDMI_ENABLE;
+       hdmi->autoconfig                = HDMI_AUTO_CONFIGURE;
+       hdmi->display                   = HDMI_DISABLE;
+       
+       hdmi->vic                               = HDMI_VIDEO_DEFAULT_MODE;
+       hdmi->audio.channel     = HDMI_AUDIO_DEFAULT_CHANNEL;
+       hdmi->audio.rate                = HDMI_AUDIO_DEFAULT_RATE;
+       hdmi->audio.word_length = HDMI_AUDIO_DEFAULT_WORD_LENGTH;
+       
+       memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
+       INIT_LIST_HEAD(&hdmi->edid.modelist);
+       return 0;
+}
+
+void hdmi_sys_remove(void)
+{
+       fb_destroy_modelist(&hdmi->edid.modelist);
+       if(hdmi->edid.audio)
+               kfree(hdmi->edid.audio);
+       if(hdmi->edid.specs)
+       {
+               if(hdmi->edid.specs->modedb)
+                       kfree(hdmi->edid.specs->modedb);
+               kfree(hdmi->edid.specs);
+       }
+       memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
+       INIT_LIST_HEAD(&hdmi->edid.modelist);
+       hdmi->display   = HDMI_DISABLE;
+       rk_fb_switch_screen(hdmi->lcdc->screen, 0, HDMI_SOURCE_DEFAULT);
+       kobject_uevent_env(&hdmi->dev->kobj, KOBJ_REMOVE, envp);
+       #ifdef CONFIG_SWITCH
+       switch_set_state(&(hdmi->switch_hdmi), 0);
+       #endif
+       #ifdef CONFIG_HDMI_RK30_CTL_CODEC
+       codec_set_spk(1);
+       #endif
+}
+
+static void hdmi_sys_sleep(void)
+{
+       mutex_lock(&hdmi->enable_mutex);
+       if(hdmi->enable)
+               disable_irq(hdmi->irq);                         
+       hdmi->state = HDMI_SLEEP;
+       hdmi->hdmi_removed();
+       if(hdmi->enable)
+               enable_irq(hdmi->irq);
+       mutex_unlock(&hdmi->enable_mutex);
+}
+
+static int hdmi_process_command(void)
+{
+       int change, state = hdmi->state;
+       
+       change = hdmi->command;
+       if(change != HDMI_CONFIG_NONE)  
+       {               
+               hdmi->command = HDMI_CONFIG_NONE;
+               switch(change)
+               {       
+                       case HDMI_CONFIG_ENABLE:
+                               /* disable HDMI */
+                               mutex_lock(&hdmi->enable_mutex);
+                               if(!hdmi->enable || hdmi->suspend)
+                               {
+                                       if(hdmi->hotplug == HDMI_HPD_ACTIVED)
+                                               hdmi_sys_remove();
+                                       hdmi->state = HDMI_SLEEP;
+                                       hdmi->hotplug = HDMI_HPD_REMOVED;
+                                       hdmi->hdmi_removed();
+                                       state = HDMI_SLEEP;
+                               }
+                               mutex_unlock(&hdmi->enable_mutex);
+                               if(hdmi->wait == 1) {
+                                       complete(&hdmi->complete);
+                                       hdmi->wait = 0; 
+                               }
+                               break;  
+                       case HDMI_CONFIG_COLOR:
+                               if(state > CONFIG_VIDEO)
+                                       state = CONFIG_VIDEO;   
+                               break;
+                       case HDMI_CONFIG_HDCP:
+                               break;
+                       case HDMI_CONFIG_DISPLAY:
+                               break;
+                       case HDMI_CONFIG_AUDIO:
+                               if(state > CONFIG_AUDIO)
+                                       state = CONFIG_AUDIO;
+                               break;
+                       case HDMI_CONFIG_VIDEO:
+                       default:
+                               if(state > SYSTEM_CONFIG)
+                                       state = SYSTEM_CONFIG;
+                               else
+                               {
+                                       if(hdmi->wait == 1) {
+                                               complete(&hdmi->complete);
+                                               hdmi->wait = 0; 
+                                       }                                       
+                               }
+                               break;
+               }
+       }
+       else if(state == HDMI_SLEEP)
+               state = WAIT_HOTPLUG;
+       return state;
+}
+
+static DEFINE_MUTEX(work_mutex);
+
+void hdmi_work(struct work_struct *work)
+{
+       int hotplug, state_last;
+       int rc = HDMI_ERROR_SUCESS, trytimes = 0;
+       struct hdmi_video_para video;
+       
+       mutex_lock(&work_mutex);
+       /* Process hdmi command */
+       hdmi->state = hdmi_process_command();
+       
+       if(!hdmi->enable || hdmi->suspend) {
+               mutex_unlock(&work_mutex);
+               return;
+       }
+       hotplug = hdmi->detect_hotplug();
+       hdmi_dbg(hdmi->dev, "[%s] hotplug %02x curvalue %d\n", __FUNCTION__, hotplug, hdmi->hotplug);
+       
+       if(hotplug != hdmi->hotplug)
+       {
+               if(hotplug  == HDMI_HPD_ACTIVED){
+                       hdmi->state = READ_PARSE_EDID;
+               }
+               else if(hdmi->hotplug == HDMI_HPD_ACTIVED) {
+                       hdmi_sys_remove();
+                       hdmi->hotplug = hotplug;
+                       if(hotplug == HDMI_HPD_REMOVED)
+                               hdmi_sys_sleep();
+                       else {
+                               hdmi->state = WAIT_HOTPLUG;
+                               hdmi->hdmi_removed();
+                       }
+                       if(hdmi->wait == 1) {
+                               complete(&hdmi->complete);
+                               hdmi->wait = 0; 
+                       }
+                       mutex_unlock(&work_mutex);
+                       return;
+               }
+               else if(hotplug == HDMI_HPD_REMOVED) {
+                       hdmi->state = HDMI_SLEEP;
+                       hdmi->hdmi_removed();
+               }
+               hdmi->hotplug  = hotplug;
+       }
+       else if(hotplug == HDMI_HPD_REMOVED)
+               hdmi_sys_sleep();
+       
+       do {
+               hdmi_sys_show_state(hdmi->state);
+               state_last = hdmi->state;
+               switch(hdmi->state)
+               {
+                       case READ_PARSE_EDID:
+                               rc = hdmi_sys_parse_edid(hdmi);
+                               if(rc == HDMI_ERROR_SUCESS)
+                               {
+                                       hdmi->state = SYSTEM_CONFIG;    
+                                       kobject_uevent_env(&hdmi->dev->kobj, KOBJ_ADD, envp);
+                                       #ifdef CONFIG_SWITCH
+                                       switch_set_state(&(hdmi->switch_hdmi), 1);
+                                       #endif
+                                       #ifdef CONFIG_HDMI_RK30_CTL_CODEC
+                                       codec_set_spk(0);
+                                       #endif
+                               }
+                               break;
+                       case SYSTEM_CONFIG:
+                               if(hdmi->autoconfig)    
+                                       hdmi->vic = hdmi_find_best_mode(hdmi, 0);
+                               else
+                                       hdmi->vic = hdmi_find_best_mode(hdmi, hdmi->vic);
+                               rc = hdmi_switch_fb(hdmi, hdmi->vic);
+                               if(rc == HDMI_ERROR_SUCESS)
+                                       hdmi->state = CONFIG_VIDEO;
+                               break;
+                       case CONFIG_VIDEO:
+                               hdmi->display = HDMI_DISABLE;
+                               video.vic = hdmi->vic;
+                               video.input_mode = VIDEO_INPUT_RGB_YCBCR_444;
+                               video.input_color = VIDEO_INPUT_COLOR_RGB;//VIDEO_INPUT_COLOR_YCBCR
+                               video.output_mode = hdmi->edid.sink_hdmi;
+                               
+                               if(hdmi->edid.ycbcr444)
+                                       video.output_color = VIDEO_OUTPUT_YCBCR444;
+                               else if(hdmi->edid.ycbcr422)
+                                       video.output_color = VIDEO_OUTPUT_YCBCR422;
+                               else
+                                       video.output_color = VIDEO_OUTPUT_RGB444;
+                               // For DVI, output RGB
+                               if(hdmi->edid.sink_hdmi == 0)
+                                       video.output_color = VIDEO_OUTPUT_RGB444;
+                               
+                               rc = hdmi->config_video(&video);
+                               if(rc == HDMI_ERROR_SUCESS)
+                               {
+                                       if(hdmi->edid.sink_hdmi)
+                                               hdmi->state = CONFIG_AUDIO;
+                                       else
+                                               hdmi->state = PLAY_BACK;
+                               }
+                               break;
+                       case CONFIG_AUDIO:
+                               rc = hdmi->config_audio(&(hdmi->audio));
+                                                       
+                               if(rc == HDMI_ERROR_SUCESS)
+                                       hdmi->state = PLAY_BACK;
+                               break;
+                       case PLAY_BACK:
+                               if(hdmi->display != HDMI_ENABLE) {
+                                       hdmi->control_output(HDMI_ENABLE);
+                                       hdmi->display = HDMI_ENABLE;
+                                       if(hdmi->hdcp_cb) {
+                                               hdmi->hdcp_cb();
+                                       }
+                               }
+                               
+                               if(hdmi->wait == 1) {   
+                                       complete(&hdmi->complete);
+                                       hdmi->wait = 0;                                         
+                               }
+                               break;
+                       default:
+                               break;
+               }
+               if(rc != HDMI_ERROR_SUCESS)
+               {
+                       trytimes++;
+                       msleep(10);
+               }
+               if(hdmi->state != state_last) 
+                       trytimes = 0;
+       
+       }while((hdmi->state != state_last || (rc != HDMI_ERROR_SUCESS) ) && trytimes < HDMI_MAX_TRY_TIMES);
+       
+//     if(trytimes == HDMI_MAX_TRY_TIMES)
+//     {
+//             if(hdmi->hotplug) {
+//                     hdmi_sys_remove();
+//                     hdmi->hotplug = HDMI_HPD_REMOVED;
+//                     hdmi_sys_sleep();
+//
+//             }
+//     }
+       hdmi_dbg(hdmi->dev, "[%s] done\n", __FUNCTION__);
+       mutex_unlock(&work_mutex);
+}
+