HDMI: rk3368: add function for HDCP2.2.

Signed-off-by: Zheng Yang <zhengyang@rock-chips.com>

Conflicts:
	drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2.c
	drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_hw.c
This commit is contained in:
Zheng Yang
2015-04-28 19:17:27 +08:00
parent 597b7c2119
commit fd18799864
5 changed files with 82 additions and 7 deletions

View File

@@ -268,6 +268,8 @@ static int rockchip_hdmiv2_fb_event_notify(struct notifier_block *self,
0, NULL);
if (delay_work)
flush_delayed_work(delay_work);
if (hdmi_dev->hdcp2_en)
hdmi_dev->hdcp2_en(0);
rockchip_hdmiv2_clk_disable(hdmi_dev);
#ifdef CONFIG_PINCTRL
if (hdmi_dev->soctype == HDMI_SOC_RK3288)
@@ -297,6 +299,10 @@ static int rockchip_hdmiv2_fb_event_notify(struct notifier_block *self,
rockchip_hdmiv2_dev_initial(hdmi_dev);
if (hdmi->ops->hdcp_power_on_cb)
hdmi->ops->hdcp_power_on_cb();
if (hdmi_dev->hdcp2_reset)
hdmi_dev->hdcp2_reset();
if (hdmi_dev->hdcp2_en)
hdmi_dev->hdcp2_en(1);
hdmi_submit_work(hdmi, HDMI_RESUME_CTL,
0, NULL);
}

View File

