msm: mdss: hdmi: check if hdcp2p2 app is present during hpd

Check if the hdcp2p2 app is present every time the hdmi cable
is connected. If the app is not present, then we consider
hdcp-2.2 as not supported on the target. This scenario occurs
on devices that are not hdcp-2.2 provisioned, and with this
change hdmi core continues in non-encrypted mode.

Change-Id: I72ebcc1e6844f46dbbc974efb6ba926948e1bbde
Signed-off-by: Tatenda Chipeperekwa <tatendac@codeaurora.org>
This commit is contained in:
Tatenda Chipeperekwa 2015-09-25 17:00:00 -07:00 committed by David Keitel
parent cc97a775f4
commit c76b5e3acf
5 changed files with 83 additions and 21 deletions

View file

@ -863,6 +863,27 @@ exit:
return rc; return rc;
} }
static bool hdcp2p2_client_feature_supported(void *phdcpcontext)
{
int rc = 0;
bool supported = false;
struct hdcp2p2_handle *handle = phdcpcontext;
if (!handle) {
pr_err("invalid input\n");
goto end;
}
rc = hdcp2p2_library_load(handle);
if (!rc) {
pr_debug("HDCP2p2 supported\n");
hdcp2p2_library_unload(handle);
supported = true;
}
end:
return supported;
}
static int hdcp2p2_client_start(void *phdcpcontext) static int hdcp2p2_client_start(void *phdcpcontext)
{ {
int rc = 0; int rc = 0;
@ -1135,6 +1156,7 @@ int hdcp_library_register(void **pphdcpcontext,
/* populate ops to be called by client */ /* populate ops to be called by client */
txmtr_ops->start = hdcp2p2_client_start; txmtr_ops->start = hdcp2p2_client_start;
txmtr_ops->stop = hdcp2p2_client_stop; txmtr_ops->stop = hdcp2p2_client_stop;
txmtr_ops->feature_supported = hdcp2p2_client_feature_supported;
txmtr_ops->process_message = hdcp2p2_txmtr_process_message; txmtr_ops->process_message = hdcp2p2_txmtr_process_message;
txmtr_ops->hdcp_txmtr_query_stream_type = txmtr_ops->hdcp_txmtr_query_stream_type =
hdcp2p2_txmtr_query_stream_type; hdcp2p2_txmtr_query_stream_type;
@ -1166,7 +1188,8 @@ int hdcp_library_register(void **pphdcpcontext,
} }
*((struct hdcp2p2_handle **)pphdcpcontext) = handle; *((struct hdcp2p2_handle **)pphdcpcontext) = handle;
pr_debug("hdcp lib successfully initialized\n");
pr_debug("hdcp lib successfully registered\n");
return 0; return 0;
error: error:
@ -1196,6 +1219,8 @@ void hdcp_library_deregister(void *phdcpcontext)
if (handle->hdcp_workqueue) if (handle->hdcp_workqueue)
destroy_workqueue(handle->hdcp_workqueue); destroy_workqueue(handle->hdcp_workqueue);
mutex_destroy(&handle->hdcp_lock);
kzfree(handle->listener_buf); kzfree(handle->listener_buf);
kzfree(handle); kzfree(handle);
} }

View file

@ -43,6 +43,7 @@ struct hdmi_hdcp_ops {
int (*hdmi_hdcp_isr)(void *ptr); int (*hdmi_hdcp_isr)(void *ptr);
int (*hdmi_hdcp_reauthenticate)(void *input); int (*hdmi_hdcp_reauthenticate)(void *input);
int (*hdmi_hdcp_authenticate)(void *hdcp_ctrl); int (*hdmi_hdcp_authenticate)(void *hdcp_ctrl);
bool (*feature_supported)(void *input);
void (*hdmi_hdcp_off)(void *hdcp_ctrl); void (*hdmi_hdcp_off)(void *hdcp_ctrl);
}; };

View file

