Skip to content

Commit 2d4254e

Browse files
ramalingamcdanvet
authored andcommitted
drm/i915: Implement the HDCP2.2 support for HDMI
Implements the HDMI adaptation specific HDCP2.2 operations. Basically these are DDC read and write for authenticating through HDCP2.2 messages. v2: Rebased. v3: No more special handling of Gmbus burst read for AKE_SEND_CERT. Style fixed with few naming. [Uma] %s/PARING/PAIRING v4: msg_sz is initialized at definition. Lookup table is defined for HDMI HDCP2.2 msgs [Daniel]. v5: Rebased. v6: Make a function as inline [Uma] %s/uintxx_t/uxx v7: Errors due to sinks are reported as DEBUG logs. Adjust to the new mei interface. v8: ARRAY_SIZE for the # of array members [Jon & Daniel]. hdcp adaptation is added as a const in the hdcp_shim [Daniel] Signed-off-by: Ramalingam C <[email protected]> Reviewed-by: Uma Shankar <[email protected]> Signed-off-by: Daniel Vetter <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 238d3a9 commit 2d4254e

File tree

1 file changed

+189
-0
lines changed

1 file changed

+189
-0
lines changed

drivers/gpu/drm/i915/intel_hdmi.c

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,190 @@ bool intel_hdmi_hdcp_check_link(struct intel_digital_port *intel_dig_port)
11291129
return true;
11301130
}
11311131

