rk30/rk2928 hdmi:
authorZheng Yang <zhengyang@rock-chips.com>
Tue, 4 Sep 2012 07:08:21 +0000 (15:08 +0800)
committerZheng Yang <zhengyang@rock-chips.com>
Tue, 4 Sep 2012 07:08:21 +0000 (15:08 +0800)
1. Fix memory leek bug at hdmi_switch_fb().
2. Add 100ms delay when read edid failed.
3. Delete unused code.
4. rk2928 hdmi support hdcp.

22 files changed:
drivers/video/rockchip/hdmi/Kconfig
drivers/video/rockchip/hdmi/chips/Kconfig
drivers/video/rockchip/hdmi/chips/rk2928/Kconfig
drivers/video/rockchip/hdmi/chips/rk2928/Makefile
drivers/video/rockchip/hdmi/chips/rk2928/hdcp/Kconfig [deleted file]
drivers/video/rockchip/hdmi/chips/rk2928/hdcp/Makefile [deleted file]
drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdcp.c [deleted file]
drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdmi_hdcp.c [deleted file]
drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdmi_hdcp.h [deleted file]
drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdcp.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdcp.h [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi.h
drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hdcp.c [new file with mode: 0755]
drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hw.c
drivers/video/rockchip/hdmi/chips/rk30/Kconfig
drivers/video/rockchip/hdmi/chips/rk30/Makefile
drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi.h
drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi_hw.c
drivers/video/rockchip/hdmi/rk_hdmi.h
drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c
drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c
drivers/video/rockchip/hdmi/rk_hdmi_task.c

index e3700bbd817d45c7525b7d150ac9529a83fa3147..144b9a51981f36ae6a9524c5e5220b88ab68dac5 100755 (executable)
@@ -1,9 +1,22 @@
-menu "RK_HDMI"
-config RK_HDMI
-       bool "RK_HDMI support"
+menuconfig RK_HDMI
+       bool "Rockchip HDMI support"
+       select FB_MODE_HELPERS
        
 if RK_HDMI
 source "drivers/video/rockchip/hdmi/chips/Kconfig"
 endif
 
-endmenu
+config RK_HDMI_DEBUG
+               bool "Rockchip HDMI Debugging"
+        depends on RK_HDMI
+        default n
+               help
+                 Enableds verbose debugging the the HDMI drivers
+
+config RK_HDMI_CTL_CODEC
+               bool "Mute Codec When HDMI Actived"
+               depends on RK_HDMI
+               default n
+               help
+                       If you say y heres, Codec will be mute when hdmi inserted,
+                       and unmute when removed. 
index e0c1c271bdc18ef67091b7da72f12bbc4a0043aa..c01155675dccdd1bc920f17b366432d9a2b8ccef 100755 (executable)
@@ -3,13 +3,11 @@ choice
 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
index 8b137891791fe96927ad78e64b0aad7bded08bdc..49a9cbf6501333ec7af5ef069db2a3bef9546116 100755 (executable)
@@ -1 +1,14 @@
+config HDCP_RK2928
+       bool "RK2928 HDCP support"
+        depends on HDMI_RK2928
+        default n
+       help
+         HDCP Interface. This adds the High Definition Content Protection Interface.
+         See http://www.digital-cp.com/ for HDCP specification.
 
+config HDCP_RK2928_DEBUG
+       bool "RK2928 HDCP Debugging"
+        depends on HDCP_RK2928
+        default n
+       help
+         Enableds verbose debugging the the HDCP drivers
index d3227c7f27d9f49127a2ebd1be4d797f048ee23f..1e17c7641c67b25fdc7ea04c8c657e80c503d191 100755 (executable)
@@ -2,7 +2,8 @@
 # Makefile for HDMI linux kernel module.
 #
 
-ccflags-$(CONFIG_HDMI_RK30_DEBUG) = -DDEBUG -DHDMI_DEBUG
+ccflags-$(CONFIG_RK_HDMI_DEBUG) = -DDEBUG -DHDMI_DEBUG
+ccflags-$(CONFIG_HDCP_RK2928_DEBUG) = -DHDCP_DEBUG
 
-obj-y += rk2928_hdmi_hw.o rk2928_hdmi.o
-obj-$(CONFIG_HDCP_RK2928) += hdcp/
+obj-$(CONFIG_HDMI_RK2928) += rk2928_hdmi_hw.o rk2928_hdmi.o
+obj-$(CONFIG_HDCP_RK2928) += rk2928_hdmi_hdcp.o rk2928_hdcp.o
diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/Kconfig b/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/Kconfig
deleted file mode 100755 (executable)
index 1bb3c3a..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-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
deleted file mode 100755 (executable)
index 108b67c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# 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
deleted file mode 100755 (executable)
index 68d0ac8..0000000
+++ /dev/null
@@ -1,570 +0,0 @@
-#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
deleted file mode 100755 (executable)
index 1184989..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-#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
deleted file mode 100755 (executable)
index 0224d88..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-#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_hdcp.c b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdcp.c
new file mode 100755 (executable)
index 0000000..25ff532
--- /dev/null
@@ -0,0 +1,563 @@
+#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 "rk2928_hdmi.h"
+#include "rk2928_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;
+       }
+
+       rk2928_hdcp_disable();
+       rk2928_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 = rk2928_hdcp_start_authentication();
+
+       if (status != HDCP_OK) {
+               DBG("HDCP: authentication failed");
+               hdcp_wq_authentication_failure();
+       } else {
+               hdcp->hdcp_state = HDCP_WAIT_KSV_LIST;
+//             hdcp->hdcp_state = HDCP_LINK_INTEGRITY_CHECK;
+       }
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_check_bksv
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_check_bksv(void)
+{
+       int status = HDCP_OK;
+
+       DBG("Check BKSV start");
+       
+       status = rk2928_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)
+{
+       rk2928_hdmi_control_output(true);
+       printk(KERN_INFO "HDCP: authentication pass");
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_wq_disable
+ *-----------------------------------------------------------------------------
+ */
+static void hdcp_wq_disable(int event)
+{
+       printk(KERN_INFO "HDCP: disabled");
+
+       hdcp_cancel_work(&hdcp->pending_wq_event);
+       rk2928_hdcp_disable();
+       if(event == HDCP_DISABLE_CTL) {
+               hdcp->hdcp_state = HDCP_DISABLED;
+               if(hdcp->hdmi_state == HDMI_STARTED)
+                       rk2928_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 status)
+{
+       char interrupt1;
+       char interrupt2;
+       
+       rk2928_hdcp_interrupt(&interrupt1, &interrupt2);
+       DBG("%s 0x%02x 0x%02x", __FUNCTION__, interrupt1, interrupt2);
+       if(interrupt1 & m_INT_HDCP_ERR)
+       {
+               if( (hdcp->hdcp_state != HDCP_DISABLED) &&
+                       (hdcp->hdcp_state != HDCP_ENABLE_PENDING) )
+               {       
+                       hdcp_submit_work(HDCP_FAIL_EVENT, 0);
+               }
+       }
+       else if(interrupt1 & (m_INT_BKSV_READY | m_INT_BKSV_UPDATE))
+               hdcp_submit_work(HDCP_KSV_LIST_RDY_EVENT, 0);
+       else if(interrupt1 & m_INT_AUTH_SUCCESS)
+               hdcp_submit_work(HDCP_AUTH_PASS_EVENT, 0);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: hdcp_power_on_cb
+ *-----------------------------------------------------------------------------
+ */
+static int hdcp_power_on_cb(void)
+{
+       DBG("%s", __FUNCTION__);
+//     return rk2928_hdcp_load_key2mem(hdcp->keys);
+       return HDCP_OK;
+}
+
+/*-----------------------------------------------------------------------------
+ * 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(5000));
+}
+
+// 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);
+       
+       printk(KERN_INFO "HDCP: load 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 rk2928_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;
+       }
+       
+       rk2928_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 rk2928_hdcp_exit(void)
+{
+       device_remove_file(mdev.this_device, &dev_attr_enable);
+       misc_deregister(&mdev);
+       if(hdcp->keys)
+               kfree(hdcp->keys);
+       if(hdcp->invalidkeys)
+               kfree(hdcp->invalidkeys);
+       kfree(hdcp);
+}
+
+module_init(rk2928_hdcp_init);
+module_exit(rk2928_hdcp_exit);
diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdcp.h b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdcp.h
new file mode 100755 (executable)
index 0000000..4d55037
--- /dev/null
@@ -0,0 +1,190 @@
+#ifndef __RK2928_HDCP_H__
+#define __RK2928_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     
+
+/* HDCP DDC Clock */
+#define HDCP_DDC_CLK                   100000
+
+/* Authentication retry times */
+#define HDCP_INFINITE_REAUTH   0x100
+
+/* HDCP Regs */
+#define HDCP_CTRL1                             0x52
+       #define m_AUTH_START            (1 << 7)
+       #define m_BKSV_VALID            (1 << 6)
+       #define m_BKSV_INVALID          (1 << 5)
+       #define m_ENCRYPT_ENABLE        (1 << 4)
+       #define m_AUTH_STOP                     (1 << 3)
+       #define m_ADVANED_ENABLE        (1 << 2)
+       #define m_HDMI_DVI                      (1 << 1)
+       #define m_HDCP_RESET            (1 << 0)
+       
+       #define v_AUTH_START(n)         (n << 7)
+       #define v_BKSV_VALID(n)         (n << 6)
+       #define v_BKSV_INVALID(n)       (n << 5)
+       #define v_ENCRYPT_ENABLE(n)     (n << 4)
+       #define v_AUTH_STOP(n)          (n << 3)
+       #define v_ADVANED_ENABLE(n)     (n << 2)
+       #define v_HDMI_DVI(n)           (n << 1)
+       #define v_HDCP_RESET(n)         (n << 0)
+
+#define HDCP_CTRL2                             0x53
+       #define m_DISABLE_127_CHECK                             (1 << 7)
+       #define m_SKIP_BKSV_CHECK                               (1 << 6)
+       #define m_ENABLE_PJ_CHECK                               (1 << 5)
+       #define m_DISABLE_DEVICE_NUMBER_CHECK   (1 << 4)
+       #define m_DELAY_RI_1_CLK                                (1 << 3)
+       #define m_USE_PRESET_AN                                 (1 << 2)
+       #define m_KEY_COMBINATION                               (3 << 0)
+       
+       #define v_DISABLE_127_CHECK(n)                  (n << 7)
+       #define v_SKIP_BKSV_CHECK(n)                    (n << 6)
+       #define v_ENABLE_PJ_CHECK(n)                    (n << 5)
+       #define v_DISABLE_DEVICE_NUMBER_CHECK(n)(n << 4)
+       #define v_DELAY_RI_1_CLK(n)                             (n << 3)
+       #define v_USE_PRESET_AN(n)                              (n << 2)
+       #define v_KEY_COMBINATION(n)                    (n << 0)
+
+#define HDCP_KEY_STATUS                        0x54
+       #define m_KEY_READY                     (1 << 0)
+
+#define HDCP_CTRL_SOFT                 0x57
+       #define m_DISABLE_127_CHECK                             (1 << 7)
+       #define m_SKIP_BKSV_CHECK                               (1 << 6)
+       #define m_NOT_AUTHENTICATED                             (1 << 5)
+       #define m_ENCRYPTED                                             (1 << 4)
+       #define m_ADVANCED_CIPHER                               (1 << 3)
+       
+#define HDCP_BCAPS_RX                  0x58
+#define HDCP_TIMER_100MS               0x63
+#define HDCP_TIMER_5S                  0x64
+#define HDCP_ERROR                             0x65
+       #define m_DDC_NO_ACK            (1 << 3)
+       #define m_PJ_MISMACH            (1 << 2)
+       #define m_RI_MISMACH            (1 << 1)
+       #define m_BKSV_WRONG            (1 << 0)
+
+#define HDCP_KSV_BYTE0                 0x66
+#define HDCP_KSV_BYTE1                 0x67
+#define HDCP_KSV_BYTE2                 0x68
+#define HDCP_KSV_BYTE3                 0x69
+#define HDCP_KSV_BYTE4                 0x6a
+
+#define HDCP_AN_SEED                   0x6c
+
+#define HDCP_BCAPS_TX                  0x80
+#define HDCP_BSTATE_0                  0x81
+#define HDCP_BSTATE_1                  0x82
+
+#define HDCP_KEY_FIFO                  0x98
+
+#define HDCP_INT_MASK1                 0xc2
+#define HDCP_INT_STATUS1               0xc3
+       #define m_INT_HDCP_ERR          (1 << 7)
+       #define m_INT_BKSV_READY        (1 << 6)
+       #define m_INT_BKSV_UPDATE       (1 << 5)
+       #define m_INT_AUTH_SUCCESS      (1 << 4)
+       #define m_INT_AUTH_READY        (1 << 3)
+       
+#define HDCP_INT_MASK2                 0xc4
+#define HDCP_INT_STATUS2               0xc5
+       #define m_INT_SOFT_MODE_READY                   (1 << 7)
+       #define m_INT_AUTH_M0_REDAY                             (1 << 6)
+       #define m_INT_1st_FRAME_ARRIVE                  (1 << 5)
+       #define m_INT_AN_READY                                  (1 << 4)
+       #define m_INT_ENCRYPTED                                 (1 << 2)
+       #define m_INT_NOT_ENCRYPTED_AVMUTE              (1 << 1)
+       #define m_INT_NOT_ENCRYPTED_AVUNMUTE    (1 << 0)
+
+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
+
+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 rk2928_hdcp_disable(void);
+extern int     rk2928_hdcp_start_authentication(void);
+extern int     rk2928_hdcp_check_bksv(void);
+extern int     rk2928_hdcp_load_key2mem(struct hdcp_keys *key);
+extern void rk2928_hdcp_interrupt(char *status1, char *status2);
+#endif /* __rk2928_HDCP_H__ */
\ No newline at end of file
index 4695086bf329d36503c91e172c2fee72036b11ba..9efceb36d63bdcb824a558426c97dddbba47d510 100755 (executable)
@@ -3,8 +3,10 @@
 
 #include "../../rk_hdmi.h"
 
+#define HDMI_SOURCE_DEFAULT            HDMI_SOURCE_LCDC0
 
-extern int rk30_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
+extern void    rk2928_hdmi_control_output(int enable);
+extern int     rk2928_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));
diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hdcp.c b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hdcp.c
new file mode 100755 (executable)
index 0000000..b83daca
--- /dev/null
@@ -0,0 +1,135 @@
+#include <linux/delay.h>\r
+#include "rk2928_hdmi.h"\r
+#include "rk2928_hdmi_hw.h"\r
+#include "rk2928_hdcp.h"\r
+\r
+#define HDCPWrReg      HDMIWrReg\r
+#define HDCPRdReg      HDMIRdReg\r
+#define HDCPMskReg(temp, addr, msk, val)       \\r
+       temp = HDCPRdReg(addr) & (0xFF - (msk)) ; \\r
+       HDCPWrReg(addr, temp | ( (val) & (msk) )); \r
+       \r
+void rk2928_hdcp_disable(void)\r
+{\r
+       char temp;\r
+       \r
+       // Diable HDCP Interrupt\r
+       HDCPWrReg(HDCP_INT_MASK1, 0x00);\r
+       // Stop and Reset HDCP\r
+       HDCPMskReg(temp, HDCP_CTRL1, m_ENCRYPT_ENABLE | m_AUTH_STOP | m_HDCP_RESET, \r
+               v_ENCRYPT_ENABLE(0) | v_AUTH_STOP(1) | v_HDCP_RESET(1) )\r
+}\r
+\r
+int    rk2928_hdcp_load_key2mem(struct hdcp_keys *key)\r
+{\r
+       int i;\r
+       DBG("HDCP: rk2928_hdcp_load_key2mem start");\r
+       // Write 40 private key\r
+       for(i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++)\r
+               HDCPWrReg(HDCP_KEY_FIFO, key->DeviceKey[i]);\r
+       \r
+       // Write 1st aksv\r
+       for(i = 0; i < 5; i++)\r
+               HDCPWrReg(HDCP_KEY_FIFO, key->KSV[i]);\r
+               \r
+       // Write 2nd aksv\r
+       for(i = 0; i < 5; i++)\r
+               HDCPWrReg(HDCP_KEY_FIFO, key->KSV[i]);\r
+       DBG("HDCP: rk2928_hdcp_load_key2mem end");\r
+       return HDCP_OK;\r
+}\r
+\r
+int    rk2928_hdcp_start_authentication(void)\r
+{\r
+       char temp;\r
+       int retry = 0;\r
+\r
+       if(hdcp->keys == NULL) {\r
+               printk(KERN_ERR "HDCP: key is not loaded\n");\r
+               return HDCP_KEY_ERR;\r
+       }\r
+       \r
+       // Select TMDS CLK to configure regs\r
+       HDCPMskReg(temp, SYS_CTRL, m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_TMDS);\r
+       \r
+       temp = HDCPRdReg(HDCP_KEY_STATUS);\r
+       while( ( temp & m_KEY_READY) == 0 ) {\r
+               if(retry > 10) {\r
+                       printk(KERN_ERR "HDCP: loaded key error\n");\r
+                       return HDCP_KEY_ERR;\r
+               }\r
+               rk2928_hdcp_load_key2mem(hdcp->keys);\r
+               msleep(1);\r
+               temp = HDCPRdReg(HDCP_KEY_STATUS);\r
+       }\r
+       \r
+       // Config DDC bus clock: ddc_clk = reg_clk/4*(reg 0x4c 0x4b)\r
+       DBG("TMDS frequency %d", hdmi->tmdsclk);\r
+       retry = hdmi->tmdsclk/(HDCP_DDC_CLK*4);\r
+       HDCPWrReg(DDC_CLK_L, retry & 0xFF);\r
+       HDCPWrReg(DDC_CLK_H, (retry >> 8) & 0xFF);\r
+       \r
+       HDCPWrReg(HDCP_CTRL2, 0x00);\r
+       \r
+       //Enable interrupt\r
+       HDCPWrReg(HDCP_INT_MASK1, m_INT_HDCP_ERR | m_INT_BKSV_READY | m_INT_BKSV_UPDATE | m_INT_AUTH_SUCCESS | m_INT_AUTH_READY);\r
+//     HDCPWrReg(HDCP_INT_MASK2, 0xFF);\r
+       //Start authentication\r
+       HDCPMskReg(temp, HDCP_CTRL1, m_AUTH_START | m_ENCRYPT_ENABLE | m_ADVANED_ENABLE, v_AUTH_START(1) | v_ENCRYPT_ENABLE(1) | v_ADVANED_ENABLE(0));\r
+       \r
+       return HDCP_OK;\r
+}\r
+\r
+int    rk2928_hdcp_check_bksv(void)\r
+{\r
+       int i, j;\r
+       char temp = 0, bksv[5];\r
+       char *invalidkey;\r
+       \r
+       for(i = 0; i < 5; i++) {\r
+               bksv[i] = HDCPRdReg(HDCP_KSV_BYTE0 + (4 - i)) & 0xFF;\r
+       }\r
+       DBG("bksv is 0x%02x%02x%02x%02x%02x", bksv[0], bksv[1], bksv[2], bksv[3], bksv[4]);\r
+       \r
+       for (i = 0; i < 5; i++)\r
+       {\r
+       for (j = 0; j < 8; j++)\r
+       {\r
+               if (bksv[i] & 0x01)\r
+               {\r
+                       temp++;\r
+               }\r
+               bksv[i] >>= 1;\r
+       }\r
+       }\r
+       if (temp != 20)\r
+       return HDCP_KSV_ERR;\r
+       \r
+       for(i = 0; i < hdcp->invalidkey; i++)\r
+       {\r
+               invalidkey = hdcp->invalidkeys + i *5;\r
+               if(memcmp(bksv, invalidkey, 5) == 0) {\r
+                       printk(KERN_ERR "HDCP: BKSV was revocated!!!\n");\r
+                       HDCPMskReg(temp, HDCP_CTRL1, m_BKSV_INVALID | m_ENCRYPT_ENABLE, v_BKSV_INVALID(1) | v_ENCRYPT_ENABLE(1));\r
+                       return HDCP_KSV_ERR;\r
+               }\r
+       }\r
+       HDCPMskReg(temp, HDCP_CTRL1, m_BKSV_VALID | m_ENCRYPT_ENABLE, v_BKSV_VALID(1) | v_ENCRYPT_ENABLE(1));\r
+       return HDCP_OK;\r
+}\r
+\r
+void rk2928_hdcp_interrupt(char *status1, char *status2)\r
+{\r
+       char interrupt1 = HDCPRdReg(HDCP_INT_STATUS1);\r
+       char interrupt2 = HDCPRdReg(HDCP_INT_STATUS2);\r
+       if(interrupt1) {\r
+               HDCPWrReg(HDCP_INT_STATUS1, interrupt1);\r
+               if(interrupt1 & m_INT_HDCP_ERR)\r
+                       printk(KERN_INFO "HDCP: Error 0x%02x\n", HDCPRdReg(HDCP_ERROR));\r
+       }\r
+       if(interrupt2)\r
+               HDCPWrReg(HDCP_INT_STATUS2, interrupt2);\r
+       \r
+       *status1 = interrupt1;\r
+       *status2 = interrupt2;\r
+}
\ No newline at end of file
index b5dd18054bffa617e316333c28ed569fef6f74c0..f2e709db6f046d0d9550b42c6fe3c63a679fb407 100755 (executable)
@@ -143,7 +143,9 @@ int rk2928_hdmi_read_edid(int block, unsigned char *buff)
                        break;
                }else
                        hdmi_err(hdmi->dev, "[%s] edid read error\n", __FUNCTION__);
-
+                       
+               hdmi_dbg(hdmi->dev, "[%s] edid try times %d\n", __FUNCTION__, trytime);
+               msleep(100);
        }
        // Disable edid interrupt
        HDMIWrReg(INTERRUPT_MASK1, m_INT_HOTPLUG);
@@ -366,7 +368,7 @@ static int rk2928_hdmi_config_audio(struct hdmi_audio *audio)
     return 0;
 }
 
-static void rk2928_hdmi_control_output(int enable)
+void rk2928_hdmi_control_output(int enable)
 {
        char mutestatus = 0;
        
@@ -444,7 +446,7 @@ int rk2928_hdmi_initial(void)
        int rc = HDMI_ERROR_SUCESS;
 
        hdmi->pwr_mode = NORMAL;
-       hdmi->hdmi_removed = rk2928_hdmi_removed ;
+       hdmi->remove = rk2928_hdmi_removed ;
        hdmi->control_output = rk2928_hdmi_control_output;
        hdmi->config_video = rk2928_hdmi_config_video;
        hdmi->config_audio = rk2928_hdmi_config_audio;
index 31deae4f65260646eb0aec3a6950ce8271079bea..27edf4102d3d08d11cf254397c413df8ab09d726 100755 (executable)
@@ -1,16 +1 @@
-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/chips/rk30/hdcp/Kconfig"
\ No newline at end of file
index 98dfae27667417b12c6df75c245180ea3131436f..0704c997140b272c2edf57e00eb0a273d66016e6 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.o
 obj-$(CONFIG_HDCP_RK30) += hdcp/
index 4695086bf329d36503c91e172c2fee72036b11ba..f0220d0134474d29eb366613b7922efeb3916325 100755 (executable)
@@ -3,6 +3,8 @@
 
 #include "../../rk_hdmi.h"
 
+/* default HDMI video source */
+#define HDMI_SOURCE_DEFAULT            HDMI_SOURCE_LCDC1
 
 extern int rk30_hdmi_register_hdcp_callbacks(void (*hdcp_cb)(void),
                                         void (*hdcp_irq_cb)(int status),
index 5f1d2662cf23e94683996fa98fdc833d483e2394..3e7ed568e684e786a914994d76541da43a580e20 100755 (executable)
@@ -16,7 +16,7 @@ int rk30_hdmi_initial(void)
        int rc = HDMI_ERROR_SUCESS;
 
        hdmi->pwr_mode = PWR_SAVE_MODE_A;
-       hdmi->hdmi_removed = rk30_hdmi_removed ;
+       hdmi->remove = rk30_hdmi_removed ;
        hdmi->control_output = rk30_hdmi_control_output;
        hdmi->config_video = rk30_hdmi_config_video;
        hdmi->config_audio = rk30_hdmi_config_audio;
@@ -144,11 +144,12 @@ int rk30_hdmi_read_edid(int block, unsigned char *buff)
                }               
                if(interrupt & m_INT_EDID_ERR)
                        hdmi_err(hdmi->dev, "[%s] edid read error\n", __FUNCTION__);
-
+               
+               hdmi_dbg(hdmi->dev, "[%s] edid try times %d\n", __FUNCTION__, trytime);
+               msleep(100);
        }
        // Disable edid interrupt
        HDMIWrReg(INTR_MASK1, m_INT_HOTPLUG | m_INT_MSENS);
-//     msleep(100);
        return ret;
 }
 
index 83d3925e482bfe55e80036538f7f4639f90aead1..7222a8cf33e2ccb1e07984c7e67f5c6236fc7053 100755 (executable)
@@ -27,12 +27,6 @@ enum {
        HDMI_SOURCE_LCDC1 = 1
 };
 
-/* default HDMI video source */
-#ifdef CONFIG_ARCH_RK2928
-#define HDMI_SOURCE_DEFAULT            HDMI_SOURCE_LCDC0
-#else
-#define HDMI_SOURCE_DEFAULT            HDMI_SOURCE_LCDC1
-#endif
 /* 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
  */
@@ -244,7 +238,6 @@ struct hdmi_edid {
        int     audio_num;                                              //Device supported audio type number
 };
 
-extern const struct fb_videomode hdmi_mode[];
 /* RK HDMI Video Configure Parameters */
 struct hdmi_video_para {
        int vic;
@@ -253,6 +246,7 @@ struct hdmi_video_para {
        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
@@ -296,8 +290,8 @@ struct hdmi {
        int yscale;                                     // y directoon scale value
        int tmdsclk;                            // TDMS Clock frequency
        
-
-       int (*hdmi_removed)(void);
+       int (*insert)(void);
+       int (*remove)(void);
        void (*control_output)(int enable);
        int (*config_video)(struct hdmi_video_para *vpara);
        int (*config_audio)(struct hdmi_audio *audio);
@@ -323,8 +317,6 @@ struct hdmi {
 #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);
@@ -338,6 +330,5 @@ 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 void hdmi_work(struct work_struct *work);
 #endif
index be2be8b72a9e11e6bd41e08f7a806d00439599e2..e212ae7792ade2bcb90269fe90553b596511f2cd 100755 (executable)
@@ -8,7 +8,7 @@
 #define SWAP_RB                        0
 #define LCD_ACLK               800000000
 
-const struct fb_videomode hdmi_mode [] = {
+static 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       },
@@ -507,9 +507,12 @@ int hdmi_switch_fb(struct hdmi *hdmi, int vic)
        rc = hdmi_set_info(screen, hdmi->vic);
 
        if(rc == 0) {           
-               rk_fb_switch_screen(screen, 1, HDMI_SOURCE_DEFAULT);
-               rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, HDMI_SOURCE_DEFAULT);
+               rk_fb_switch_screen(screen, 1, hdmi->lcdc->id);
+               rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, hdmi->lcdc->id);
        }
+       
+       kfree(screen);
+       
        return rc;
 }
 
index 45d28eea57b52c271f50b560e5801da067bff7db..dc0c5d82fb4fe2411b63ce45709618d35416369e 100755 (executable)
@@ -112,7 +112,7 @@ static int hdmi_set_scale(struct rk_display_device *device, int direction, int v
                hdmi->yscale = value;
        else
                return -1;
-       rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, HDMI_SOURCE_DEFAULT);
+       rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, hdmi->lcdc->id);
        return 0;
 }
 