@ -554,6 +554,29 @@ static int hdcp2p2_isr(void *input)
return 0; return 0;
} }
static bool hdcp2p2_feature_supported(void *input)
{
struct hdcp2p2_ctrl *hdcp2p2_ctrl = input;
struct hdcp_txmtr_ops *lib = NULL;
bool supported = false;
if (!hdcp2p2_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
goto end;
}
lib = hdcp2p2_ctrl->txmtr_ops;
if (!lib) {
DEV_ERR("%s: invalid lib ops data\n", __func__);
goto end;
}
if (lib->feature_supported)
supported = lib->feature_supported(
hdcp2p2_ctrl->hdcp_lib_handle);
end:
return supported;
}
static void hdcp2p2_reset(struct hdcp2p2_ctrl *hdcp2p2_ctrl) static void hdcp2p2_reset(struct hdcp2p2_ctrl *hdcp2p2_ctrl)
{ {
@ -781,6 +804,7 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data)
.hdmi_hdcp_isr = hdcp2p2_isr, .hdmi_hdcp_isr = hdcp2p2_isr,
.hdmi_hdcp_reauthenticate = hdcp2p2_reauthenticate, .hdmi_hdcp_reauthenticate = hdcp2p2_reauthenticate,
.hdmi_hdcp_authenticate = hdcp2p2_authenticate, .hdmi_hdcp_authenticate = hdcp2p2_authenticate,
.feature_supported = hdcp2p2_feature_supported,
.hdmi_hdcp_off = hdcp2p2_off .hdmi_hdcp_off = hdcp2p2_off
}; };

View file

@ -1600,6 +1600,36 @@ error:
return status; return status;
} /* hdmi_tx_read_sink_info */ } /* hdmi_tx_read_sink_info */
static void hdmi_tx_update_hdcp_info(struct hdmi_tx_ctrl *hdmi_ctrl)
{
void *fd = NULL;
struct hdmi_hdcp_ops *ops = NULL;
if (!hdmi_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
return;
}
/* check first if hdcp2p2 is supported */
fd = hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2];
if (fd)
ops = hdmi_hdcp2p2_start(fd);
if (ops && ops->feature_supported)
hdmi_ctrl->hdcp22_present = ops->feature_supported(fd);
else
hdmi_ctrl->hdcp22_present = false;
if (!hdmi_ctrl->hdcp22_present && hdmi_ctrl->hdcp14_present) {
fd = hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP];
ops = hdmi_hdcp_start(fd);
}
/* update internal data about hdcp */
hdmi_ctrl->hdcp_feature_data = fd;
hdmi_ctrl->hdcp_ops = ops;
}
static void hdmi_tx_hpd_int_work(struct work_struct *work) static void hdmi_tx_hpd_int_work(struct work_struct *work)
{ {
struct hdmi_tx_ctrl *hdmi_ctrl = NULL; struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
@ -1629,26 +1659,7 @@ static void hdmi_tx_hpd_int_work(struct work_struct *work)
if (hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, false)) if (hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, false))
DEV_ERR("%s: Failed to disable ddc power\n", __func__); DEV_ERR("%s: Failed to disable ddc power\n", __func__);
/* Figure out HDCP capabilities of sink */ hdmi_tx_update_hdcp_info(hdmi_ctrl);
hdmi_ctrl->hdcp_ops = NULL;
hdmi_ctrl->hdcp_feature_data =
hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP2P2];
if (hdmi_ctrl->hdcp_feature_data)
hdmi_ctrl->hdcp_ops =
hdmi_hdcp2p2_start(
hdmi_ctrl->hdcp_feature_data);
if (hdmi_ctrl->hdcp_ops)
hdmi_ctrl->hdcp22_present = true;
else
hdmi_ctrl->hdcp22_present = false;
if (!hdmi_ctrl->hdcp22_present && hdmi_ctrl->hdcp14_present) {
hdmi_ctrl->hdcp_feature_data =
hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP];
hdmi_ctrl->hdcp_ops =
hdmi_hdcp_start(hdmi_ctrl->hdcp_feature_data);
}
hdmi_tx_send_cable_notification(hdmi_ctrl, true); hdmi_tx_send_cable_notification(hdmi_ctrl, true);
} else { } else {

View file

@ -17,6 +17,7 @@
struct hdcp_txmtr_ops { struct hdcp_txmtr_ops {
int (*start)(void *phdcpcontext); int (*start)(void *phdcpcontext);
int (*stop)(void *phdcpcontext); int (*stop)(void *phdcpcontext);
bool (*feature_supported)(void *phdcpcontext);
int (*process_message)(void *phdcpcontext, int (*process_message)(void *phdcpcontext,
unsigned char *msg, uint32_t msg_size); unsigned char *msg, uint32_t msg_size);