1132+
static struct hdcp2_hdmi_msg_data {
1133+
u8 msg_id;
1134+
u32 timeout;
1135+
u32 timeout2;
1136+
} hdcp2_msg_data[] = {
1137+
{HDCP_2_2_AKE_INIT, 0, 0},
1138+
{HDCP_2_2_AKE_SEND_CERT, HDCP_2_2_CERT_TIMEOUT_MS, 0},
1139+
{HDCP_2_2_AKE_NO_STORED_KM, 0, 0},
1140+
{HDCP_2_2_AKE_STORED_KM, 0, 0},
1141+
{HDCP_2_2_AKE_SEND_HPRIME, HDCP_2_2_HPRIME_PAIRED_TIMEOUT_MS,
1142+
HDCP_2_2_HPRIME_NO_PAIRED_TIMEOUT_MS},
1143+
{HDCP_2_2_AKE_SEND_PAIRING_INFO, HDCP_2_2_PAIRING_TIMEOUT_MS,
1144+
0},
1145+
{HDCP_2_2_LC_INIT, 0, 0},
1146+
{HDCP_2_2_LC_SEND_LPRIME, HDCP_2_2_HDMI_LPRIME_TIMEOUT_MS, 0},
1147+
{HDCP_2_2_SKE_SEND_EKS, 0, 0},
1148+
{HDCP_2_2_REP_SEND_RECVID_LIST,
1149+
HDCP_2_2_RECVID_LIST_TIMEOUT_MS, 0},
1150+
{HDCP_2_2_REP_SEND_ACK, 0, 0},
1151+
{HDCP_2_2_REP_STREAM_MANAGE, 0, 0},
1152+
{HDCP_2_2_REP_STREAM_READY, HDCP_2_2_STREAM_READY_TIMEOUT_MS,
1153+
0},
1154+
};
1155+
1156+
static
1157+
int intel_hdmi_hdcp2_read_rx_status(struct intel_digital_port *intel_dig_port,
1158+
uint8_t *rx_status)
1159+
{
1160+
return intel_hdmi_hdcp_read(intel_dig_port,
1161+
HDCP_2_2_HDMI_REG_RXSTATUS_OFFSET,
1162+
rx_status,
1163+
HDCP_2_2_HDMI_RXSTATUS_LEN);
1164+
}
1165+
1166+
static int get_hdcp2_msg_timeout(u8 msg_id, bool is_paired)
1167+
{
1168+
int i;
1169+
1170+
for (i = 0; i < ARRAY_SIZE(hdcp2_msg_data); i++)
1171+
if (hdcp2_msg_data[i].msg_id == msg_id &&
1172+
(msg_id != HDCP_2_2_AKE_SEND_HPRIME || is_paired))
1173+
return hdcp2_msg_data[i].timeout;
1174+
else if (hdcp2_msg_data[i].msg_id == msg_id)
1175+
return hdcp2_msg_data[i].timeout2;
1176+
1177+
return -EINVAL;
1178+
}
1179+
1180+
static inline
1181+
int hdcp2_detect_msg_availability(struct intel_digital_port *intel_digital_port,
1182+
u8 msg_id, bool *msg_ready,
1183+
ssize_t *msg_sz)
1184+
{
1185+
u8 rx_status[HDCP_2_2_HDMI_RXSTATUS_LEN];
1186+
int ret;
1187+
1188+
ret = intel_hdmi_hdcp2_read_rx_status(intel_digital_port, rx_status);
1189+
if (ret < 0) {
1190+
DRM_DEBUG_KMS("rx_status read failed. Err %d\n", ret);
1191+
return ret;
1192+
}
1193+
1194+
*msg_sz = ((HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(rx_status[1]) << 8) |
1195+
rx_status[0]);
1196+
1197+
if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST)
1198+
*msg_ready = (HDCP_2_2_HDMI_RXSTATUS_READY(rx_status[1]) &&
1199+
*msg_sz);
1200+
else
1201+
*msg_ready = *msg_sz;
1202+
1203+
return 0;
1204+
}
1205+
1206+
static ssize_t
1207+
intel_hdmi_hdcp2_wait_for_msg(struct intel_digital_port *intel_dig_port,
1208+
u8 msg_id, bool paired)
1209+
{
1210+
bool msg_ready = false;
1211+
int timeout, ret;
1212+
ssize_t msg_sz = 0;
1213+
1214+
timeout = get_hdcp2_msg_timeout(msg_id, paired);
1215+
if (timeout < 0)
1216+
return timeout;
1217+
1218+
ret = __wait_for(ret = hdcp2_detect_msg_availability(intel_dig_port,
1219+
msg_id, &msg_ready,
1220+
&msg_sz),
1221+
!ret && msg_ready && msg_sz, timeout * 1000,
1222+
1000, 5 * 1000);
1223+
if (ret)
1224+
DRM_DEBUG_KMS("msg_id: %d, ret: %d, timeout: %d\n",
1225+
msg_id, ret, timeout);
1226+
1227+
return ret ? ret : msg_sz;
1228+
}
1229+
1230+
static
1231+
int intel_hdmi_hdcp2_write_msg(struct intel_digital_port *intel_dig_port,
1232+
void *buf, size_t size)
1233+
{
1234+
unsigned int offset;
1235+
1236+
offset = HDCP_2_2_HDMI_REG_WR_MSG_OFFSET;
1237+
return intel_hdmi_hdcp_write(intel_dig_port, offset, buf, size);
1238+
}
1239+
1240+
static
1241+
int intel_hdmi_hdcp2_read_msg(struct intel_digital_port *intel_dig_port,
1242+
u8 msg_id, void *buf, size_t size)
1243+
{
1244+
struct intel_hdmi *hdmi = &intel_dig_port->hdmi;
1245+
struct intel_hdcp *hdcp = &hdmi->attached_connector->hdcp;
1246+
unsigned int offset;
1247+
ssize_t ret;
1248+
1249+
ret = intel_hdmi_hdcp2_wait_for_msg(intel_dig_port, msg_id,
1250+
hdcp->is_paired);
1251+
if (ret < 0)
1252+
return ret;
1253+
1254+
/*
1255+
* Available msg size should be equal to or lesser than the
1256+
* available buffer.
1257+
*/
1258+
if (ret > size) {
1259+
DRM_DEBUG_KMS("msg_sz(%zd) is more than exp size(%zu)\n",
1260+
ret, size);
1261+
return -1;
1262+
}
1263+
1264+
offset = HDCP_2_2_HDMI_REG_RD_MSG_OFFSET;
1265+
ret = intel_hdmi_hdcp_read(intel_dig_port, offset, buf, ret);
1266+
if (ret)
1267+
DRM_DEBUG_KMS("Failed to read msg_id: %d(%zd)\n", msg_id, ret);
1268+
1269+
return ret;
1270+
}
1271+
1272+
static
1273+
int intel_hdmi_hdcp2_check_link(struct intel_digital_port *intel_dig_port)
1274+
{
1275+
u8 rx_status[HDCP_2_2_HDMI_RXSTATUS_LEN];
1276+
int ret;
1277+
1278+
ret = intel_hdmi_hdcp2_read_rx_status(intel_dig_port, rx_status);
1279+
if (ret)
1280+
return ret;
1281+
1282+
/*
1283+
* Re-auth request and Link Integrity Failures are represented by
1284+
* same bit. i.e reauth_req.
1285+
*/
1286+
if (HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(rx_status[1]))
1287+
ret = HDCP_REAUTH_REQUEST;
1288+
else if (HDCP_2_2_HDMI_RXSTATUS_READY(rx_status[1]))
1289+
ret = HDCP_TOPOLOGY_CHANGE;
1290+
1291+
return ret;
1292+
}
1293+
1294+
static
1295+
int intel_hdmi_hdcp2_capable(struct intel_digital_port *intel_dig_port,
1296+
bool *capable)
1297+
{
1298+
u8 hdcp2_version;
1299+
int ret;
1300+
1301+
*capable = false;
1302+
ret = intel_hdmi_hdcp_read(intel_dig_port, HDCP_2_2_HDMI_REG_VER_OFFSET,
1303+
&hdcp2_version, sizeof(hdcp2_version));
1304+
if (!ret && hdcp2_version & HDCP_2_2_HDMI_SUPPORT_MASK)
1305+
*capable = true;
1306+
1307+
return ret;
1308+
}
1309+
1310+
static inline
1311+
enum hdcp_wired_protocol intel_hdmi_hdcp2_protocol(void)
1312+
{
1313+
return HDCP_PROTOCOL_HDMI;
1314+
}
1315+
11321316
static const struct intel_hdcp_shim intel_hdmi_hdcp_shim = {
11331317
.write_an_aksv = intel_hdmi_hdcp_write_an_aksv,
11341318
.read_bksv = intel_hdmi_hdcp_read_bksv,
@@ -1140,6 +1324,11 @@ static const struct intel_hdcp_shim intel_hdmi_hdcp_shim = {
11401324
.read_v_prime_part = intel_hdmi_hdcp_read_v_prime_part,
11411325
.toggle_signalling = intel_hdmi_hdcp_toggle_signalling,
11421326
.check_link = intel_hdmi_hdcp_check_link,
1327+
.write_2_2_msg = intel_hdmi_hdcp2_write_msg,
1328+
.read_2_2_msg = intel_hdmi_hdcp2_read_msg,
1329+
.check_2_2_link = intel_hdmi_hdcp2_check_link,
1330+
.hdcp_2_2_capable = intel_hdmi_hdcp2_capable,
1331+
.protocol = HDCP_PROTOCOL_HDMI,
11431332
};
11441333

11451334
static void intel_hdmi_prepare(struct intel_encoder *encoder,

0 commit comments

Comments
 (0)