msm: mdss: hdmi: add SRM support for HDCP1.4
Extend HDCP1.4 SRM support for fb based hdmi driver as well. Change-Id: I3d6597503d95b066d1fcfa71218cdda70965fbd0 Signed-off-by: Narender Ankam <nankam@codeaurora.org>
This commit is contained in:
parent
1a51baa68a
commit
2cc1946a7a
2 changed files with 165 additions and 2 deletions
|
@ -18,6 +18,8 @@
|
|||
#include <video/msm_hdmi_modes.h>
|
||||
#include <soc/qcom/scm.h>
|
||||
|
||||
#define HDCP_SRM_CHECK_FAIL 29
|
||||
|
||||
enum hdcp_client_id {
|
||||
HDCP_CLIENT_HDMI,
|
||||
HDCP_CLIENT_DP,
|
||||
|
|
|
@ -789,6 +789,107 @@ error:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static u8 *hdcp_1x_swap_byte_order(u8 *bksv_in, int num_dev)
|
||||
{
|
||||
u8 *bksv_out;
|
||||
u8 *tmp_out;
|
||||
u8 *tmp_in;
|
||||
int i, j;
|
||||
|
||||
/* Dont exceed max downstream devices */
|
||||
if (num_dev > MAX_DEVICES_SUPPORTED) {
|
||||
pr_err("invalid params\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bksv_out = kzalloc(RECV_ID_SIZE * num_dev, GFP_KERNEL);
|
||||
|
||||
if (!bksv_out)
|
||||
return NULL;
|
||||
|
||||
pr_debug("num_dev = %d\n", num_dev);
|
||||
|
||||
/* Store temporarily for return */
|
||||
tmp_out = bksv_out;
|
||||
tmp_in = bksv_in;
|
||||
|
||||
for (i = 0; i < num_dev; i++) {
|
||||
for (j = 0; j < RECV_ID_SIZE; j++)
|
||||
bksv_out[j] = tmp_in[RECV_ID_SIZE - j - 1];
|
||||
|
||||
/* Each KSV is 5 bytes long */
|
||||
bksv_out += RECV_ID_SIZE;
|
||||
tmp_in += RECV_ID_SIZE;
|
||||
}
|
||||
|
||||
return tmp_out;
|
||||
}
|
||||
|
||||
static int hdcp_1x_revoked_rcv_chk(struct hdcp_1x *hdcp)
|
||||
{
|
||||
int rc = 0;
|
||||
u8 *bksv = hdcp->current_tp.bksv;
|
||||
u8 *bksv_out;
|
||||
struct hdcp_srm_device_id_t *bksv_srm;
|
||||
|
||||
bksv_out = hdcp_1x_swap_byte_order(bksv, 1);
|
||||
|
||||
if (!bksv_out) {
|
||||
rc = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
pr_debug("bksv_out : 0x%2x%2x%2x%2x%2x\n",
|
||||
bksv_out[4], bksv_out[3], bksv_out[2],
|
||||
bksv_out[1], bksv_out[0]);
|
||||
|
||||
bksv_srm = (struct hdcp_srm_device_id_t *)bksv_out;
|
||||
/* Here we are checking only receiver ID
|
||||
* hence the device count is one
|
||||
*/
|
||||
rc = hdcp1_validate_receiver_ids(bksv_srm, 1);
|
||||
|
||||
kfree(bksv_out);
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int hdcp_1x_revoked_rpt_chk(struct hdcp_1x *hdcp)
|
||||
{
|
||||
int rc = 0;
|
||||
int i;
|
||||
u8 *bksv = hdcp->current_tp.ksv_list;
|
||||
u8 *bksv_out;
|
||||
struct hdcp_srm_device_id_t *bksv_srm;
|
||||
|
||||
for (i = 0; i < hdcp->sink_addr.ksv_fifo.len;
|
||||
i += RECV_ID_SIZE) {
|
||||
pr_debug("bksv : 0x%2x%2x%2x%2x%2x\n",
|
||||
bksv[i + 4],
|
||||
bksv[i + 3], bksv[i + 2],
|
||||
bksv[i + 1], bksv[i]);
|
||||
}
|
||||
|
||||
bksv_out = hdcp_1x_swap_byte_order(bksv,
|
||||
hdcp->current_tp.dev_count);
|
||||
|
||||
if (!bksv_out) {
|
||||
rc = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
bksv_srm = (struct hdcp_srm_device_id_t *)bksv_out;
|
||||
/* Here we are checking repeater ksv list */
|
||||
rc = hdcp1_validate_receiver_ids(bksv_srm,
|
||||
hdcp->current_tp.dev_count);
|
||||
|
||||
kfree(bksv_out);
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void hdcp_1x_enable_sink_irq_hpd(struct hdcp_1x *hdcp)
|
||||
{
|
||||
int rc;
|
||||
|
@ -906,6 +1007,12 @@ static int hdcp_1x_authentication_part1(struct hdcp_1x *hdcp)
|
|||
if (rc)
|
||||
goto error;
|
||||
|
||||
rc = hdcp_1x_revoked_rcv_chk(hdcp);
|
||||
if (rc) {
|
||||
rc = -HDCP_SRM_CHECK_FAIL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = hdcp_1x_send_an_aksv_to_sink(hdcp);
|
||||
if (rc)
|
||||
goto error;
|
||||
|
@ -1230,6 +1337,12 @@ static int hdcp_1x_authentication_part2(struct hdcp_1x *hdcp)
|
|||
if (rc)
|
||||
goto error;
|
||||
|
||||
rc = hdcp_1x_revoked_rpt_chk(hdcp);
|
||||
if (rc) {
|
||||
rc = -HDCP_SRM_CHECK_FAIL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
do {
|
||||
rc = hdcp_1x_transfer_v_h(hdcp);
|
||||
if (rc)
|
||||
|
@ -1361,9 +1474,11 @@ static void hdcp_1x_auth_work(struct work_struct *work)
|
|||
DSS_REG_W_ND(io, HDMI_DDC_ARBITRATION, DSS_REG_R(io,
|
||||
HDMI_DDC_ARBITRATION) | (BIT(4)));
|
||||
end:
|
||||
if (rc && !hdcp_1x_state(HDCP_STATE_INACTIVE))
|
||||
if (rc && !hdcp_1x_state(HDCP_STATE_INACTIVE)) {
|
||||
hdcp->hdcp_state = HDCP_STATE_AUTH_FAIL;
|
||||
|
||||
if (rc == -HDCP_SRM_CHECK_FAIL)
|
||||
hdcp->hdcp_state = HDCP_STATE_AUTH_FAIL_NOREAUTH;
|
||||
}
|
||||
|
||||
hdcp_1x_update_auth_status(hdcp);
|
||||
|
||||
|
@ -1751,6 +1866,7 @@ void hdcp_1x_deinit(void *input)
|
|||
sysfs_remove_group(hdcp->init_data.sysfs_kobj,
|
||||
&hdcp_1x_fs_attr_group);
|
||||
|
||||
hdcp1_client_unregister();
|
||||
kfree(hdcp);
|
||||
} /* hdcp_1x_deinit */
|
||||
|
||||
|
@ -1853,6 +1969,44 @@ irq_not_handled:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void hdcp_1x_srm_cb(void *input)
|
||||
{
|
||||
|
||||
struct hdcp_1x *hdcp = (struct hdcp_1x *)input;
|
||||
int rc = 0;
|
||||
|
||||
if (!hdcp) {
|
||||
pr_err("invalid input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rc = hdcp_1x_revoked_rcv_chk(hdcp);
|
||||
|
||||
if (rc) {
|
||||
pr_err("receiver failed SRM check\n");
|
||||
goto fail_noreauth;
|
||||
}
|
||||
|
||||
/* If its not a repeater we are done */
|
||||
if (hdcp->current_tp.ds_type != DS_REPEATER)
|
||||
return;
|
||||
|
||||
|
||||
/* Check the repeater KSV against SRM */
|
||||
rc = hdcp_1x_revoked_rpt_chk(hdcp);
|
||||
if (rc) {
|
||||
pr_err("repeater failed SRM check\n");
|
||||
goto fail_noreauth;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
fail_noreauth:
|
||||
/* No reauth in case of SRM failure */
|
||||
hdcp->hdcp_state = HDCP_STATE_AUTH_FAIL_NOREAUTH;
|
||||
hdcp_1x_update_auth_status(hdcp);
|
||||
}
|
||||
|
||||
void *hdcp_1x_init(struct hdcp_init_data *init_data)
|
||||
{
|
||||
struct hdcp_1x *hdcp = NULL;
|
||||
|
@ -1865,6 +2019,10 @@ void *hdcp_1x_init(struct hdcp_init_data *init_data)
|
|||
.off = hdcp_1x_off
|
||||
};
|
||||
|
||||
static struct hdcp_client_ops client_ops = {
|
||||
.srm_cb = hdcp_1x_srm_cb,
|
||||
};
|
||||
|
||||
if (!init_data || !init_data->core_io || !init_data->qfprom_io ||
|
||||
!init_data->mutex || !init_data->notify_status ||
|
||||
!init_data->workq || !init_data->cb_data) {
|
||||
|
@ -1907,6 +2065,9 @@ void *hdcp_1x_init(struct hdcp_init_data *init_data)
|
|||
init_completion(&hdcp->r0_checked);
|
||||
init_completion(&hdcp->sink_r0_available);
|
||||
|
||||
/* Register client ctx and the srm_cb with hdcp lib */
|
||||
hdcp1_client_register((void *)hdcp, &client_ops);
|
||||
|
||||
pr_debug("HDCP module initialized. HDCP_STATE=%s\n",
|
||||
HDCP_STATE_NAME);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue