HDMI: rk3368: add function for HDCP2.2.

Signed-off-by: Zheng Yang <zhengyang@rock-chips.com>
This commit is contained in:
Zheng Yang
2015-04-28 19:17:27 +08:00
parent 5f3c54f3cb
commit 61d46c90ee
5 changed files with 98 additions and 13 deletions

View File

@@ -250,6 +250,9 @@ static int rockchip_hdmiv2_fb_event_notify(struct notifier_block *self,
struct hdmi *hdmi = hdmi_dev->hdmi;
struct delayed_work *delay_work;
struct pinctrl_state *gpio_state;
#ifdef CONFIG_PINCTRL
struct dev_pin_info *pins = hdmi_dev->dev->pins;
#endif
if (action == FB_EARLY_EVENT_BLANK) {
switch (blank_mode) {
@@ -264,9 +267,16 @@ 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);
gpio_state = pinctrl_lookup_state(hdmi_dev->dev->pins->p, "gpio");
pinctrl_select_state(hdmi_dev->dev->pins->p, gpio_state);
#ifdef CONFIG_PINCTRL
gpio_state =
pinctrl_lookup_state(pins->p,
"gpio");
pinctrl_select_state(pins->p,
gpio_state);
#endif
}
break;
}
@@ -275,12 +285,18 @@ static int rockchip_hdmiv2_fb_event_notify(struct notifier_block *self,
case FB_BLANK_UNBLANK:
HDMIDBG("resume hdmi\n");
if (hdmi->sleep) {
pinctrl_select_state(hdmi_dev->dev->pins->p,
hdmi_dev->dev->pins->default_state);
#ifdef CONFIG_PINCTRL
pinctrl_select_state(pins->p,
pins->default_state);
#endif
rockchip_hdmiv2_clk_enable(hdmi_dev);
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)
{
@@ -111,6 +111,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;
@@ -118,11 +164,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,
@@ -146,6 +200,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__);
}
@@ -160,6 +216,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,
@@ -296,4 +353,3 @@ void rockchip_hdmiv2_hdcp_init(struct hdmi *hdmi)
else
hdcp_load_key(hdmi, hdcp->keys);
}

View File

@@ -1511,8 +1511,8 @@ static int hdmi_dev_config_audio(struct hdmi *hdmi, struct hdmi_audio *audio)
HDMIDBG("hbr mode.\n");
hdmi_writel(hdmi_dev, AUD_CONF2, 0x1);
word_length = I2S_24BIT_SAMPLE;
} else if ((HDMI_AUDIO_FS_48000 == audio->rate)
|| (HDMI_AUDIO_FS_192000 == audio->rate)) {
} else if ((HDMI_AUDIO_FS_48000 == audio->rate) ||
(HDMI_AUDIO_FS_192000 == audio->rate)) {
HDMIDBG("nlpcm mode.\n");
hdmi_writel(hdmi_dev, AUD_CONF2, 0x2);
word_length = I2S_24BIT_SAMPLE;
@@ -1751,6 +1751,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