summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c23
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_hdcp2p2.c23
-rw-r--r--drivers/gpu/drm/msm/sde_hdcp.h3
-rw-r--r--drivers/gpu/drm/msm/sde_hdcp_1x.c8
-rw-r--r--drivers/misc/hdcp.c5
-rw-r--r--include/linux/hdcp_qseecom.h3
6 files changed, 52 insertions, 13 deletions
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
index 48bddbf0e871..ca60c869d613 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
@@ -591,6 +591,22 @@ static void sde_hdmi_tx_hdcp_cb(void *ptr, enum sde_hdcp_states status)
queue_delayed_work(hdmi->workq, &hdmi_ctrl->hdcp_cb_work, HZ/4);
}
+static void sde_hdmi_tx_set_avmute(void *ptr)
+{
+ struct sde_hdmi *hdmi_ctrl = (struct sde_hdmi *)ptr;
+ struct hdmi *hdmi;
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ pr_err("setting avmute to true\n");
+
+ hdmi = hdmi_ctrl->ctrl.ctrl;
+ sde_hdmi_config_avmute(hdmi, true);
+}
+
void sde_hdmi_hdcp_off(struct sde_hdmi *hdmi_ctrl)
{
@@ -645,10 +661,6 @@ static void sde_hdmi_tx_hdcp_cb_work(struct work_struct *work)
hdmi_ctrl->auth_state = false;
- if (sde_hdmi_tx_is_encryption_set(hdmi_ctrl) ||
- !sde_hdmi_tx_is_stream_shareable(hdmi_ctrl))
- rc = sde_hdmi_config_avmute(hdmi, true);
-
if (sde_hdmi_tx_is_panel_on(hdmi_ctrl)) {
pr_debug("%s: Reauthenticating\n", __func__);
if (hdmi_ctrl->hdcp_ops && hdmi_ctrl->hdcp_data) {
@@ -666,7 +678,7 @@ static void sde_hdmi_tx_hdcp_cb_work(struct work_struct *work)
}
break;
- case HDCP_STATE_AUTH_FAIL_NOREAUTH:
+ case HDCP_STATE_AUTH_FAIL_NOREAUTH:
if (hdmi_ctrl->hdcp1_use_sw_keys && hdmi_ctrl->hdcp14_present) {
if (hdmi_ctrl->auth_state && !hdmi_ctrl->hdcp22_present)
hdcp1_set_enc(false);
@@ -2472,6 +2484,7 @@ static int _sde_hdmi_init_hdcp(struct sde_hdmi *hdmi_ctrl)
hdcp_init_data.mutex = &hdmi_ctrl->hdcp_mutex;
hdcp_init_data.workq = hdmi->workq;
hdcp_init_data.notify_status = sde_hdmi_tx_hdcp_cb;
+ hdcp_init_data.avmute_sink = sde_hdmi_tx_set_avmute;
hdcp_init_data.cb_data = (void *)hdmi_ctrl;
hdcp_init_data.hdmi_tx_ver = hdmi_ctrl->hdmi_tx_major_version;
hdcp_init_data.sec_access = true;
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_hdcp2p2.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_hdcp2p2.c
index a4f47756ad9b..fbb8bd1a3ca4 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_hdcp2p2.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_hdcp2p2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -321,11 +321,27 @@ int min_enc_lvl)
SDE_HDCP_DEBUG("enc level changed %d\n", min_enc_lvl);
+ /* notify the client first about the new level */
+ if (enc_notify && ctrl->init_data.notify_status)
+ ctrl->init_data.notify_status(ctrl->init_data.cb_data, enc_lvl);
+
cdata.context = ctrl->lib_ctx;
sde_hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata);
+}
- if (enc_notify && ctrl->init_data.notify_status)
- ctrl->init_data.notify_status(ctrl->init_data.cb_data, enc_lvl);
+static void sde_hdmi_hdcp2p2_mute_sink(void *client_ctx)
+{
+ struct sde_hdmi_hdcp2p2_ctrl *ctrl =
+ (struct sde_hdmi_hdcp2p2_ctrl *)client_ctx;
+
+ if (!ctrl) {
+ SDE_ERROR("invalid input\n");
+ return;
+ }
+
+ /* call into client to send avmute to the sink */
+ if (ctrl->init_data.avmute_sink)
+ ctrl->init_data.avmute_sink(ctrl->init_data.cb_data);
}
static void sde_hdmi_hdcp2p2_auth_failed(struct sde_hdmi_hdcp2p2_ctrl *ctrl)
@@ -930,6 +946,7 @@ void *sde_hdmi_hdcp2p2_init(struct sde_hdcp_init_data *init_data)
.wakeup = sde_hdmi_hdcp2p2_wakeup,
.notify_lvl_change = sde_hdmi_hdcp2p2_min_level_change,
.srm_cb = sde_hdmi_hdcp2p2_srm_cb,
+ .mute_sink = sde_hdmi_hdcp2p2_mute_sink,
};
static struct hdcp_txmtr_ops txmtr_ops;
diff --git a/drivers/gpu/drm/msm/sde_hdcp.h b/drivers/gpu/drm/msm/sde_hdcp.h
index 415e8467c99f..90c0d1cef26b 100644
--- a/drivers/gpu/drm/msm/sde_hdcp.h
+++ b/drivers/gpu/drm/msm/sde_hdcp.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -59,6 +59,7 @@ struct sde_hdcp_init_data {
struct workqueue_struct *workq;
void *cb_data;
void (*notify_status)(void *cb_data, enum sde_hdcp_states status);
+ void (*avmute_sink)(void *cb_data);
struct sde_hdmi_tx_ddc_ctrl *ddc_ctrl;
u8 sink_rx_status;
u16 *version;
diff --git a/drivers/gpu/drm/msm/sde_hdcp_1x.c b/drivers/gpu/drm/msm/sde_hdcp_1x.c
index 6c69cd58c0ed..ddbe54f6280f 100644
--- a/drivers/gpu/drm/msm/sde_hdcp_1x.c
+++ b/drivers/gpu/drm/msm/sde_hdcp_1x.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1359,6 +1359,9 @@ static void sde_hdcp_1x_notify_topology(void)
static void sde_hdcp_1x_update_auth_status(struct sde_hdcp_1x *hdcp)
{
+ if (sde_hdcp_1x_state(HDCP_STATE_AUTH_FAIL))
+ hdcp->init_data.avmute_sink(hdcp->init_data.cb_data);
+
if (sde_hdcp_1x_state(HDCP_STATE_AUTHENTICATED)) {
sde_hdcp_1x_cache_topology(hdcp);
sde_hdcp_1x_notify_topology();
@@ -1853,7 +1856,8 @@ void *sde_hdcp_1x_init(struct sde_hdcp_init_data *init_data)
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) {
+ !init_data->workq || !init_data->cb_data ||
+ !init_data->avmute_sink) {
pr_err("invalid input\n");
goto error;
}
diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c
index 09c7c1eeca7a..8dd9ba018f3b 100644
--- a/drivers/misc/hdcp.c
+++ b/drivers/misc/hdcp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2078,6 +2078,9 @@ static void hdcp_lib_clean(struct hdcp_lib_handle *handle)
handle->authenticated = false;
+ /* AV mute the sink first to avoid artifacts */
+ handle->client_ops->mute_sink(handle->client_ctx);
+
hdcp_lib_txmtr_deinit(handle);
if (!handle->legacy_app)
hdcp_lib_session_deinit(handle);
diff --git a/include/linux/hdcp_qseecom.h b/include/linux/hdcp_qseecom.h
index 11c2af725bb1..1ff11e4e33db 100644
--- a/include/linux/hdcp_qseecom.h
+++ b/include/linux/hdcp_qseecom.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -133,6 +133,7 @@ struct hdcp_client_ops {
int (*wakeup)(struct hdmi_hdcp_wakeup_data *data);
void (*notify_lvl_change)(void *client_ctx, int min_lvl);
void (*srm_cb)(void *client_ctx);
+ void (*mute_sink)(void *client_ctx);
};
enum hdcp_device_type {