index 7bb6eb6c2628df59b02a124b21e632743fddb020..5f34b23236dc6eed59978d1801cb6fac31af8cf5 100755 (executable)
@@ -2,7 +2,7 @@
 #include <linux/delay.h>
 #include "rk_hdmi.h"
 
-#ifdef CONFIG_HDMI_RK30_CTL_CODEC
+#ifdef CONFIG_RK_HDMI_CTL_CODEC
 extern void codec_set_spk(bool on);
 #endif
 
@@ -80,12 +80,12 @@ void hdmi_sys_remove(void)
        memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
        INIT_LIST_HEAD(&hdmi->edid.modelist);
        hdmi->display   = HDMI_DISABLE;
-       rk_fb_switch_screen(hdmi->lcdc->screen1, 0, HDMI_SOURCE_DEFAULT);
+       rk_fb_switch_screen(hdmi->lcdc->screen1, 0, hdmi->lcdc->id);
        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
+       #ifdef CONFIG_RK_HDMI_CTL_CODEC
        codec_set_spk(1);
        #endif
 }
@@ -96,7 +96,7 @@ static void hdmi_sys_sleep(void)
        if(hdmi->enable)
                disable_irq(hdmi->irq);                         
        hdmi->state = HDMI_SLEEP;
-       hdmi->hdmi_removed();
+       hdmi->remove();
        if(hdmi->enable)
                enable_irq(hdmi->irq);
        mutex_unlock(&hdmi->enable_mutex);