@@ -38,6 +38,7 @@ struct hdmi_dev {
int soctype;
int audiosrc;
int enable;
int hdcp2_enable;
unsigned char clk_disable;
unsigned char clk_on;
@@ -48,5 +49,9 @@ struct hdmi_dev {
bool tmdsclk_ratio_change;
struct mutex ddc_lock; /*mutex for ddc operation */
void (*hdcp2_en)(int);
void (*hdcp2_reset)(void);
void (*hdcp2_start)(void);
};
#endif /*__RK32_HDMI_H__*/

View File

@@ -30,7 +30,7 @@ struct hdcp {
};
static struct miscdevice mdev;
static struct hdcp *hdcp = NULL;
static struct hdcp *hdcp;
static void hdcp_load_key(struct hdmi *hdmi, struct hdcp_keys *key)
{
@@ -115,6 +115,52 @@ static void hdcp_load_keys_cb(const struct firmware *fw,
hdcp_load_key(hdmi, hdcp->keys);
}
void rockchip_hdmiv2_hdcp2_enable(int enable)
{
struct hdmi_dev *hdmi_dev;
if (!hdcp) {
pr_err("rockchip hdmiv2 hdcp is not exist\n");
return;
}
hdmi_dev = hdcp->hdmi->property->priv;
if (hdmi_dev->soctype == HDMI_SOC_RK3368 &&
hdmi_dev->hdcp2_enable != enable) {
hdmi_dev->hdcp2_enable = enable;
if (hdmi_dev->hdcp2_enable == 0) {
hdmi_msk_reg(hdmi_dev, HDCP2REG_CTRL,
m_HDCP2_OVR_EN | m_HDCP2_FORCE,
v_HDCP2_OVR_EN(1) | v_HDCP2_FORCE(0));
hdmi_writel(hdmi_dev, HDCP2REG_MASK, 0xff);
hdmi_writel(hdmi_dev, HDCP2REG_MUTE, 0xff);
} else {
hdmi_msk_reg(hdmi_dev, HDCP2REG_CTRL,
m_HDCP2_OVR_EN | m_HDCP2_FORCE,
v_HDCP2_OVR_EN(0) | v_HDCP2_FORCE(0));
hdmi_writel(hdmi_dev, HDCP2REG_MASK, 0x00);
hdmi_writel(hdmi_dev, HDCP2REG_MUTE, 0x00);
}
}
}
EXPORT_SYMBOL(rockchip_hdmiv2_hdcp2_enable);
void rockchip_hdmiv2_hdcp2_init(void (*hdcp2_enble)(int),
void (*hdcp2_reset)(void),
void (*hdcp2_start)(void))
{
struct hdmi_dev *hdmi_dev;
if (!hdcp) {
pr_err("rockchip hdmiv2 hdcp is not exist\n");
return;
}
hdmi_dev = hdcp->hdmi->property->priv;
hdmi_dev->hdcp2_en = hdcp2_enble;
hdmi_dev->hdcp2_reset = hdcp2_reset;
hdmi_dev->hdcp2_start = hdcp2_start;
}
EXPORT_SYMBOL(rockchip_hdmiv2_hdcp2_init);
static void rockchip_hdmiv2_hdcp_start(struct hdmi *hdmi)
{
struct hdmi_dev *hdmi_dev = hdmi->property->priv;
@@ -122,11 +168,19 @@ static void rockchip_hdmiv2_hdcp_start(struct hdmi *hdmi)
if (!hdcp->enable)
return;
if (hdmi_dev->soctype == HDMI_SOC_RK3368) {
hdmi_msk_reg(hdmi_dev, HDCP2REG_CTRL,
m_HDCP2_OVR_EN | m_HDCP2_FORCE,
v_HDCP2_OVR_EN(1) | v_HDCP2_FORCE(0));
hdmi_writel(hdmi_dev, HDCP2REG_MASK, 0x00);
hdmi_writel(hdmi_dev, HDCP2REG_MUTE, 0x00);
if (hdmi_dev->hdcp2_enable == 0) {
hdmi_msk_reg(hdmi_dev, HDCP2REG_CTRL,
m_HDCP2_OVR_EN | m_HDCP2_FORCE,
v_HDCP2_OVR_EN(1) | v_HDCP2_FORCE(0));
hdmi_writel(hdmi_dev, HDCP2REG_MASK, 0xff);
hdmi_writel(hdmi_dev, HDCP2REG_MUTE, 0xff);
} else {
hdmi_msk_reg(hdmi_dev, HDCP2REG_CTRL,
m_HDCP2_OVR_EN | m_HDCP2_FORCE,
v_HDCP2_OVR_EN(0) | v_HDCP2_FORCE(0));
hdmi_writel(hdmi_dev, HDCP2REG_MASK, 0x00);
hdmi_writel(hdmi_dev, HDCP2REG_MUTE, 0x00);
}
}
hdmi_msk_reg(hdmi_dev, FC_INVIDCONF,
@@ -151,6 +205,8 @@ static void rockchip_hdmiv2_hdcp_start(struct hdmi *hdmi)
hdmi_msk_reg(hdmi_dev, MC_CLKDIS,
m_HDCPCLK_DISABLE, v_HDCPCLK_DISABLE(0));
if (hdmi_dev->hdcp2_start)
hdmi_dev->hdcp2_start();
pr_info("%s success\n", __func__);
}
@@ -165,6 +221,7 @@ static void rockchip_hdmiv2_hdcp_stop(struct hdmi *hdmi)
m_HDCPCLK_DISABLE, v_HDCPCLK_DISABLE(1));
hdmi_writel(hdmi_dev, A_APIINTMSK, 0xff);
hdmi_msk_reg(hdmi_dev, A_HDCPCFG0, m_RX_DETECT, v_RX_DETECT(0));
rockchip_hdmiv2_hdcp2_enable(0);
}
static ssize_t hdcp_enable_read(struct device *device,
@@ -306,4 +363,3 @@ void rockchip_hdmiv2_hdcp_init(struct hdmi *hdmi)
else
hdcp_load_key(hdmi, hdcp->keys);
}

View File

@@ -1740,6 +1740,12 @@ irqreturn_t rockchip_hdmiv2_dev_irq(int irq, void *priv)
if (hdcp2_int) {
hdmi_writel(hdmi_dev, HDCP2REG_STAT, hdcp2_int);
pr_info("hdcp2_int is 0x%02x\n", hdcp2_int);
if ((hdcp2_int & m_HDCP2_AUTH_FAIL ||
hdcp2_int & m_HDCP2_AUTH_LOST) &&
hdmi_dev->hdcp2_start) {
pr_info("hdcp2 failed or lost\n");
hdmi_dev->hdcp2_start();
}
}
return IRQ_HANDLED;
}

View File

@@ -1314,6 +1314,7 @@ enum {
#define m_HDCP2_AUTH_LOST (1 << 2)
#define m_HDCP2_AUTH_OK (1 << 3)
#define m_HDCP2_AUTH_FAIL (1 << 4)
#define m_HDCP2_DECRYPTED_CHG (1 << 5)
/* CEC Engine Registers */
#define CEC_ENGINE_BASE 0x7d00
@@ -1565,4 +1566,5 @@ void rockchip_hdmiv2_cec_init(struct hdmi *hdmi);
void rockchip_hdmiv2_cec_isr(struct hdmi_dev *hdmi_dev, char cec_int);
void rockchip_hdmiv2_dump_phy_regs(struct hdmi_dev *hdmi_dev);
void rockchip_hdmiv2_hdcp_init(struct hdmi *hdmi);
void rockchip_hdmiv2_hdcp2_enable(int enable);
#endif