mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 21:07:02 +09:00
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.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,157 +0,0 @@
|
||||
#include <linux/delay.h>
|
||||
#include <asm/io.h>
|
||||
#include <mach/io.h>
|
||||
#include "../rk30_hdmi.h"
|
||||
#include "../rk30_hdmi_hw.h"
|
||||
#include "rk30_hdmi_hdcp.h"
|
||||
|
||||
static void rk30_hdcp_write_mem(int addr_8, char value)
|
||||
{
|
||||
int temp;
|
||||
int addr_32 = addr_8 - addr_8%4;
|
||||
int shift = (addr_8%4) * 8;
|
||||
|
||||
temp = HDMIRdReg(addr_32);
|
||||
temp &= ~(0xff << shift);
|
||||
temp |= value << shift;
|
||||
// printk("temp is %08x\n", temp);
|
||||
HDMIWrReg(addr_32, temp);
|
||||
}
|
||||
|
||||
int rk30_hdcp_load_key2mem(struct hdcp_keys *key)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(key == NULL) return HDMI_ERROR_FALSE;
|
||||
|
||||
HDMIWrReg(0x800, HDMI_INTERANL_CLK_DIV);
|
||||
|
||||
for(i = 0; i < 7; i++)
|
||||
rk30_hdcp_write_mem(HDCP_RAM_KEY_KSV1 + i, key->KSV[i]);
|
||||
for(i = 0; i < 7; i++)
|
||||
rk30_hdcp_write_mem(HDCP_RAM_KEY_KSV2 + i, key->KSV[i]);
|
||||
for(i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++)
|
||||
rk30_hdcp_write_mem(HDCP_RAM_KEY_PRIVATE + i, key->DeviceKey[i]);
|
||||
for(i = 0; i < HDCP_KEY_SHA_SIZE; i++)
|
||||
rk30_hdcp_write_mem(HDCP_RAM_KEY_PRIVATE + HDCP_PRIVATE_KEY_SIZE + i, key->sha1[i]);
|
||||
|
||||
HDMIWrReg(0x800, HDMI_INTERANL_CLK_DIV | 0x20);
|
||||
return HDCP_OK;
|
||||
}
|
||||
|
||||
void rk30_hdcp_disable(void)
|
||||
{
|
||||
int temp;
|
||||
// Diable HDCP Interrupt
|
||||
HDMIWrReg(INTR_MASK2, 0x00);
|
||||
// Stop and Reset HDCP
|
||||
HDMIMskReg(temp, HDCP_CTRL, m_HDCP_FRAMED_ENCRYPED | m_HDCP_AUTH_STOP | m_HDCP_RESET,
|
||||
v_HDCP_FRAMED_ENCRYPED(0) | v_HDCP_AUTH_STOP(1) | v_HDCP_RESET(1) );
|
||||
}
|
||||
|
||||
static int rk30_hdcp_load_key(void)
|
||||
{
|
||||
int value, temp = 0;
|
||||
|
||||
if(hdcp->keys == NULL) {
|
||||
pr_err("[%s] HDCP key not loaded.\n", __FUNCTION__);
|
||||
return HDCP_KEY_ERR;
|
||||
}
|
||||
|
||||
value = HDMIRdReg(HDCP_KEY_MEM_CTRL);
|
||||
//Check HDCP key loaded from external HDCP memory
|
||||
while((value & (m_KSV_VALID | m_KEY_VALID | m_KEY_READY)) != (m_KSV_VALID | m_KEY_VALID | m_KEY_READY)) {
|
||||
if(temp > 10) {
|
||||
pr_err("[%s] loaded hdcp key is incorrectable %02x\n", __FUNCTION__, value & 0xFF);
|
||||
return HDCP_KEY_ERR;
|
||||
}
|
||||
//Load HDCP Key from external HDCP memory
|
||||
HDMIWrReg(HDCP_KEY_ACCESS_CTRL2, m_LOAD_HDCP_KEY);
|
||||
msleep(1);
|
||||
value = HDMIRdReg(HDCP_KEY_MEM_CTRL);
|
||||
temp++;
|
||||
}
|
||||
|
||||
return HDCP_OK;
|
||||
}
|
||||
|
||||
|
||||
int rk30_hdcp_start_authentication(void)
|
||||
{
|
||||
int rc, temp;
|
||||
|
||||
rc = rk30_hdcp_load_key();
|
||||
if(rc != HDCP_OK)
|
||||
return rc;
|
||||
|
||||
// Set 100ms & 5 sec timer
|
||||
switch(hdmi->vic)
|
||||
{
|
||||
case HDMI_720x576p_50Hz_4_3:
|
||||
case HDMI_720x576p_50Hz_16_9:
|
||||
case HDMI_1280x720p_50Hz:
|
||||
case HDMI_1920x1080i_50Hz:
|
||||
case HDMI_720x576i_50Hz_4_3:
|
||||
case HDMI_720x576i_50Hz_16_9:
|
||||
case HDMI_1920x1080p_50Hz:
|
||||
HDMIWrReg(HDCP_TIMER_100MS, 5);
|
||||
HDMIWrReg(HDCP_TIMER_5S, 250);
|
||||
break;
|
||||
|
||||
default:
|
||||
HDMIWrReg(HDCP_TIMER_100MS, 0x26);
|
||||
HDMIWrReg(HDCP_TIMER_5S, 0x2c);
|
||||
break;
|
||||
}
|
||||
// Config DDC Clock
|
||||
temp = (hdmi->tmdsclk/HDCP_DDC_CLK)/4;
|
||||
HDMIWrReg(DDC_BUS_FREQ_L, temp & 0xFF);
|
||||
HDMIWrReg(DDC_BUS_FREQ_H, (temp >> 8) & 0xFF);
|
||||
// Enable HDCP Interrupt
|
||||
HDMIWrReg(INTR_MASK2, m_INT_HDCP_ERR | m_INT_BKSV_RPRDY | m_INT_BKSV_RCRDY | m_INT_AUTH_DONE | m_INT_AUTH_READY);
|
||||
// Start HDCP
|
||||
HDMIMskReg(temp, HDCP_CTRL, m_HDCP_AUTH_START | m_HDCP_FRAMED_ENCRYPED, v_HDCP_AUTH_START(1) | v_HDCP_FRAMED_ENCRYPED(0));
|
||||
|
||||
return HDCP_OK;
|
||||
}
|
||||
|
||||
int rk30_hdcp_check_bksv(void)
|
||||
{
|
||||
int i, temp;
|
||||
char bksv[5];
|
||||
char *invalidkey;
|
||||
|
||||
temp = HDMIRdReg(HDCP_BCAPS);
|
||||
DBG("Receiver capacity is 0x%02x", temp);
|
||||
|
||||
#ifdef DEBUG
|
||||
if(temp & m_HDMI_RECEIVED)
|
||||
DBG("Receiver support HDMI");
|
||||
if(temp & m_REPEATER)
|
||||
DBG("Receiver is a repeater");
|
||||
if(temp & m_DDC_FAST)
|
||||
DBG("Receiver support 400K DDC");
|
||||
if(temp & m_1_1_FEATURE)
|
||||
DBG("Receiver support 1.1 features, such as advanced cipher, EESS.");
|
||||
if(temp & m_FAST_REAUTHENTICATION)
|
||||
DBG("Receiver support fast reauthentication.");
|
||||
#endif
|
||||
|
||||
for(i = 0; i < 5; i++) {
|
||||
bksv[i] = HDMIRdReg(HDCP_KSV_BYTE0 + (4 - i)*4) & 0xFF;
|
||||
}
|
||||
|
||||
DBG("bksv is 0x%02x%02x%02x%02x%02x", bksv[0], bksv[1], bksv[2], bksv[3], bksv[4]);
|
||||
|
||||
for(i = 0; i < hdcp->invalidkey; i++)
|
||||
{
|
||||
invalidkey = hdcp->invalidkeys + i *5;
|
||||
if(memcmp(bksv, invalidkey, 5) == 0) {
|
||||
printk(KERN_ERR "HDCP: BKSV was revocated!!!\n");
|
||||
HDMIMskReg(temp, HDCP_CTRL, m_HDCP_BKSV_FAILED | m_HDCP_FRAMED_ENCRYPED, v_HDCP_BKSV_FAILED(1) | v_HDCP_FRAMED_ENCRYPED(0));
|
||||
return HDCP_KSV_ERR;
|
||||
}
|
||||
}
|
||||
HDMIMskReg(temp, HDCP_CTRL, m_HDCP_BKSV_PASS | m_HDCP_FRAMED_ENCRYPED, v_HDCP_BKSV_PASS(1) | v_HDCP_FRAMED_ENCRYPED(1));
|
||||
return HDCP_OK;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -5,9 +5,8 @@
|
||||
#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"
|
||||
#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);
|
||||
module_init(rk2928_hdcp_init);
|
||||
module_exit(rk2928_hdcp_exit);
|
||||
190
drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdcp.h
Executable file
190
drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdcp.h
Executable file
@@ -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__ */
|
||||
@@ -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));
|
||||
|
||||
135
drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hdcp.c
Executable file
135
drivers/video/rockchip/hdmi/chips/rk2928/rk2928_hdmi_hdcp.c
Executable file
@@ -0,0 +1,135 @@
|
||||
#include <linux/delay.h>
|
||||
#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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
@@ -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/
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include "rk_hdmi.h"
|
||||
|
||||
#ifdef CONFIG_HDMI_RK30_CTL_CODEC
|
||||
#ifdef CONFIG_RK_HDMI_CTL_CODEC
|
||||
extern void codec_set_spk(bool on);
|
||||
#endif
|
||||
|
||||
@@ -80,12 +80,12 @@ void hdmi_sys_remove(void)
|
||||
memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
|
||||
INIT_LIST_HEAD(&hdmi->edid.modelist);
|
||||
hdmi->display = HDMI_DISABLE;
|
||||
rk_fb_switch_screen(hdmi->lcdc->screen1, 0, HDMI_SOURCE_DEFAULT);
|
||||
rk_fb_switch_screen(hdmi->lcdc->screen1, 0, hdmi->lcdc->id);
|
||||
kobject_uevent_env(&hdmi->dev->kobj, KOBJ_REMOVE, envp);
|
||||
#ifdef CONFIG_SWITCH
|
||||
switch_set_state(&(hdmi->switch_hdmi), 0);
|
||||
#endif
|
||||
#ifdef CONFIG_HDMI_RK30_CTL_CODEC
|
||||
#ifdef CONFIG_RK_HDMI_CTL_CODEC
|
||||
codec_set_spk(1);
|
||||
#endif
|
||||
}
|
||||
@@ -96,7 +96,7 @@ static void hdmi_sys_sleep(void)
|
||||
if(hdmi->enable)
|
||||
disable_irq(hdmi->irq);
|
||||
hdmi->state = HDMI_SLEEP;
|
||||
hdmi->hdmi_removed();
|
||||
hdmi->remove();
|
||||
if(hdmi->enable)
|
||||
enable_irq(hdmi->irq);
|
||||
mutex_unlock(&hdmi->enable_mutex);
|
||||
@@ -121,7 +121,7 @@ static int hdmi_process_command(void)
|
||||
hdmi_sys_remove();
|
||||
hdmi->state = HDMI_SLEEP;
|
||||
hdmi->hotplug = HDMI_HPD_REMOVED;
|
||||
hdmi->hdmi_removed();
|
||||
hdmi->remove();
|
||||
state = HDMI_SLEEP;
|
||||
}
|
||||
mutex_unlock(&hdmi->enable_mutex);
|
||||
@@ -183,6 +183,8 @@ void hdmi_work(struct work_struct *work)
|
||||
if(hotplug != hdmi->hotplug)
|
||||
{
|
||||
if(hotplug == HDMI_HPD_ACTIVED){
|
||||
if(hdmi->insert)
|
||||
hdmi->insert();
|
||||
hdmi->state = READ_PARSE_EDID;
|
||||
}
|
||||
else if(hdmi->hotplug == HDMI_HPD_ACTIVED) {
|
||||
@@ -192,7 +194,7 @@ void hdmi_work(struct work_struct *work)
|
||||
hdmi_sys_sleep();
|
||||
else {
|
||||
hdmi->state = WAIT_HOTPLUG;
|
||||
hdmi->hdmi_removed();
|
||||
hdmi->remove();
|
||||
}
|
||||
if(hdmi->wait == 1) {
|
||||
complete(&hdmi->complete);
|
||||
@@ -203,7 +205,7 @@ void hdmi_work(struct work_struct *work)
|
||||
}
|
||||
else if(hotplug == HDMI_HPD_REMOVED) {
|
||||
hdmi->state = HDMI_SLEEP;
|
||||
hdmi->hdmi_removed();
|
||||
hdmi->remove();
|
||||
}
|
||||
hdmi->hotplug = hotplug;
|
||||
}
|
||||
@@ -224,7 +226,7 @@ void hdmi_work(struct work_struct *work)
|
||||
#ifdef CONFIG_SWITCH
|
||||
switch_set_state(&(hdmi->switch_hdmi), 1);
|
||||
#endif
|
||||
#ifdef CONFIG_HDMI_RK30_CTL_CODEC
|
||||
#ifdef CONFIG_RK_HDMI_CTL_CODEC
|
||||
codec_set_spk(0);
|
||||
#endif
|
||||
}
|
||||
@@ -297,15 +299,6 @@ void hdmi_work(struct work_struct *work)
|
||||
|
||||
}while((hdmi->state != state_last || (rc != HDMI_ERROR_SUCESS) ) && trytimes < HDMI_MAX_TRY_TIMES);
|
||||
|
||||
// if(trytimes == HDMI_MAX_TRY_TIMES)
|
||||
// {
|
||||
// if(hdmi->hotplug) {
|
||||
// hdmi_sys_remove();
|
||||
// hdmi->hotplug = HDMI_HPD_REMOVED;
|
||||
// hdmi_sys_sleep();
|
||||
//
|
||||
// }
|
||||
// }
|
||||
hdmi_dbg(hdmi->dev, "[%s] done\n", __FUNCTION__);
|
||||
mutex_unlock(&work_mutex);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user