summaryrefslogtreecommitdiff
path: root/drivers/video/tegra
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/tegra')
-rw-r--r--drivers/video/tegra/dc/nvhdcp.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/video/tegra/dc/nvhdcp.c b/drivers/video/tegra/dc/nvhdcp.c
index 3566e2bd33b5..b509a6c78499 100644
--- a/drivers/video/tegra/dc/nvhdcp.c
+++ b/drivers/video/tegra/dc/nvhdcp.c
@@ -78,6 +78,7 @@ struct tegra_nvhdcp {
struct tegra_dc_hdmi_data *hdmi;
struct workqueue_struct *downstream_wq;
struct mutex lock;
+ struct mutex state_lock;
struct miscdevice miscdev;
char name[12];
unsigned id;
@@ -980,7 +981,9 @@ static void nvhdcp_downstream_worker(struct work_struct *work)
nvhdcp_vdbg("CRYPT enabled\n");
+ mutex_lock(&nvhdcp->state_lock);
nvhdcp->state = STATE_LINK_VERIFY;
+ mutex_unlock(&nvhdcp->state_lock);
nvhdcp_info("link verified!\n");
while (1) {
@@ -1007,30 +1010,39 @@ failure:
if(nvhdcp->fail_count > 5) {
nvhdcp_err("nvhdcp failure - too many failures, giving up!\n");
} else {
- nvhdcp_err("nvhdcp failure - renegotiating in 1 second\n");
- if (!nvhdcp_is_plugged(nvhdcp))
+ if (!nvhdcp_is_plugged(nvhdcp)) {
+ nvhdcp_err("nvhdcp failure\n");
goto lost_hdmi;
+ }
+ nvhdcp_err("nvhdcp failure - renegotiating in 1 second\n");
queue_delayed_work(nvhdcp->downstream_wq, &nvhdcp->work,
msecs_to_jiffies(1000));
}
lost_hdmi:
+ mutex_lock(&nvhdcp->state_lock);
nvhdcp->state = STATE_UNAUTHENTICATED;
+ mutex_unlock(&nvhdcp->state_lock);
hdcp_ctrl_run(hdmi, 0);
err:
mutex_unlock(&nvhdcp->lock);
return;
disable:
+ mutex_lock(&nvhdcp->state_lock);
nvhdcp->state = STATE_OFF;
nvhdcp_set_plugged(nvhdcp, false);
+ mutex_unlock(&nvhdcp->state_lock);
mutex_unlock(&nvhdcp->lock);
return;
}
static int tegra_nvhdcp_on(struct tegra_nvhdcp *nvhdcp)
{
+ mutex_lock(&nvhdcp->state_lock);
+ nvhdcp_set_plugged(nvhdcp, true);
nvhdcp->state = STATE_UNAUTHENTICATED;
+ mutex_unlock(&nvhdcp->state_lock);
if (nvhdcp_is_plugged(nvhdcp)) {
nvhdcp->fail_count = 0;
queue_delayed_work(nvhdcp->downstream_wq, &nvhdcp->work,
@@ -1041,10 +1053,10 @@ static int tegra_nvhdcp_on(struct tegra_nvhdcp *nvhdcp)
static int tegra_nvhdcp_off(struct tegra_nvhdcp *nvhdcp)
{
- mutex_lock(&nvhdcp->lock);
+ mutex_lock(&nvhdcp->state_lock);
nvhdcp->state = STATE_OFF;
nvhdcp_set_plugged(nvhdcp, false);
- mutex_unlock(&nvhdcp->lock);
+ mutex_unlock(&nvhdcp->state_lock);
wake_up_interruptible(&wq_worker);
flush_workqueue(nvhdcp->downstream_wq);
return 0;
@@ -1055,7 +1067,6 @@ void tegra_nvhdcp_set_plug(struct tegra_nvhdcp *nvhdcp, bool hpd)
nvhdcp_debug("hdmi hotplug detected (hpd = %d)\n", hpd);
if (hpd) {
- nvhdcp_set_plugged(nvhdcp, true);
tegra_nvhdcp_on(nvhdcp);
} else {
tegra_nvhdcp_off(nvhdcp);
@@ -1080,9 +1091,9 @@ int tegra_nvhdcp_set_policy(struct tegra_nvhdcp *nvhdcp, int pol)
static int tegra_nvhdcp_renegotiate(struct tegra_nvhdcp *nvhdcp)
{
- mutex_lock(&nvhdcp->lock);
+ mutex_lock(&nvhdcp->state_lock);
nvhdcp->state = STATE_RENEGOTIATE;
- mutex_unlock(&nvhdcp->lock);
+ mutex_unlock(&nvhdcp->state_lock);
tegra_nvhdcp_on(nvhdcp);
return 0;
}
@@ -1201,6 +1212,7 @@ struct tegra_nvhdcp *tegra_nvhdcp_create(struct tegra_dc_hdmi_data *hdmi,
snprintf(nvhdcp->name, sizeof(nvhdcp->name), "nvhdcp%u", id);
nvhdcp->hdmi = hdmi;
mutex_init(&nvhdcp->lock);
+ mutex_init(&nvhdcp->state_lock);
strlcpy(nvhdcp->info.type, nvhdcp->name, sizeof(nvhdcp->info.type));
nvhdcp->bus = bus;
@@ -1224,7 +1236,9 @@ struct tegra_nvhdcp *tegra_nvhdcp_create(struct tegra_dc_hdmi_data *hdmi,
goto free_nvhdcp;
}
+ mutex_lock(&nvhdcp->state_lock);
nvhdcp->state = STATE_UNAUTHENTICATED;
+ mutex_unlock(&nvhdcp->state_lock);
nvhdcp->downstream_wq = create_singlethread_workqueue(nvhdcp->name);
INIT_DELAYED_WORK(&nvhdcp->work, nvhdcp_downstream_worker);