Skip to content

Commit da3fd7a

Browse files
Bhawanpreet Lakhaalexdeucher
authored andcommitted
drm/amd/display: Update CP property based on HW query
[Why] We need to use HW state to set content protection to ENABLED. This way we know that the link is encrypted from the HW side [How] Create a workqueue that queries the HW every ~2seconds, and sets it to ENABLED or DESIRED based on the result from the hardware Signed-off-by: Bhawanpreet Lakha <[email protected]> Reviewed-by: Harry Wentland <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent 2a0f927 commit da3fd7a

File tree

3 files changed

+73
-15
lines changed

3 files changed

+73
-15
lines changed

drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5436,19 +5436,9 @@ static void update_content_protection(struct drm_connector_state *state, const s
54365436
{
54375437
struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
54385438

5439-
if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) {
5440-
hdcp_add_display(hdcp_w, aconnector->dc_link->link_index);
5441-
5442-
/*
5443-
* TODO: ENABLED should be verified using psp, it is planned later.
5444-
* Just set this to ENABLED for now
5445-
*/
5446-
state->content_protection = DRM_MODE_CONTENT_PROTECTION_ENABLED;
5447-
5448-
return;
5449-
}
5450-
5451-
if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
5439+
if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED)
5440+
hdcp_add_display(hdcp_w, aconnector->dc_link->link_index, aconnector);
5441+
else if (state->content_protection == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
54525442
hdcp_remove_display(hdcp_w, aconnector->dc_link->link_index, aconnector->base.index);
54535443

54545444
}

drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "amdgpu.h"
2828
#include "amdgpu_dm.h"
2929
#include "dm_helpers.h"
30+
#include <drm/drm_hdcp.h>
3031

3132
bool lp_write_i2c(void *handle, uint32_t address, const uint8_t *data, uint32_t size)
3233
{
@@ -82,16 +83,19 @@ static void process_output(struct hdcp_workqueue *hdcp_work)
8283

8384
}
8485

