From 39f81f80670f503f50157fd4fb959dc99f072424 Mon Sep 17 00:00:00 2001 From: Zheng Yang Date: Tue, 4 Sep 2012 15:08:21 +0800 Subject: [PATCH] rk30/rk2928 hdmi: 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. --- drivers/video/rockchip/hdmi/Kconfig | 21 +- drivers/video/rockchip/hdmi/chips/Kconfig | 2 - .../video/rockchip/hdmi/chips/rk2928/Kconfig | 13 ++ .../video/rockchip/hdmi/chips/rk2928/Makefile | 7 +- .../rockchip/hdmi/chips/rk2928/hdcp/Kconfig | 14 -- .../rockchip/hdmi/chips/rk2928/hdcp/Makefile | 8 - .../hdmi/chips/rk2928/hdcp/rk30_hdmi_hdcp.c | 157 --------------- .../hdmi/chips/rk2928/hdcp/rk30_hdmi_hdcp.h | 99 --------- .../{hdcp/rk30_hdcp.c => rk2928_hdcp.c} | 79 ++++---- .../rockchip/hdmi/chips/rk2928/rk2928_hdcp.h | 190 ++++++++++++++++++ .../rockchip/hdmi/chips/rk2928/rk2928_hdmi.h | 4 +- .../hdmi/chips/rk2928/rk2928_hdmi_hdcp.c | 135 +++++++++++++ .../hdmi/chips/rk2928/rk2928_hdmi_hw.c | 8 +- .../video/rockchip/hdmi/chips/rk30/Kconfig | 15 -- .../video/rockchip/hdmi/chips/rk30/Makefile | 2 +- .../rockchip/hdmi/chips/rk30/rk30_hdmi.h | 2 + .../rockchip/hdmi/chips/rk30/rk30_hdmi_hw.c | 7 +- drivers/video/rockchip/hdmi/rk_hdmi.h | 17 +- drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c | 9 +- drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c | 2 +- drivers/video/rockchip/hdmi/rk_hdmi_task.c | 27 +-- 21 files changed, 431 insertions(+), 387 deletions(-) delete mode 100755 drivers/video/rockchip/hdmi/chips/rk2928/hdcp/Kconfig delete mode 100755 drivers/video/rockchip/hdmi/chips/rk2928/hdcp/Makefile delete mode 100755 drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdmi_hdcp.c delete mode 100755 drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdmi_hdcp.h rename drivers/video/rockchip/hdmi/chips/rk2928/{hdcp/rk30_hdcp.c => rk2928_hdcp.c} (90%) create mode 100755 drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdcp.h create mode 100755 drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hdcp.c diff --git a/drivers/video/rockchip/hdmi/Kconfig b/drivers/video/rockchip/hdmi/Kconfig index e3700bbd817d..144b9a51981f 100755 --- a/drivers/video/rockchip/hdmi/Kconfig +++ b/drivers/video/rockchip/hdmi/Kconfig @@ -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. diff --git a/drivers/video/rockchip/hdmi/chips/Kconfig b/drivers/video/rockchip/hdmi/chips/Kconfig index e0c1c271bdc1..c01155675dcc 100755 --- a/drivers/video/rockchip/hdmi/chips/Kconfig +++ b/drivers/video/rockchip/hdmi/chips/Kconfig @@ -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 diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/Kconfig b/drivers/video/rockchip/hdmi/chips/rk2928/Kconfig index 8b137891791f..49a9cbf65013 100755 --- a/drivers/video/rockchip/hdmi/chips/rk2928/Kconfig +++ b/drivers/video/rockchip/hdmi/chips/rk2928/Kconfig @@ -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 diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/Makefile b/drivers/video/rockchip/hdmi/chips/rk2928/Makefile index d3227c7f27d9..1e17c7641c67 100755 --- a/drivers/video/rockchip/hdmi/chips/rk2928/Makefile +++ b/drivers/video/rockchip/hdmi/chips/rk2928/Makefile @@ -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 index 1bb3c3a24f56..000000000000 --- a/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/Kconfig +++ /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 index 108b67ca134e..000000000000 --- a/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/Makefile +++ /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_hdmi_hdcp.c b/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdmi_hdcp.c deleted file mode 100755 index 1184989a57b2..000000000000 --- a/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdmi_hdcp.c +++ /dev/null @@ -1,157 +0,0 @@ -#include -#include -#include -#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 index 0224d88ab134..000000000000 --- a/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdmi_hdcp.h +++ /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/hdcp/rk30_hdcp.c b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdcp.c similarity index 90% rename from drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdcp.c rename to drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdcp.c index 68d0ac841a67..25ff53203139 100755 --- a/drivers/video/rockchip/hdmi/chips/rk2928/hdcp/rk30_hdcp.c +++ b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdcp.c @@ -5,9 +5,8 @@ #include #include #include -#include "../rk30_hdmi.h" -#include "../rk30_hdmi_hw.h" -#include "rk30_hdmi_hdcp.h" +#include "rk2928_hdmi.h" +#include "rk2928_hdcp.h" struct hdcp *hdcp = NULL; @@ -70,11 +69,11 @@ static void hdcp_wq_authentication_failure(void) return; } - rk30_hdcp_disable(); - rk30_hdmi_control_output(false); + 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--; @@ -109,13 +108,14 @@ static void hdcp_wq_start_authentication(void) DBG("HDCP: authentication start"); - status = rk30_hdcp_start_authentication(); + 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; } } @@ -129,7 +129,7 @@ static void hdcp_wq_check_bksv(void) DBG("Check BKSV start"); - status = rk30_hdcp_check_bksv(); + status = rk2928_hdcp_check_bksv(); if (status != HDCP_OK) { printk(KERN_INFO "HDCP: Check BKSV failed"); @@ -155,8 +155,8 @@ static void hdcp_wq_check_bksv(void) */ static void hdcp_wq_authentication_sucess(void) { + rk2928_hdmi_control_output(true); printk(KERN_INFO "HDCP: authentication pass"); - rk30_hdmi_control_output(true); } /*----------------------------------------------------------------------------- @@ -168,11 +168,11 @@ static void hdcp_wq_disable(int event) printk(KERN_INFO "HDCP: disabled"); hdcp_cancel_work(&hdcp->pending_wq_event); - rk30_hdcp_disable(); + rk2928_hdcp_disable(); if(event == HDCP_DISABLE_CTL) { hdcp->hdcp_state = HDCP_DISABLED; if(hdcp->hdmi_state == HDMI_STARTED) - rk30_hdmi_control_output(true); + rk2928_hdmi_control_output(true); } else if(event == HDCP_STOP_FRAME_EVENT) hdcp->hdcp_state = HDCP_ENABLE_PENDING; @@ -302,25 +302,24 @@ static void hdcp_start_frame_cb(void) * Function: hdcp_irq_cb *----------------------------------------------------------------------------- */ -static void hdcp_irq_cb(int interrupt) +static void hdcp_irq_cb(int status) { - int value; - DBG("%s 0x%x", __FUNCTION__, interrupt); - if(interrupt & m_INT_HDCP_ERR) + char interrupt1; + char interrupt2; + + rk2928_hdcp_interrupt(&interrupt1, &interrupt2); + DBG("%s 0x%02x 0x%02x", __FUNCTION__, interrupt1, interrupt2); + if(interrupt1 & 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)) + else if(interrupt1 & (m_INT_BKSV_READY | m_INT_BKSV_UPDATE)) hdcp_submit_work(HDCP_KSV_LIST_RDY_EVENT, 0); - else if(interrupt & m_INT_AUTH_DONE) + else if(interrupt1 & m_INT_AUTH_SUCCESS) hdcp_submit_work(HDCP_AUTH_PASS_EVENT, 0); } @@ -331,7 +330,8 @@ static void hdcp_irq_cb(int interrupt) static int hdcp_power_on_cb(void) { DBG("%s", __FUNCTION__); - return rk30_hdcp_load_key2mem(hdcp->keys); +// return rk2928_hdcp_load_key2mem(hdcp->keys); + return HDCP_OK; } /*----------------------------------------------------------------------------- @@ -350,7 +350,7 @@ static void hdcp_power_off_cb(void) /* Post event to workqueue */ if (hdcp_submit_work(HDCP_STOP_FRAME_EVENT, 0)) wait_for_completion_interruptible_timeout(&hdcp->complete, - msecs_to_jiffies(2000)); + msecs_to_jiffies(5000)); } // Load HDCP key to external HDCP memory @@ -374,8 +374,7 @@ static void hdcp_load_keys_cb(const struct firmware *fw, void *context) memcpy(hdcp->keys, fw->data, HDCP_KEY_SIZE); - rk30_hdcp_load_key2mem(hdcp->keys); - printk(KERN_INFO "HDCP: loaded hdcp key success\n"); + 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); @@ -468,7 +467,7 @@ static DEVICE_ATTR(trytimes, S_IRUGO|S_IWUSR, hdcp_trytimes_read, hdcp_trytimes_ static struct miscdevice mdev; -static int __init rk30_hdcp_init(void) +static int __init rk2928_hdcp_init(void) { int ret; @@ -523,7 +522,7 @@ static int __init rk30_hdcp_init(void) goto error5; } - rk30_hdmi_register_hdcp_callbacks( hdcp_start_frame_cb, + rk2928_hdmi_register_hdcp_callbacks(hdcp_start_frame_cb, hdcp_irq_cb, hdcp_power_on_cb, hdcp_power_off_cb); @@ -549,22 +548,16 @@ error0: return ret; } -static void __exit rk30_hdcp_exit(void) +static void __exit rk2928_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); - } + 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(rk30_hdcp_init); -module_exit(rk30_hdcp_exit); \ No newline at end of file +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 index 000000000000..4d55037e5e5d --- /dev/null +++ b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdcp.h @@ -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 diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi.h b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi.h index 4695086bf329..9efceb36d63b 100755 --- a/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi.h +++ b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi.h @@ -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 index 000000000000..b83daca53d78 --- /dev/null +++ b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hdcp.c @@ -0,0 +1,135 @@ +#include +#include "rk2928_hdmi.h" +#include "rk2928_hdmi_hw.h" +#include "rk2928_hdcp.h" + +#define HDCPWrReg HDMIWrReg +#define HDCPRdReg HDMIRdReg +#define HDCPMskReg(temp, addr, msk, val) \ + temp = HDCPRdReg(addr) & (0xFF - (msk)) ; \ + HDCPWrReg(addr, temp | ( (val) & (msk) )); + +void rk2928_hdcp_disable(void) +{ + char temp; + + // Diable HDCP Interrupt + HDCPWrReg(HDCP_INT_MASK1, 0x00); + // Stop and Reset HDCP + HDCPMskReg(temp, HDCP_CTRL1, m_ENCRYPT_ENABLE | m_AUTH_STOP | m_HDCP_RESET, + v_ENCRYPT_ENABLE(0) | v_AUTH_STOP(1) | v_HDCP_RESET(1) ) +} + +int rk2928_hdcp_load_key2mem(struct hdcp_keys *key) +{ + int i; + DBG("HDCP: rk2928_hdcp_load_key2mem start"); + // Write 40 private key + for(i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++) + HDCPWrReg(HDCP_KEY_FIFO, key->DeviceKey[i]); + + // Write 1st aksv + for(i = 0; i < 5; i++) + HDCPWrReg(HDCP_KEY_FIFO, key->KSV[i]); + + // Write 2nd aksv + for(i = 0; i < 5; i++) + HDCPWrReg(HDCP_KEY_FIFO, key->KSV[i]); + DBG("HDCP: rk2928_hdcp_load_key2mem end"); + return HDCP_OK; +} + +int rk2928_hdcp_start_authentication(void) +{ + char temp; + int retry = 0; + + if(hdcp->keys == NULL) { + printk(KERN_ERR "HDCP: key is not loaded\n"); + return HDCP_KEY_ERR; + } + + // Select TMDS CLK to configure regs + HDCPMskReg(temp, SYS_CTRL, m_REG_CLK_SOURCE, v_REG_CLK_SOURCE_TMDS); + + temp = HDCPRdReg(HDCP_KEY_STATUS); + while( ( temp & m_KEY_READY) == 0 ) { + if(retry > 10) { + printk(KERN_ERR "HDCP: loaded key error\n"); + return HDCP_KEY_ERR; + } + rk2928_hdcp_load_key2mem(hdcp->keys); + msleep(1); + temp = HDCPRdReg(HDCP_KEY_STATUS); + } + + // Config DDC bus clock: ddc_clk = reg_clk/4*(reg 0x4c 0x4b) + DBG("TMDS frequency %d", hdmi->tmdsclk); + retry = hdmi->tmdsclk/(HDCP_DDC_CLK*4); + HDCPWrReg(DDC_CLK_L, retry & 0xFF); + HDCPWrReg(DDC_CLK_H, (retry >> 8) & 0xFF); + + HDCPWrReg(HDCP_CTRL2, 0x00); + + //Enable interrupt + HDCPWrReg(HDCP_INT_MASK1, m_INT_HDCP_ERR | m_INT_BKSV_READY | m_INT_BKSV_UPDATE | m_INT_AUTH_SUCCESS | m_INT_AUTH_READY); +// HDCPWrReg(HDCP_INT_MASK2, 0xFF); + //Start authentication + 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)); + + return HDCP_OK; +} + +int rk2928_hdcp_check_bksv(void) +{ + int i, j; + char temp = 0, bksv[5]; + char *invalidkey; + + for(i = 0; i < 5; i++) { + bksv[i] = HDCPRdReg(HDCP_KSV_BYTE0 + (4 - i)) & 0xFF; + } + DBG("bksv is 0x%02x%02x%02x%02x%02x", bksv[0], bksv[1], bksv[2], bksv[3], bksv[4]); + + for (i = 0; i < 5; i++) + { + for (j = 0; j < 8; j++) + { + if (bksv[i] & 0x01) + { + temp++; + } + bksv[i] >>= 1; + } + } + if (temp != 20) + return HDCP_KSV_ERR; + + 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"); + HDCPMskReg(temp, HDCP_CTRL1, m_BKSV_INVALID | m_ENCRYPT_ENABLE, v_BKSV_INVALID(1) | v_ENCRYPT_ENABLE(1)); + return HDCP_KSV_ERR; + } + } + HDCPMskReg(temp, HDCP_CTRL1, m_BKSV_VALID | m_ENCRYPT_ENABLE, v_BKSV_VALID(1) | v_ENCRYPT_ENABLE(1)); + return HDCP_OK; +} + +void rk2928_hdcp_interrupt(char *status1, char *status2) +{ + char interrupt1 = HDCPRdReg(HDCP_INT_STATUS1); + char interrupt2 = HDCPRdReg(HDCP_INT_STATUS2); + if(interrupt1) { + HDCPWrReg(HDCP_INT_STATUS1, interrupt1); + if(interrupt1 & m_INT_HDCP_ERR) + printk(KERN_INFO "HDCP: Error 0x%02x\n", HDCPRdReg(HDCP_ERROR)); + } + if(interrupt2) + HDCPWrReg(HDCP_INT_STATUS2, interrupt2); + + *status1 = interrupt1; + *status2 = interrupt2; +} \ No newline at end of file diff --git a/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hw.c b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hw.c index b5dd18054bff..f2e709db6f04 100755 --- a/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hw.c +++ b/drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hw.c @@ -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; diff --git a/drivers/video/rockchip/hdmi/chips/rk30/Kconfig b/drivers/video/rockchip/hdmi/chips/rk30/Kconfig index 31deae4f6526..27edf4102d3d 100755 --- a/drivers/video/rockchip/hdmi/chips/rk30/Kconfig +++ b/drivers/video/rockchip/hdmi/chips/rk30/Kconfig @@ -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 diff --git a/drivers/video/rockchip/hdmi/chips/rk30/Makefile b/drivers/video/rockchip/hdmi/chips/rk30/Makefile index 98dfae276674..0704c997140b 100755 --- a/drivers/video/rockchip/hdmi/chips/rk30/Makefile +++ b/drivers/video/rockchip/hdmi/chips/rk30/Makefile @@ -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/ diff --git a/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi.h b/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi.h index 4695086bf329..f0220d013447 100755 --- a/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi.h +++ b/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi.h @@ -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), diff --git a/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi_hw.c b/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi_hw.c index 5f1d2662cf23..3e7ed568e684 100755 --- a/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi_hw.c +++ b/drivers/video/rockchip/hdmi/chips/rk30/rk30_hdmi_hw.c @@ -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; } diff --git a/drivers/video/rockchip/hdmi/rk_hdmi.h b/drivers/video/rockchip/hdmi/rk_hdmi.h index 83d3925e482b..7222a8cf33e2 100755 --- a/drivers/video/rockchip/hdmi/rk_hdmi.h +++ b/drivers/video/rockchip/hdmi/rk_hdmi.h @@ -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 diff --git a/drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c b/drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c index be2be8b72a9e..e212ae7792ad 100755 --- a/drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c +++ b/drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c @@ -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; } diff --git a/drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c b/drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c index 45d28eea57b5..dc0c5d82fb4f 100755 --- a/drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c +++ b/drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c @@ -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; } diff --git a/drivers/video/rockchip/hdmi/rk_hdmi_task.c b/drivers/video/rockchip/hdmi/rk_hdmi_task.c index 7bb6eb6c2628..5f34b23236dc 100755 --- a/drivers/video/rockchip/hdmi/rk_hdmi_task.c +++ b/drivers/video/rockchip/hdmi/rk_hdmi_task.c @@ -2,7 +2,7 @@ #include #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); } -- 2.34.1