msm_fb: HDMI: Driver changes to support HDCP module parameter

This change removes the need to use HDCP feature flags in the
HDMI driver and adds the necessary support to configure HDCP
feature based on a module parameter.

Change-Id: Ie0eacc5b447230927cfdedfcb979c22d60e81981
Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
This commit is contained in:
Aravind Venkateswaran 2012-09-07 16:08:10 -07:00 committed by Stephen Boyd
parent 7244a2bd88
commit ef2a73fc6d
2 changed files with 217 additions and 178 deletions

View file

@ -70,12 +70,7 @@ static DEFINE_MUTEX(hdcp_auth_state_mutex);
static void hdmi_msm_dump_regs(const char *prefix);
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
static void hdmi_msm_hdcp_enable(void);
#else
static inline void hdmi_msm_hdcp_enable(void) {}
#endif
static void hdmi_msm_turn_on(void);
static int hdmi_msm_audio_off(void);
static int hdmi_msm_read_edid(void);
@ -679,7 +674,6 @@ const char *hdmi_msm_name(uint32 offset)
case 0x00D8: return "ACR_48_1";
case 0x00E4: return "AUDIO_INFO0";
case 0x00E8: return "AUDIO_INFO1";
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
case 0x0110: return "HDCP_CTRL";
case 0x0114: return "HDCP_DEBUG_CTRL";
case 0x0118: return "HDCP_INT_CTRL";
@ -694,7 +688,6 @@ const char *hdmi_msm_name(uint32 offset)
case 0x014C: return "HDCP_RCVPORT_DATA5";
case 0x0150: return "HDCP_RCVPORT_DATA6";
case 0x0168: return "HDCP_RCVPORT_DATA12";
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
case 0x01D0: return "AUDIO_CFG";
case 0x0208: return "USEC_REFTIMER";
case 0x020C: return "DDC_CTRL";
@ -709,14 +702,10 @@ const char *hdmi_msm_name(uint32 offset)
case 0x0250: return "HPD_INT_STATUS";
case 0x0254: return "HPD_INT_CTRL";
case 0x0258: return "HPD_CTRL";
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
case 0x025C: return "HDCP_ENTROPY_CTRL1";
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
case 0x027C: return "DDC_REF";
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
case 0x0284: return "HDCP_SW_UPPER_AKSV";
case 0x0288: return "HDCP_SW_LOWER_AKSV";
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
case 0x02B4: return "ACTIVE_H";
case 0x02B8: return "ACTIVE_V";
case 0x02BC: return "ACTIVE_V_F2";
@ -785,7 +774,7 @@ static void hdmi_msm_send_event(boolean on)
DEV_INFO("HDMI HPD: CONNECTED: send ONLINE\n");
kobject_uevent(external_common_state->uevent_kobj, KOBJ_ONLINE);
if (!external_common_state->present_hdcp) {
if (!hdmi_msm_state->hdcp_enable) {
/* Send Audio for HDMI Compliance Cases*/
envp[0] = "HDCP_STATE=PASS";
envp[1] = NULL;
@ -874,10 +863,13 @@ static void hdmi_msm_cec_latch_work(struct work_struct *work)
}
#endif
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
static void hdcp_deauthenticate(void);
static void hdmi_msm_hdcp_reauth_work(struct work_struct *work)
{
if (!hdmi_msm_state->hdcp_enable) {
DEV_DBG("%s: HDCP not enabled\n", __func__);
return;
}
/* Don't process recursive actions */
mutex_lock(&hdmi_msm_state_mutex);
@ -895,17 +887,20 @@ static void hdmi_msm_hdcp_reauth_work(struct work_struct *work)
* Therefore, as surprising as it may sound do reauth
* only if the device is HDCP-capable
*/
if (external_common_state->present_hdcp) {
hdcp_deauthenticate();
mutex_lock(&hdcp_auth_state_mutex);
hdmi_msm_state->reauth = TRUE;
mutex_unlock(&hdcp_auth_state_mutex);
mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
}
hdcp_deauthenticate();
mutex_lock(&hdcp_auth_state_mutex);
hdmi_msm_state->reauth = TRUE;
mutex_unlock(&hdcp_auth_state_mutex);
mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
}
static void hdmi_msm_hdcp_work(struct work_struct *work)
{
if (!hdmi_msm_state->hdcp_enable) {
DEV_DBG("%s: HDCP not enabled\n", __func__);
return;
}
/* Only re-enable if cable still connected */
mutex_lock(&external_common_state_hpd_mutex);
if (external_common_state->hpd_state &&
@ -926,7 +921,111 @@ static void hdmi_msm_hdcp_work(struct work_struct *work)
hdmi_msm_state->reauth = FALSE;
}
}
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
int hdmi_msm_process_hdcp_interrupts(void)
{
int rc = -1;
uint32 hdcp_int_val;
char *envp[2];
if (!hdmi_msm_state->hdcp_enable) {
DEV_DBG("%s: HDCP not enabled\n", __func__);
return -EINVAL;
}
/* HDCP_INT_CTRL[0x0118]
* [0] AUTH_SUCCESS_INT [R] HDCP Authentication Success
* interrupt status
* [1] AUTH_SUCCESS_ACK [W] Acknowledge bit for HDCP
* Authentication Success bit - write 1 to clear
* [2] AUTH_SUCCESS_MASK [R/W] Mask bit for HDCP Authentication
* Success interrupt - set to 1 to enable interrupt */
hdcp_int_val = HDMI_INP_ND(0x0118);
if ((hdcp_int_val & (1 << 2)) && (hdcp_int_val & (1 << 0))) {
/* AUTH_SUCCESS_INT */
HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 1)) & ~(1 << 0));
DEV_INFO("HDCP: AUTH_SUCCESS_INT received\n");
complete_all(&hdmi_msm_state->hdcp_success_done);
return 0;
}
/* [4] AUTH_FAIL_INT [R] HDCP Authentication Lost
* interrupt Status
* [5] AUTH_FAIL_ACK [W] Acknowledge bit for HDCP
* Authentication Lost bit - write 1 to clear
* [6] AUTH_FAIL_MASK [R/W] Mask bit fo HDCP Authentication
* Lost interrupt set to 1 to enable interrupt
* [7] AUTH_FAIL_INFO_ACK [W] Acknowledge bit for HDCP
* Authentication Failure Info field - write 1 to clear */
if ((hdcp_int_val & (1 << 6)) && (hdcp_int_val & (1 << 4))) {
/* AUTH_FAIL_INT */
/* Clear and Disable */
uint32 link_status = HDMI_INP_ND(0x011C);
HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 5))
& ~((1 << 6) | (1 << 4)));
DEV_INFO("HDCP: AUTH_FAIL_INT received, LINK0_STATUS=0x%08x\n",
link_status);
if (hdmi_msm_state->full_auth_done) {
switch_set_state(&external_common_state->sdev, 0);
DEV_INFO("Hdmi state switched to %d: %s\n",
external_common_state->sdev.state, __func__);
envp[0] = "HDCP_STATE=FAIL";
envp[1] = NULL;
DEV_INFO("HDMI HPD:QDSP OFF\n");
kobject_uevent_env(external_common_state->uevent_kobj,
KOBJ_CHANGE, envp);
mutex_lock(&hdcp_auth_state_mutex);
hdmi_msm_state->full_auth_done = FALSE;
mutex_unlock(&hdcp_auth_state_mutex);
/* Calling reauth only when authentication
* is sucessful or else we always go into
* the reauth loop. Also, No need to reauthenticate
* if authentication failed because of cable disconnect
*/
if (((link_status & 0xF0) >> 4) != 0x7) {
DEV_DBG("Reauthenticate From %s HDCP FAIL INT ",
__func__);
queue_work(hdmi_work_queue,
&hdmi_msm_state->hdcp_reauth_work);
} else {
DEV_INFO("HDCP: HDMI cable disconnected\n");
}
}
/* Clear AUTH_FAIL_INFO as well */
HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 7)));
return 0;
}
/* [8] DDC_XFER_REQ_INT [R] HDCP DDC Transfer Request
* interrupt status
* [9] DDC_XFER_REQ_ACK [W] Acknowledge bit for HDCP DDC
* Transfer Request bit - write 1 to clear
* [10] DDC_XFER_REQ_MASK [R/W] Mask bit for HDCP DDC Transfer
* Request interrupt - set to 1 to enable interrupt */
if ((hdcp_int_val & (1 << 10)) && (hdcp_int_val & (1 << 8))) {
/* DDC_XFER_REQ_INT */
HDMI_OUTP_ND(0x0118, (hdcp_int_val | (1 << 9)) & ~(1 << 8));
if (!(hdcp_int_val & (1 << 12)))
return 0;
}
/* [12] DDC_XFER_DONE_INT [R] HDCP DDC Transfer done interrupt
* status
* [13] DDC_XFER_DONE_ACK [W] Acknowledge bit for HDCP DDC
* Transfer done bit - write 1 to clear
* [14] DDC_XFER_DONE_MASK [R/W] Mask bit for HDCP DDC Transfer
* done interrupt - set to 1 to enable interrupt */
if ((hdcp_int_val & (1 << 14)) && (hdcp_int_val & (1 << 12))) {
/* DDC_XFER_DONE_INT */
HDMI_OUTP_ND(0x0118, (hdcp_int_val | (1 << 13)) & ~(1 << 12));
DEV_INFO("HDCP: DDC_XFER_DONE received\n");
return 0;
}
return rc;
}
static irqreturn_t hdmi_msm_isr(int irq, void *dev_id)
{
@ -937,10 +1036,6 @@ static irqreturn_t hdmi_msm_isr(int irq, void *dev_id)
#endif
uint32 ddc_int_ctrl;
uint32 audio_int_val;
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
uint32 hdcp_int_val;
char *envp[2];
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
static uint32 fifo_urun_int_occurred;
static uint32 sample_drop_int_occurred;
const uint32 occurrence_limit = 5;
@ -1058,96 +1153,8 @@ static irqreturn_t hdmi_msm_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
/* HDCP_INT_CTRL[0x0118]
* [0] AUTH_SUCCESS_INT [R] HDCP Authentication Success
* interrupt status
* [1] AUTH_SUCCESS_ACK [W] Acknowledge bit for HDCP
* Authentication Success bit - write 1 to clear
* [2] AUTH_SUCCESS_MASK [R/W] Mask bit for HDCP Authentication
* Success interrupt - set to 1 to enable interrupt */
hdcp_int_val = HDMI_INP_ND(0x0118);
if ((hdcp_int_val & (1 << 2)) && (hdcp_int_val & (1 << 0))) {
/* AUTH_SUCCESS_INT */
HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 1)) & ~(1 << 0));
DEV_INFO("HDCP: AUTH_SUCCESS_INT received\n");
complete_all(&hdmi_msm_state->hdcp_success_done);
if (!hdmi_msm_process_hdcp_interrupts())
return IRQ_HANDLED;
}
/* [4] AUTH_FAIL_INT [R] HDCP Authentication Lost
* interrupt Status
* [5] AUTH_FAIL_ACK [W] Acknowledge bit for HDCP
* Authentication Lost bit - write 1 to clear
* [6] AUTH_FAIL_MASK [R/W] Mask bit fo HDCP Authentication
* Lost interrupt set to 1 to enable interrupt
* [7] AUTH_FAIL_INFO_ACK [W] Acknowledge bit for HDCP
* Authentication Failure Info field - write 1 to clear */
if ((hdcp_int_val & (1 << 6)) && (hdcp_int_val & (1 << 4))) {
/* AUTH_FAIL_INT */
/* Clear and Disable */
uint32 link_status = HDMI_INP_ND(0x011C);
HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 5))
& ~((1 << 6) | (1 << 4)));
DEV_INFO("HDCP: AUTH_FAIL_INT received, LINK0_STATUS=0x%08x\n",
link_status);
if (hdmi_msm_state->full_auth_done) {
switch_set_state(&external_common_state->sdev, 0);
DEV_INFO("Hdmi state switched to %d: %s\n",
external_common_state->sdev.state, __func__);
envp[0] = "HDCP_STATE=FAIL";
envp[1] = NULL;
DEV_INFO("HDMI HPD:QDSP OFF\n");
kobject_uevent_env(external_common_state->uevent_kobj,
KOBJ_CHANGE, envp);
mutex_lock(&hdcp_auth_state_mutex);
hdmi_msm_state->full_auth_done = FALSE;
mutex_unlock(&hdcp_auth_state_mutex);
/* Calling reauth only when authentication
* is sucessful or else we always go into
* the reauth loop. Also, No need to reauthenticate
* if authentication failed because of cable disconnect
*/
if (((link_status & 0xF0) >> 4) != 0x7) {
DEV_DBG("Reauthenticate From %s HDCP FAIL INT ",
__func__);
queue_work(hdmi_work_queue,
&hdmi_msm_state->hdcp_reauth_work);
} else {
DEV_INFO("HDCP: HDMI cable disconnected\n");
}
}
/* Clear AUTH_FAIL_INFO as well */
HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 7)));
return IRQ_HANDLED;
}
/* [8] DDC_XFER_REQ_INT [R] HDCP DDC Transfer Request
* interrupt status
* [9] DDC_XFER_REQ_ACK [W] Acknowledge bit for HDCP DDC
* Transfer Request bit - write 1 to clear
* [10] DDC_XFER_REQ_MASK [R/W] Mask bit for HDCP DDC Transfer
* Request interrupt - set to 1 to enable interrupt */
if ((hdcp_int_val & (1 << 10)) && (hdcp_int_val & (1 << 8))) {
/* DDC_XFER_REQ_INT */
HDMI_OUTP_ND(0x0118, (hdcp_int_val | (1 << 9)) & ~(1 << 8));
if (!(hdcp_int_val & (1 << 12)))
return IRQ_HANDLED;
}
/* [12] DDC_XFER_DONE_INT [R] HDCP DDC Transfer done interrupt
* status
* [13] DDC_XFER_DONE_ACK [W] Acknowledge bit for HDCP DDC
* Transfer done bit - write 1 to clear
* [14] DDC_XFER_DONE_MASK [R/W] Mask bit for HDCP DDC Transfer
* done interrupt - set to 1 to enable interrupt */
if ((hdcp_int_val & (1 << 14)) && (hdcp_int_val & (1 << 12))) {
/* DDC_XFER_DONE_INT */
HDMI_OUTP_ND(0x0118, (hdcp_int_val | (1 << 13)) & ~(1 << 12));
DEV_INFO("HDCP: DDC_XFER_DONE received\n");
return IRQ_HANDLED;
}
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
/* Process CEC Interrupt */
@ -1306,7 +1313,7 @@ void hdmi_msm_set_mode(boolean power_on)
if (external_common_state->hdmi_sink == 0) {
/* HDMI_DVI_SEL */
reg_val |= 0x00000002;
if (external_common_state->present_hdcp)
if (hdmi_msm_state->hdcp_enable)
/* HDMI Encryption */
reg_val |= 0x00000004;
/* HDMI_CTRL */
@ -1314,7 +1321,7 @@ void hdmi_msm_set_mode(boolean power_on)
/* HDMI_DVI_SEL */
reg_val &= ~0x00000002;
} else {
if (external_common_state->present_hdcp)
if (hdmi_msm_state->hdcp_enable)
/* HDMI_Encryption_ON */
reg_val |= 0x00000006;
else
@ -1394,7 +1401,6 @@ static int hdmi_msm_ddc_clear_irq(const char *what)
return 0;
}
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
static int hdmi_msm_ddc_write(uint32 dev_addr, uint32 offset,
const uint8 *data_buf, uint32 data_len, const char *what)
{
@ -1590,7 +1596,6 @@ again:
error:
return status;
}
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
static int hdmi_msm_ddc_read_retry(uint32 dev_addr, uint32 offset,
uint8 *data_buf, uint32 data_len, uint32 request_len, int retry,
@ -2155,9 +2160,13 @@ error:
return status;
}
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
static void hdcp_auth_info(uint32 auth_info)
{
if (!hdmi_msm_state->hdcp_enable) {
DEV_DBG("%s: HDCP not enabled\n", __func__);
return;
}
switch (auth_info) {
case 0:
DEV_INFO("%s: None", __func__);
@ -2192,6 +2201,11 @@ static void hdcp_auth_info(uint32 auth_info)
static void hdcp_key_state(uint32 key_state)
{
if (!hdmi_msm_state->hdcp_enable) {
DEV_DBG("%s: HDCP not enabled\n", __func__);
return;
}
switch (key_state) {
case 0:
DEV_WARN("%s: No HDCP Keys", __func__);
@ -2235,6 +2249,11 @@ static void hdcp_deauthenticate(void)
{
int hdcp_link_status = HDMI_INP(0x011C);
if (!hdmi_msm_state->hdcp_enable) {
DEV_DBG("%s: HDCP not enabled\n", __func__);
return;
}
/* Disable HDCP interrupts */
HDMI_OUTP(0x0118, 0x0);
@ -2262,6 +2281,11 @@ static void check_and_clear_HDCP_DDC_Failure(void)
int failure;
int nack0;
if (!hdmi_msm_state->hdcp_enable) {
DEV_DBG("%s: HDCP not enabled\n", __func__);
return;
}
/*
* Check for any DDC transfer failures
* 0x0128 HDCP_DDC_STATUS
@ -2372,6 +2396,11 @@ static int hdcp_authentication_part1(void)
static uint8 buf[0xFF];
memset(buf, 0, sizeof(buf));
if (!hdmi_msm_state->hdcp_enable) {
DEV_DBG("%s: HDCP not enabled\n", __func__);
return 0;
}
if (!is_part1_done) {
is_part1_done = TRUE;
@ -2659,6 +2688,11 @@ static int hdmi_msm_transfer_v_h(void)
int ret;
uint8 buf[4];
if (!hdmi_msm_state->hdcp_enable) {
DEV_DBG("%s: HDCP not enabled\n", __func__);
return 0;
}
snprintf(what, sizeof(what), "V' H0");
ret = hdmi_msm_ddc_read(0x74, 0x20, buf, 4, 5, what, TRUE);
if (ret) {
@ -2751,6 +2785,11 @@ static int hdcp_authentication_part2(void)
boolean ksv_done = FALSE;
if (!hdmi_msm_state->hdcp_enable) {
DEV_DBG("%s: HDCP not enabled\n", __func__);
return 0;
}
memset(buf, 0, sizeof(buf));
memset(kvs_fifo, 0, sizeof(kvs_fifo));
@ -2943,6 +2982,12 @@ static int hdcp_authentication_part3(uint32 found_repeater)
{
int ret = 0;
int poll = 3000;
if (!hdmi_msm_state->hdcp_enable) {
DEV_DBG("%s: HDCP not enabled\n", __func__);
return 0;
}
while (poll) {
/* 0x011C HDCP_LINK0_STATUS
[30:28] KEYS_STATE = 3 = "Valid"
@ -2973,7 +3018,7 @@ static void hdmi_msm_hdcp_enable(void)
uint32 found_repeater = 0x0;
char *envp[2];
if (!hdmi_msm_has_hdcp()) {
if (!hdmi_msm_state->hdcp_enable) {
DEV_INFO("%s: HDCP NOT ENABLED\n", __func__);
return;
}
@ -3074,7 +3119,6 @@ error:
DEV_INFO("Hdmi state switched to %d: %s\n",
external_common_state->sdev.state, __func__);
}
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
static void hdmi_msm_video_setup(int video_format)
{
@ -3592,11 +3636,9 @@ void hdmi_msm_audio_sample_rate_reset(int rate)
{
msm_hdmi_sample_rate = rate;
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
if (hdmi_msm_has_hdcp())
if (hdmi_msm_state->hdcp_enable)
hdcp_deauthenticate();
else
#endif
hdmi_msm_turn_on();
}
EXPORT_SYMBOL(hdmi_msm_audio_sample_rate_reset);
@ -4166,12 +4208,10 @@ static void hdmi_msm_turn_on(void)
#endif
hdmi_msm_spd_infoframe_packetsetup();
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
if (hdmi_msm_state->reauth) {
if (hdmi_msm_state->hdcp_enable && hdmi_msm_state->reauth) {
hdmi_msm_hdcp_enable();
hdmi_msm_state->reauth = FALSE ;
}
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
/* re-initialize CEC if enabled */
@ -4216,12 +4256,15 @@ static void hdmi_msm_hpd_state_timer(unsigned long data)
}
}
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
static void hdmi_msm_hdcp_timer(unsigned long data)
{
if (!hdmi_msm_state->hdcp_enable) {
DEV_DBG("%s: HDCP not enabled\n", __func__);
return;
}
queue_work(hdmi_work_queue, &hdmi_msm_state->hdcp_work);
}
#endif
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
static void hdmi_msm_cec_read_timer_func(unsigned long data)
@ -4386,12 +4429,14 @@ static int hdmi_msm_power_on(struct platform_device *pdev)
mutex_unlock(&external_common_state_hpd_mutex);
hdmi_msm_turn_on();
/* Kick off HDCP Authentication */
mutex_lock(&hdcp_auth_state_mutex);
hdmi_msm_state->reauth = FALSE;
hdmi_msm_state->full_auth_done = FALSE;
mutex_unlock(&hdcp_auth_state_mutex);
mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
if (hdmi_msm_state->hdcp_enable) {
/* Kick off HDCP Authentication */
mutex_lock(&hdcp_auth_state_mutex);
hdmi_msm_state->reauth = FALSE;
hdmi_msm_state->full_auth_done = FALSE;
mutex_unlock(&hdcp_auth_state_mutex);
mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
}
} else
mutex_unlock(&external_common_state_hpd_mutex);
@ -4415,16 +4460,14 @@ void mhl_connect_api(boolean on)
external_common_state->sdev.state, __func__);
if (on) {
hdmi_msm_read_edid();
if (hdmi_msm_has_hdcp())
hdmi_msm_state->reauth = FALSE ;
hdmi_msm_state->reauth = FALSE ;
/* Build EDID table */
hdmi_msm_turn_on();
DEV_INFO("HDMI HPD: CONNECTED: send ONLINE\n");
kobject_uevent(external_common_state->uevent_kobj,
KOBJ_ONLINE);
hdmi_msm_hdcp_enable();
envp[0] = 0;
if (!hdmi_msm_has_hdcp()) {
if (!hdmi_msm_state->hdcp_enable) {
/* Send Audio for HDMI Compliance Cases*/
envp[0] = "HDCP_STATE=PASS";
envp[1] = NULL;
@ -4434,6 +4477,8 @@ void mhl_connect_api(boolean on)
switch_set_state(&external_common_state->sdev, 1);
DEV_INFO("Hdmi state switched to %d: %s\n",
external_common_state->sdev.state, __func__);
} else {
hdmi_msm_hdcp_enable();
}
} else {
DEV_INFO("HDMI HPD: DISCONNECTED: send OFFLINE\n");
@ -4457,7 +4502,6 @@ static int hdmi_msm_power_off(struct platform_device *pdev)
if (!hdmi_msm_state->hdmi_app_clk)
return -ENODEV;
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
mutex_lock(&hdmi_msm_state_mutex);
if (hdmi_msm_state->hdcp_activating) {
hdmi_msm_state->panel_power_on = FALSE;
@ -4466,19 +4510,38 @@ static int hdmi_msm_power_off(struct platform_device *pdev)
return 0;
}
mutex_unlock(&hdmi_msm_state_mutex);
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
DEV_INFO("power: OFF (audio off, Reset Core)\n");
hdmi_msm_audio_off();
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
hdcp_deauthenticate();
#endif
hdmi_msm_powerdown_phy();
hdmi_msm_state->panel_power_on = FALSE;
return 0;
}
void hdmi_msm_config_hdcp_feature(void)
{
if (hdcp_feature_on && hdmi_msm_has_hdcp()) {
init_timer(&hdmi_msm_state->hdcp_timer);
hdmi_msm_state->hdcp_timer.function = hdmi_msm_hdcp_timer;
hdmi_msm_state->hdcp_timer.data = (uint32)NULL;
hdmi_msm_state->hdcp_timer.expires = 0xffffffffL;
init_completion(&hdmi_msm_state->hdcp_success_done);
INIT_WORK(&hdmi_msm_state->hdcp_reauth_work,
hdmi_msm_hdcp_reauth_work);
INIT_WORK(&hdmi_msm_state->hdcp_work, hdmi_msm_hdcp_work);
hdmi_msm_state->hdcp_enable = TRUE;
} else {
del_timer(&hdmi_msm_state->hdcp_timer);
hdmi_msm_state->hdcp_enable = FALSE;
}
external_common_state->present_hdcp = hdmi_msm_state->hdcp_enable;
DEV_INFO("%s: HDCP Feature: %s\n", __func__,
hdmi_msm_state->hdcp_enable ? "Enabled" : "Disabled");
}
static int __devinit hdmi_msm_probe(struct platform_device *pdev)
{
int rc;
@ -4591,15 +4654,6 @@ static int __devinit hdmi_msm_probe(struct platform_device *pdev)
hdmi_msm_state->hpd_state_timer.expires = 0xffffffffL;
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
init_timer(&hdmi_msm_state->hdcp_timer);
hdmi_msm_state->hdcp_timer.function =
hdmi_msm_hdcp_timer;
hdmi_msm_state->hdcp_timer.data = (uint32)NULL;
hdmi_msm_state->hdcp_timer.expires = 0xffffffffL;
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
init_timer(&hdmi_msm_state->cec_read_timer);
hdmi_msm_state->cec_read_timer.function =
@ -4626,22 +4680,7 @@ static int __devinit hdmi_msm_probe(struct platform_device *pdev)
goto error;
}
if (hdmi_msm_has_hdcp()) {
/* Don't Set Encryption in case of non HDCP builds */
external_common_state->present_hdcp = FALSE;
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
external_common_state->present_hdcp = TRUE;
#endif
} else {
external_common_state->present_hdcp = FALSE;
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
/*
* If the device is not hdcp capable do
* not start hdcp timer.
*/
del_timer(&hdmi_msm_state->hdcp_timer);
#endif
}
hdmi_msm_config_hdcp_feature();
/* Initialize hdmi node and register with switch driver */
if (hdmi_prim_display)
@ -4819,11 +4858,6 @@ static int __init hdmi_msm_init(void)
hdmi_common_init_panel_info(&hdmi_msm_panel_data.panel_info);
init_completion(&hdmi_msm_state->ddc_sw_done);
INIT_WORK(&hdmi_msm_state->hpd_state_work, hdmi_msm_hpd_state_work);
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
init_completion(&hdmi_msm_state->hdcp_success_done);
INIT_WORK(&hdmi_msm_state->hdcp_reauth_work, hdmi_msm_hdcp_reauth_work);
INIT_WORK(&hdmi_msm_state->hdcp_work, hdmi_msm_hdcp_work);
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
INIT_WORK(&hdmi_msm_state->cec_latch_detect_work,
@ -4847,9 +4881,6 @@ static int __init hdmi_msm_init(void)
" RELEASE"
#endif
" AUDIO EDID HPD HDCP"
#ifndef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
":0"
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
" DVI"
#ifndef CONFIG_FB_MSM_HDMI_MSM_PANEL_DVI_SUPPORT
":0"
@ -4879,6 +4910,15 @@ static int set_hdcp_feature_on(const char *val, const struct kernel_param *kp)
return rv;
pr_debug("%s: HDCP feature = %d\n", __func__, hdcp_feature_on);
if (hdmi_msm_state) {
if ((HDMI_INP(0x0250) & 0x2)) {
pr_err("%s: Unable to set HDCP feature", __func__);
pr_err("%s: HDMI panel is currently turned on",
__func__);
} else if (hdcp_feature_on != hdmi_msm_state->hdcp_enable) {
hdmi_msm_config_hdcp_feature();
}
}
return 0;
}

View file

@ -64,13 +64,12 @@ struct hdmi_msm_state_type {
struct timer_list hpd_state_timer;
struct completion ddc_sw_done;
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
bool hdcp_enable;
boolean hdcp_activating;
boolean reauth ;
struct work_struct hdcp_reauth_work, hdcp_work;
struct completion hdcp_success_done;
struct timer_list hdcp_timer;
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
boolean cec_enabled;