85-
void hdcp_add_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index)
86+
void hdcp_add_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index, struct amdgpu_dm_connector *aconnector)
8687
{
8788
struct hdcp_workqueue *hdcp_w = &hdcp_work[link_index];
8889
struct mod_hdcp_display *display = &hdcp_work[link_index].display;
8990
struct mod_hdcp_link *link = &hdcp_work[link_index].link;
9091

9192
mutex_lock(&hdcp_w->mutex);
93+
hdcp_w->aconnector = aconnector;
9294

9395
mod_hdcp_add_display(&hdcp_w->hdcp, link, display, &hdcp_w->output);
9496

97+
schedule_delayed_work(&hdcp_w->property_validate_dwork, msecs_to_jiffies(DRM_HDCP_CHECK_PERIOD_MS));
98+
9599
process_output(hdcp_w);
96100

97101
mutex_unlock(&hdcp_w->mutex);
@@ -106,6 +110,9 @@ void hdcp_remove_display(struct hdcp_workqueue *hdcp_work, unsigned int link_ind
106110

107111
mod_hdcp_remove_display(&hdcp_w->hdcp, display_index, &hdcp_w->output);
108112

113+
cancel_delayed_work(&hdcp_w->property_validate_dwork);
114+
hdcp_w->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
115+
109116
process_output(hdcp_w);
110117

111118
mutex_unlock(&hdcp_w->mutex);
@@ -120,6 +127,9 @@ void hdcp_reset_display(struct hdcp_workqueue *hdcp_work, unsigned int link_inde
120127

121128
mod_hdcp_reset_connection(&hdcp_w->hdcp, &hdcp_w->output);
122129

130+
cancel_delayed_work(&hdcp_w->property_validate_dwork);
131+
hdcp_w->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
132+
123133
process_output(hdcp_w);
124134

125135
mutex_unlock(&hdcp_w->mutex);
@@ -155,7 +165,58 @@ static void event_callback(struct work_struct *work)
155165

156166

157167
}
168+
static void event_property_update(struct work_struct *work)
169+
{
170+
171+
struct hdcp_workqueue *hdcp_work = container_of(work, struct hdcp_workqueue, property_update_work);
172+
struct amdgpu_dm_connector *aconnector = hdcp_work->aconnector;
173+
struct drm_device *dev = hdcp_work->aconnector->base.dev;
174+
long ret;
175+
176+
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
177+
mutex_lock(&hdcp_work->mutex);
178+
179+
180+
if (aconnector->base.state->commit) {
181+
ret = wait_for_completion_interruptible_timeout(&aconnector->base.state->commit->hw_done, 10 * HZ);
182+
183+
if (ret == 0) {
184+
DRM_ERROR("HDCP state unknown! Setting it to DESIRED");
185+
hdcp_work->encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
186+
}
187+
}
188+
189+
if (hdcp_work->encryption_status == MOD_HDCP_ENCRYPTION_STATUS_HDCP1_ON)
190+
drm_hdcp_update_content_protection(&aconnector->base, DRM_MODE_CONTENT_PROTECTION_ENABLED);
191+
else
192+
drm_hdcp_update_content_protection(&aconnector->base, DRM_MODE_CONTENT_PROTECTION_DESIRED);
193+
194+
195+
mutex_unlock(&hdcp_work->mutex);
196+
drm_modeset_unlock(&dev->mode_config.connection_mutex);
197+
}
198+
199+
static void event_property_validate(struct work_struct *work)
200+
{
201+
struct hdcp_workqueue *hdcp_work =
202+
container_of(to_delayed_work(work), struct hdcp_workqueue, property_validate_dwork);
203+
struct mod_hdcp_display_query query;
204+
struct amdgpu_dm_connector *aconnector = hdcp_work->aconnector;
205+
206+
mutex_lock(&hdcp_work->mutex);
158207

208+
query.encryption_status = MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
209+
mod_hdcp_query_display(&hdcp_work->hdcp, aconnector->base.index, &query);
210+
211+
if (query.encryption_status != hdcp_work->encryption_status) {
212+
hdcp_work->encryption_status = query.encryption_status;
213+
schedule_work(&hdcp_work->property_update_work);
214+
}
215+
216+
schedule_delayed_work(&hdcp_work->property_validate_dwork, msecs_to_jiffies(DRM_HDCP_CHECK_PERIOD_MS));
217+
218+
mutex_unlock(&hdcp_work->mutex);
219+
}
159220

160221
static void event_watchdog_timer(struct work_struct *work)
161222
{
@@ -250,8 +311,10 @@ struct hdcp_workqueue *hdcp_create_workqueue(void *psp_context, struct cp_psp *c
250311
mutex_init(&hdcp_work[i].mutex);
251312

252313
INIT_WORK(&hdcp_work[i].cpirq_work, event_cpirq);
314+
INIT_WORK(&hdcp_work[i].property_update_work, event_property_update);
253315
INIT_DELAYED_WORK(&hdcp_work[i].callback_dwork, event_callback);
254316
INIT_DELAYED_WORK(&hdcp_work[i].watchdog_timer_dwork, event_watchdog_timer);
317+
INIT_DELAYED_WORK(&hdcp_work[i].property_validate_dwork, event_property_validate);
255318

256319
hdcp_work[i].hdcp.config.psp.handle = psp_context;
257320
hdcp_work[i].hdcp.config.ddc.handle = dc_get_link_at_index(dc, i);

drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,24 @@ struct cp_psp;
3838

3939
struct hdcp_workqueue {
4040
struct work_struct cpirq_work;
41+
struct work_struct property_update_work;
4142
struct delayed_work callback_dwork;
4243
struct delayed_work watchdog_timer_dwork;
44+
struct delayed_work property_validate_dwork;
45+
struct amdgpu_dm_connector *aconnector;
4346
struct mutex mutex;
4447

4548
struct mod_hdcp hdcp;
4649
struct mod_hdcp_output output;
4750
struct mod_hdcp_display display;
4851
struct mod_hdcp_link link;
4952

53+
enum mod_hdcp_encryption_status encryption_status;
5054
uint8_t max_link;
5155
};
5256

53-
void hdcp_add_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index);
57+
void hdcp_add_display(struct hdcp_workqueue *hdcp_work, unsigned int link_index,
58+
struct amdgpu_dm_connector *aconnector);
5459
void hdcp_remove_display(struct hdcp_workqueue *work, unsigned int link_index, unsigned int display_index);
5560
void hdcp_reset_display(struct hdcp_workqueue *work, unsigned int link_index);
5661
void hdcp_handle_cpirq(struct hdcp_workqueue *work, unsigned int link_index);

0 commit comments

Comments
 (0)