Skip to content
This repository was archived by the owner on Oct 8, 2024. It is now read-only.

Commit c3b53ec

Browse files
committed
Add support for HDCP 2.2
With HDCP 2.2 a new connector property is added for marking the content type. This property controls the type of authentication that the kernel needs to perform. The content type property takes 2 values, 0 (TYPE0) and 1 (TYPE1). When the client marks the content as TYPE0, the kernel can choose whether to go for HDCP 1.4 or HDCP 2.2 authentication but when the client marks the content as TYPE1, the kernel is only allowed to attempt HDCP 2.2 authentication. Failing which, HDCP fails to enable. The spec states that the source needs to wait at least 5 seconds before declaring success/failure in authentication. Along with this wait, the kernel re-tries 3 times, thus the compositor needs to wait for ~15 seconds. Once HDCP is enabled, it is expected that the compositor should continuously poll the connector property to ensure that HDCP is active. If HDCP gets disabled due to link failure, the compositor should re-try the authentication either till it succeeds or the client notifies that it doesn't require HDCP. This patch adds code to fulfill the above requirements. Jira: None Test: Test introduced in jsonlayerstest.cpp in the previous patch Test it by running ./testlayers -f 120 -j jsonconfigs/kmscube1layer.json Signed-off-by: Harish Krupo <harish.krupo.kps@intel.com>
1 parent 1aed7df commit c3b53ec

File tree

10 files changed

+191
-53
lines changed

10 files changed

+191
-53
lines changed

common/core/logicaldisplay.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ bool LogicalDisplay::SetPowerMode(uint32_t power_mode) {
6868
return true;
6969
}
7070

