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.
-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.
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
+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
# 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
+++ /dev/null
-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
+++ /dev/null
-#
-# 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
+++ /dev/null
-#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
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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
--- /dev/null
+#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);
--- /dev/null
+#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
#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));
--- /dev/null
+#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
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);
return 0;
}
-static void rk2928_hdmi_control_output(int enable)
+void rk2928_hdmi_control_output(int enable)
{
char mutestatus = 0;
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;
-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
# 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/
#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),
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;
}
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;
}
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
*/
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;
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 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);
#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_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
#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 },
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;
}
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;
}
#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
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
}
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);
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);
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) {
hdmi_sys_sleep();
else {
hdmi->state = WAIT_HOTPLUG;
- hdmi->hdmi_removed();
+ hdmi->remove();
}
if(hdmi->wait == 1) {
complete(&hdmi->complete);
}
else if(hotplug == HDMI_HPD_REMOVED) {
hdmi->state = HDMI_SLEEP;
- hdmi->hdmi_removed();
+ hdmi->remove();
}
hdmi->hotplug = hotplug;
}
#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
}
}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);
}