@@ -121,7 +121,7 @@ static int hdmi_process_command(void)
                                                hdmi_sys_remove();
                                        hdmi->state = HDMI_SLEEP;
                                        hdmi->hotplug = HDMI_HPD_REMOVED;
-                                       hdmi->hdmi_removed();
+                                       hdmi->remove();
                                        state = HDMI_SLEEP;
                                }
                                mutex_unlock(&hdmi->enable_mutex);
@@ -183,6 +183,8 @@ void hdmi_work(struct work_struct *work)
        if(hotplug != hdmi->hotplug)
        {
                if(hotplug  == HDMI_HPD_ACTIVED){
+                       if(hdmi->insert)
+                               hdmi->insert();
                        hdmi->state = READ_PARSE_EDID;
                }
                else if(hdmi->hotplug == HDMI_HPD_ACTIVED) {
@@ -192,7 +194,7 @@ void hdmi_work(struct work_struct *work)
                                hdmi_sys_sleep();
                        else {
                                hdmi->state = WAIT_HOTPLUG;
-                               hdmi->hdmi_removed();
+                               hdmi->remove();
                        }
                        if(hdmi->wait == 1) {
                                complete(&hdmi->complete);
@@ -203,7 +205,7 @@ void hdmi_work(struct work_struct *work)
                }
                else if(hotplug == HDMI_HPD_REMOVED) {
                        hdmi->state = HDMI_SLEEP;
-                       hdmi->hdmi_removed();
+                       hdmi->remove();
                }
                hdmi->hotplug  = hotplug;
        }
@@ -224,7 +226,7 @@ void hdmi_work(struct work_struct *work)
                                        #ifdef CONFIG_SWITCH
                                        switch_set_state(&(hdmi->switch_hdmi), 1);
                                        #endif
-                                       #ifdef CONFIG_HDMI_RK30_CTL_CODEC
+                                       #ifdef CONFIG_RK_HDMI_CTL_CODEC
                                        codec_set_spk(0);
                                        #endif
                                }
@@ -297,15 +299,6 @@ void hdmi_work(struct work_struct *work)
        
        }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);
 }