71-
void LogicalDisplay::SetHDCPState(HWCContentProtection state,
71+
bool LogicalDisplay::SetHDCPState(HWCContentProtection state,
7272
HWCContentType content_type) {
73-
logical_display_manager_->SetHDCPState(state, content_type);
73+
return logical_display_manager_->SetHDCPState(state, content_type);
7474
}
7575

7676
void LogicalDisplay::SetHDCPSRM(const int8_t *SRM, uint32_t SRMLength) {

common/core/logicaldisplay.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ class LogicalDisplay : public NativeDisplay {
122122

123123
void HotPlugUpdate(bool connected) override;
124124

125-
void SetHDCPState(HWCContentProtection state,
125+
bool SetHDCPState(HWCContentProtection state,
126126
HWCContentType content_type) override;
127127
void SetHDCPSRM(const int8_t *SRM, uint32_t SRMLength) override;
128128

common/core/logicaldisplaymanager.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,12 +223,15 @@ void LogicalDisplayManager::GetLogicalDisplays(
223223
}
224224
}
225225

226-
void LogicalDisplayManager::SetHDCPState(HWCContentProtection state,
226+
bool LogicalDisplayManager::SetHDCPState(HWCContentProtection state,
227227
HWCContentType content_type) {
228228
uint32_t size = displays_.size();
229+
bool ret = true;
229230
for (uint32_t i = 0; i < size; i++) {
230-
displays_.at(i)->SetHDCPState(state, content_type);
231+
ret = ret && displays_.at(i)->SetHDCPState(state, content_type);
231232
}
233+
234+
return ret;
232235
}
233236

234237
void LogicalDisplayManager::SetHDCPSRM(const int8_t* SRM, uint32_t SRMLength) {

common/core/logicaldisplaymanager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class LogicalDisplayManager {
9595
* @param state an enum named HWCContentProtection
9696
* @param content_type an enum of HWCContentType
9797
*/
98-
void SetHDCPState(HWCContentProtection state, HWCContentType content_type);
98+
bool SetHDCPState(HWCContentProtection state, HWCContentType content_type);
9999

100100
void SetHDCPSRM(const int8_t* SRM, uint32_t SRMLength);
101101

common/core/mosaicdisplay.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -504,12 +504,15 @@ bool MosaicDisplay::GetDisplayName(uint32_t *size, char *name) {
504504
return true;
505505
}
506506

507-
void MosaicDisplay::SetHDCPState(HWCContentProtection state,
507+
bool MosaicDisplay::SetHDCPState(HWCContentProtection state,
508508
HWCContentType content_type) {
509509
uint32_t size = physical_displays_.size();
510+
bool ret = true;
510511
for (uint32_t i = 0; i < size; i++) {
511-
physical_displays_.at(i)->SetHDCPState(state, content_type);
512+
ret = ret && physical_displays_.at(i)->SetHDCPState(state, content_type);
512513
}
514+
515+
return ret;
513516
}
514517

515518
void MosaicDisplay::SetHDCPSRM(const int8_t *SRM, uint32_t SRMLength) {

common/core/mosaicdisplay.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ class MosaicDisplay : public NativeDisplay {
109109

110110
void HotPlugUpdate(bool connected);
111111

112-
void SetHDCPState(HWCContentProtection state,
112+
bool SetHDCPState(HWCContentProtection state,
113113
HWCContentType content_type) override;
114114
void SetHDCPSRM(const int8_t *SRM, uint32_t SRMLength) override;
115115

public/hwcdefs.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include <unordered_map>
2626
#include <vector>
27+
#include "hwcthread.h"
2728

2829
namespace hwcomposer {
2930

@@ -40,15 +41,16 @@ enum class HWCBlending : int32_t {
4041

4142
// Enumerations for content protection.
4243
enum HWCContentProtection {
43-
kUnSupported = 0, // Content Protection is not supported.
44-
kUnDesired = 1, // Content Protection is not required.
45-
kDesired = 2 // Content Protection is desired.
44+
kUnSupported = -1, // Content Protection is not supported.
45+
kUnDesired = 0, // Content Protection is not required.
46+
kDesired = 1, // Content Protection is desired.
47+
kEnabled = 2
4648
};
4749

4850
enum HWCContentType {
49-
kInvalid, // Used when disabling HDCP.
50-
kCONTENT_TYPE0, // Can support any HDCP specifiction.
51-
kCONTENT_TYPE1, // Can support only HDCP 2.2 and higher specification.
51+
kInvalid = -1, // Used when disabling HDCP.
52+
kCONTENT_TYPE0 = 0, // Can support any HDCP specifiction.
53+
kCONTENT_TYPE1 = 1, // Can support only HDCP 2.2 and higher specification.
5254
};
5355

5456
enum HWCTransform : uint32_t {

public/nativedisplay.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,9 @@ class NativeDisplay {
400400
* tries to take advantage of any HDCP support advertised by
401401
* the Kernel.
402402
*/
403-
virtual void SetHDCPState(HWCContentProtection /*state*/,
403+
virtual bool SetHDCPState(HWCContentProtection /*state*/,
404404
HWCContentType /*content_type*/) {
405+
return false;
405406
}
406407

407408
virtual void SetPAVPSessionStatus(bool enabled, uint32_t pavp_session_id,

wsi/drm/drmdisplay.cpp

Lines changed: 138 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -178,26 +178,15 @@ bool DrmDisplay::ConnectDisplay(const drmModeModeInfo &mode_info,
178178
return false;
179179
}
180180

181+
uint32_t hdcp_id = 0, hdcp_cp_id = 0;
181182
int value = -1;
182183
GetDrmHDCPObjectProperty("Content Protection", connector, connector_props,
183-
&hdcp_id_prop_, &value);
184+
&hdcp_id, &value);
184185

185-
if (value >= 0) {
186-
switch (value) {
187-
case 0:
188-
current_protection_support_ = HWCContentProtection::kUnDesired;
189-
break;
190-
case 1:
191-
current_protection_support_ = HWCContentProtection::kDesired;
192-
break;
193-
default:
194-
break;
195-
}
186+
GetDrmObjectProperty("CP_Content_Type", connector_props, &hdcp_cp_id);
196187

197-
if (desired_protection_support_ == HWCContentProtection::kUnSupported) {
198-
desired_protection_support_ = current_protection_support_;
199-
}
200-
}
188+
hdcp_thread_.reset(
189+
new DrmHDCPThread(gpu_fd_, connector_, hdcp_id, hdcp_cp_id));
201190

202191
GetDrmHDCPObjectProperty("CP_SRM", connector, connector_props,
203192
&hdcp_srm_id_prop_, &value);
@@ -213,7 +202,6 @@ bool DrmDisplay::ConnectDisplay(const drmModeModeInfo &mode_info,
213202
ITRACE("DCIP3 support not available");
214203

215204
PhysicalDisplay::Connect();
216-
SetHDCPState(desired_protection_support_, content_type_);
217205

218206
drmModePropertyPtr broadcastrgb_props =
219207
drmModeGetProperty(gpu_fd_, broadcastrgb_id_);
@@ -419,30 +407,150 @@ bool DrmDisplay::SetBroadcastRGB(const char *range_property) {
419407
return true;
420408
}
421409

422-
void DrmDisplay::SetHDCPState(HWCContentProtection state,
423-
HWCContentType content_type) {
424-
desired_protection_support_ = state;
425-
content_type_ = content_type;
426-
if (desired_protection_support_ == current_protection_support_)
427-
return;
410+
DrmDisplay::DrmHDCPThread::DrmHDCPThread(uint32_t gpu_fd, uint32_t connector,
411+
uint32_t hdcp_id, uint32_t hdcp_cp_id)
412+
: HWCThread(-8, "HDCPThread"),
413+
gpu_fd_(gpu_fd),
414+
connector_(connector),
415+
hdcp_id_(hdcp_id),
416+
hdcp_cp_id_(hdcp_cp_id) {
417+
}
418+
419+
bool DrmDisplay::DrmHDCPThread::CheckHDCPStatus() {
420+
int val = -1;
421+
uint32_t i;
422+
ScopedDrmObjectPropertyPtr cprops(drmModeObjectGetProperties(
423+
gpu_fd_, connector_, DRM_MODE_OBJECT_CONNECTOR));
424+
for (i = 0; i < cprops->count_props; i++) {
425+
if (cprops->props[i] == hdcp_id_) {
426+
val = cprops->prop_values[i];
427+
break;
428+
}
429+
}
430+
431+
if ((current_state_ && val == 2) || (!current_state_ && val == 0))
432+
return true;
428433

429-
if (hdcp_id_prop_ <= 0) {
434+
return false;
435+
}
436+
437+
bool DrmDisplay::DrmHDCPThread::DrmConnectorSetupHDCP() {
438+
int i;
439+
ScopedDrmAtomicReqPtr pset(drmModeAtomicAlloc());
440+
441+
int ret = drmModeAtomicAddProperty(pset.get(), connector_, hdcp_id_,
442+
current_state_) < 0;
443+
444+
if (current_state_ && (hdcp_cp_id_ > 0))
445+
ret = ret ||
446+
drmModeAtomicAddProperty(pset.get(), connector_, hdcp_cp_id_,
447+
cp_type_) < 0;
448+
if (ret) {
449+
ETRACE("Unable to fill pset for HDCP\n");
450+
return false;
451+
}
452+
453+
ret = drmModeAtomicCommit(gpu_fd_, pset.get(), DRM_MODE_ATOMIC_ALLOW_MODESET,
454+
NULL);
455+
if (ret) {
456+
ETRACE("Failed to commit HDCP ret %d errno %d : %s\n", ret, errno,
457+
PRINTERROR());
458+
return false;
459+
}
460+
461+
/* Wait for Enable should be 5.1 Sec * 3(kernel reattempt cnt) */
462+
for (i = 0; i < 160; i++) {
463+
if (CheckHDCPStatus())
464+
return true;
465+
usleep(100 * 1000);
466+
}
467+
468+
return false;
469+
}
470+
471+
bool DrmDisplay::DrmHDCPThread::SetHDCPState(bool enable, uint32_t type) {
472+
bool ret;
473+
474+
if ((hdcp_id_ <= 0)) {
430475
ETRACE("Cannot set HDCP state as Connector property is not supported \n");
431-
return;
476+
return false;
477+
}
478+
479+
if ((hdcp_cp_id_ <= 0) && (type == 1)) {
480+
ETRACE("Content type property unavailable. HDCP 2.2 cannot be enabled\n");
481+
return false;
482+
}
483+
484+
if (enable == current_state_) {
485+
ITRACE("HDCP already enabled");
486+
return true;
487+
}
488+
489+
current_state_ = enable;
490+
cp_type_ = type;
491+
492+
if (!enable) {
493+
Exit();
494+
ret = DrmConnectorSetupHDCP();
495+
} else {
496+
ret = DrmConnectorSetupHDCP();
497+
if (ret && !InitWorker()) {
498+
ETRACE("Failed to start hdcp poll thread. %s", PRINTERROR());
499+
}
432500
}
433501

502+
if (!ret) {
503+
current_state_ = !enable;
504+
// if we tried to enable hdcp and failed
505+
// toggle the property from desired -> undesired
506+
if (enable)
507+
DrmConnectorSetupHDCP();
508+
}
509+
510+
return ret;
511+
}
512+
513+
void DrmDisplay::DrmHDCPThread::HandleWait() {
514+
usleep(50 * 1000);
515+
}
516+
517+
void DrmDisplay::DrmHDCPThread::HandleRoutine() {
518+
if (!CheckHDCPStatus()) {
519+
ETRACE("HDCP link failed. Re-trying to establish the link");
520+
DrmConnectorSetupHDCP();
521+
}
522+
}
523+
524+
bool DrmDisplay::SetHDCPState(HWCContentProtection state,
525+
HWCContentType content_type) {
526+
bool ret = false;
527+
std::string err_str;
434528
if (!(connection_state_ & kConnected)) {
435-
return;
529+
ITRACE("Display not connected. Cannot set HDCP state");
530+
return ret;
436531
}
437532

438-
current_protection_support_ = desired_protection_support_;
439533
uint32_t value = 0;
440-
if (current_protection_support_ == kDesired) {
534+
if (state == kDesired) {
441535
value = 1;
442536
}
443537

444-
drmModeConnectorSetProperty(gpu_fd_, connector_, hdcp_id_prop_, value);
445-
ETRACE("Ignored Content type. \n");
538+
ret = hdcp_thread_->SetHDCPState(value, content_type);
539+
if (ret) {
540+
if (value)
541+
err_str = "Successfully enabled HDCP\n";
542+
else
543+
err_str = "Successfully disabled HDCP\n";
544+
} else {
545+
if (value)
546+
err_str = "Unable to enable HDCP\n";
547+
else
548+
err_str = "Unable to disable HDCP\n";
549+
}
550+
551+
ITRACE("%s", err_str.c_str());
552+
553+
return ret;
446554
}
447555

448556
void DrmDisplay::SetHDCPSRM(const int8_t *SRM, uint32_t SRMLength) {

wsi/drm/drmdisplay.h

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class DrmDisplay : public PhysicalDisplay {
5353

5454
bool SetBroadcastRGB(const char *range_property) override;
5555

56-
void SetHDCPState(HWCContentProtection state,
56+
bool SetHDCPState(HWCContentProtection state,
5757
HWCContentType content_type) override;
5858
void SetHDCPSRM(const int8_t *SRM, uint32_t SRMLength) override;
5959

@@ -108,6 +108,31 @@ class DrmDisplay : public PhysicalDisplay {
108108
void HandleLazyInitialization() override;
109109

110110
private:
111+
class DrmHDCPThread : public HWCThread {
112+
public:
113+
DrmHDCPThread(uint32_t gpu_fd, uint32_t connector, uint32_t hdcp_id,
114+
uint32_t hdcp_cp_id);
115+
~DrmHDCPThread() {
116+
Exit();
117+
}
118+
119+
bool SetHDCPState(bool enable, uint32_t type);
120+
121+
protected:
122+
void HandleRoutine() override;
123+
void HandleWait() override;
124+
125+
private:
126+
bool DrmConnectorSetupHDCP();
127+
bool CheckHDCPStatus();
128+
uint32_t gpu_fd_;
129+
uint32_t connector_;
130+
uint32_t hdcp_id_;
131+
uint32_t hdcp_cp_id_;
132+
bool current_state_ = false;
133+
uint32_t cp_type_ = 0;
134+
};
135+
111136
void ShutDownPipe();
112137
void GetDrmObjectPropertyValue(const char *name,
113138
const ScopedDrmObjectPropertyPtr &props,
@@ -154,7 +179,6 @@ class DrmDisplay : public PhysicalDisplay {
154179
uint32_t old_blob_id_ = 0;
155180
uint32_t active_prop_ = 0;
156181
uint32_t mode_id_prop_ = 0;
157-
uint32_t hdcp_id_prop_ = 0;
158182
uint32_t hdcp_srm_id_prop_ = 0;
159183
uint32_t edid_prop_ = 0;
160184
uint32_t canvas_color_prop_ = 0;
@@ -164,15 +188,12 @@ class DrmDisplay : public PhysicalDisplay {
164188
int64_t broadcastrgb_full_ = -1;
165189
int64_t broadcastrgb_automatic_ = -1;
166190
uint32_t flags_ = DRM_MODE_ATOMIC_ALLOW_MODESET;
167-
HWCContentProtection current_protection_support_ =
168-
HWCContentProtection::kUnSupported;
169-
HWCContentProtection desired_protection_support_ =
170-
HWCContentProtection::kUnSupported;
171191
drmModeModeInfo current_mode_;
172-
HWCContentType content_type_ = kCONTENT_TYPE0;
173192
std::vector<drmModeModeInfo> modes_;
174193
SpinLock display_lock_;
194+
bool protection_changed = false;
175195
DrmDisplayManager *manager_;
196+
std::unique_ptr<DrmHDCPThread> hdcp_thread_;
176197
};
177198

178199
} // namespace hwcomposer

0 commit comments

Comments
 (0)