Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: bridge: cdns-mhdp8546: Enable HDCP

This patch enable HDCP in MHDP driver.

Signed-off-by: Parshuram Thombare <pthombar@cadence.com>
Reviewed-by: Robert Foss <robert.foss@linaro.org>
Signed-off-by: Robert Foss <robert.foss@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/1618078542-30679-1-git-send-email-pthombar@cadence.com

authored by

Parshuram Thombare and committed by
Robert Foss
6a3608ea 7169d082

+801 -13
+1 -1
drivers/gpu/drm/bridge/cadence/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 obj-$(CONFIG_DRM_CDNS_MHDP8546) += cdns-mhdp8546.o 3 - cdns-mhdp8546-y := cdns-mhdp8546-core.o 3 + cdns-mhdp8546-y := cdns-mhdp8546-core.o cdns-mhdp8546-hdcp.o 4 4 cdns-mhdp8546-$(CONFIG_DRM_CDNS_MHDP8546_J721E) += cdns-mhdp8546-j721e.o
+116 -12
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
··· 42 42 #include <drm/drm_connector.h> 43 43 #include <drm/drm_crtc_helper.h> 44 44 #include <drm/drm_dp_helper.h> 45 + #include <drm/drm_hdcp.h> 45 46 #include <drm/drm_modeset_helper_vtables.h> 46 47 #include <drm/drm_print.h> 47 48 #include <drm/drm_probe_helper.h> ··· 50 49 #include <asm/unaligned.h> 51 50 52 51 #include "cdns-mhdp8546-core.h" 53 - 52 + #include "cdns-mhdp8546-hdcp.h" 54 53 #include "cdns-mhdp8546-j721e.h" 55 54 56 55 static int cdns_mhdp_mailbox_read(struct cdns_mhdp_device *mhdp) ··· 1615 1614 return MODE_OK; 1616 1615 } 1617 1616 1617 + static int cdns_mhdp_connector_atomic_check(struct drm_connector *conn, 1618 + struct drm_atomic_state *state) 1619 + { 1620 + struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn); 1621 + struct drm_connector_state *old_state, *new_state; 1622 + struct drm_crtc_state *crtc_state; 1623 + u64 old_cp, new_cp; 1624 + 1625 + if (!mhdp->hdcp_supported) 1626 + return 0; 1627 + 1628 + old_state = drm_atomic_get_old_connector_state(state, conn); 1629 + new_state = drm_atomic_get_new_connector_state(state, conn); 1630 + old_cp = old_state->content_protection; 1631 + new_cp = new_state->content_protection; 1632 + 1633 + if (old_state->hdcp_content_type != new_state->hdcp_content_type && 1634 + new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { 1635 + new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; 1636 + goto mode_changed; 1637 + } 1638 + 1639 + if (!new_state->crtc) { 1640 + if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED) 1641 + new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; 1642 + return 0; 1643 + } 1644 + 1645 + if (old_cp == new_cp || 1646 + (old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED && 1647 + new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)) 1648 + return 0; 1649 + 1650 + mode_changed: 1651 + crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc); 1652 + crtc_state->mode_changed = true; 1653 + 1654 + return 0; 1655 + } 1656 + 1618 1657 static const struct drm_connector_helper_funcs cdns_mhdp_conn_helper_funcs = { 1619 1658 .detect_ctx = cdns_mhdp_connector_detect, 1620 1659 .get_modes = cdns_mhdp_get_modes, 1621 1660 .mode_valid = cdns_mhdp_mode_valid, 1661 + .atomic_check = cdns_mhdp_connector_atomic_check, 1622 1662 }; 1623 1663 1624 1664 static const struct drm_connector_funcs cdns_mhdp_conn_funcs = { ··· 1704 1662 return ret; 1705 1663 } 1706 1664 1707 - return 0; 1665 + if (mhdp->hdcp_supported) 1666 + ret = drm_connector_attach_content_protection_property(conn, true); 1667 + 1668 + return ret; 1708 1669 } 1709 1670 1710 1671 static int cdns_mhdp_attach(struct drm_bridge *bridge, ··· 2002 1957 if (WARN_ON(!conn_state)) 2003 1958 goto out; 2004 1959 1960 + if (mhdp->hdcp_supported && 1961 + mhdp->hw_state == MHDP_HW_READY && 1962 + conn_state->content_protection == 1963 + DRM_MODE_CONTENT_PROTECTION_DESIRED) { 1964 + mutex_unlock(&mhdp->link_mutex); 1965 + cdns_mhdp_hdcp_enable(mhdp, conn_state->hdcp_content_type); 1966 + mutex_lock(&mhdp->link_mutex); 1967 + } 1968 + 2005 1969 crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); 2006 1970 if (WARN_ON(!crtc_state)) 2007 1971 goto out; ··· 2053 1999 dev_dbg(mhdp->dev, "%s\n", __func__); 2054 2000 2055 2001 mutex_lock(&mhdp->link_mutex); 2002 + 2003 + if (mhdp->hdcp_supported) 2004 + cdns_mhdp_hdcp_disable(mhdp); 2056 2005 2057 2006 mhdp->bridge_enabled = false; 2058 2007 cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp); ··· 2345 2288 struct cdns_mhdp_device *mhdp = data; 2346 2289 u32 apb_stat, sw_ev0; 2347 2290 bool bridge_attached; 2348 - int ret; 2349 2291 2350 2292 apb_stat = readl(mhdp->regs + CDNS_APB_INT_STATUS); 2351 2293 if (!(apb_stat & CDNS_APB_INT_MASK_SW_EVENT_INT)) ··· 2363 2307 spin_unlock(&mhdp->start_lock); 2364 2308 2365 2309 if (bridge_attached && (sw_ev0 & CDNS_DPTX_HPD)) { 2366 - ret = cdns_mhdp_update_link_status(mhdp); 2367 - if (mhdp->connector.dev) { 2368 - if (ret < 0) 2369 - schedule_work(&mhdp->modeset_retry_work); 2370 - else 2371 - drm_kms_helper_hotplug_event(mhdp->bridge.dev); 2372 - } else { 2373 - drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp)); 2374 - } 2310 + schedule_work(&mhdp->hpd_work); 2311 + } 2312 + 2313 + if (sw_ev0 & ~CDNS_DPTX_HPD) { 2314 + mhdp->sw_events |= (sw_ev0 & ~CDNS_DPTX_HPD); 2315 + wake_up(&mhdp->sw_events_wq); 2375 2316 } 2376 2317 2377 2318 return IRQ_HANDLED; 2319 + } 2320 + 2321 + u32 cdns_mhdp_wait_for_sw_event(struct cdns_mhdp_device *mhdp, u32 event) 2322 + { 2323 + u32 ret; 2324 + 2325 + ret = wait_event_timeout(mhdp->sw_events_wq, 2326 + mhdp->sw_events & event, 2327 + msecs_to_jiffies(500)); 2328 + if (!ret) { 2329 + dev_dbg(mhdp->dev, "SW event 0x%x timeout\n", event); 2330 + goto sw_event_out; 2331 + } 2332 + 2333 + ret = mhdp->sw_events; 2334 + mhdp->sw_events &= ~event; 2335 + 2336 + sw_event_out: 2337 + return ret; 2338 + } 2339 + 2340 + static void cdns_mhdp_hpd_work(struct work_struct *work) 2341 + { 2342 + struct cdns_mhdp_device *mhdp = container_of(work, 2343 + struct cdns_mhdp_device, 2344 + hpd_work); 2345 + int ret; 2346 + 2347 + ret = cdns_mhdp_update_link_status(mhdp); 2348 + if (mhdp->connector.dev) { 2349 + if (ret < 0) 2350 + schedule_work(&mhdp->modeset_retry_work); 2351 + else 2352 + drm_kms_helper_hotplug_event(mhdp->bridge.dev); 2353 + } else { 2354 + drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp)); 2355 + } 2378 2356 } 2379 2357 2380 2358 static int cdns_mhdp_probe(struct platform_device *pdev) ··· 2444 2354 if (IS_ERR(mhdp->regs)) { 2445 2355 dev_err(dev, "Failed to get memory resource\n"); 2446 2356 return PTR_ERR(mhdp->regs); 2357 + } 2358 + 2359 + mhdp->sapb_regs = devm_platform_ioremap_resource_byname(pdev, "mhdptx-sapb"); 2360 + if (IS_ERR(mhdp->sapb_regs)) { 2361 + mhdp->hdcp_supported = false; 2362 + dev_warn(dev, 2363 + "Failed to get SAPB memory resource, HDCP not supported\n"); 2364 + } else { 2365 + mhdp->hdcp_supported = true; 2447 2366 } 2448 2367 2449 2368 mhdp->phy = devm_of_phy_get_by_index(dev, pdev->dev.of_node, 0); ··· 2529 2430 2530 2431 /* Initialize the work for modeset in case of link train failure */ 2531 2432 INIT_WORK(&mhdp->modeset_retry_work, cdns_mhdp_modeset_retry_fn); 2433 + INIT_WORK(&mhdp->hpd_work, cdns_mhdp_hpd_work); 2532 2434 2533 2435 init_waitqueue_head(&mhdp->fw_load_wq); 2436 + init_waitqueue_head(&mhdp->sw_events_wq); 2534 2437 2535 2438 ret = cdns_mhdp_load_firmware(mhdp); 2536 2439 if (ret) 2537 2440 goto phy_exit; 2441 + 2442 + if (mhdp->hdcp_supported) 2443 + cdns_mhdp_hdcp_init(mhdp); 2538 2444 2539 2445 drm_bridge_add(&mhdp->bridge); 2540 2446
+22
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
··· 47 47 48 48 #define CDNS_SW_EVENT0 0x00044 49 49 #define CDNS_DPTX_HPD BIT(0) 50 + #define CDNS_HDCP_TX_STATUS BIT(4) 51 + #define CDNS_HDCP2_TX_IS_KM_STORED BIT(5) 52 + #define CDNS_HDCP2_TX_STORE_KM BIT(6) 53 + #define CDNS_HDCP_TX_IS_RCVR_ID_VALID BIT(7) 50 54 51 55 #define CDNS_SW_EVENT1 0x00048 52 56 #define CDNS_SW_EVENT2 0x0004c ··· 343 339 #define to_cdns_mhdp_bridge_state(s) \ 344 340 container_of(s, struct cdns_mhdp_bridge_state, base) 345 341 342 + struct cdns_mhdp_hdcp { 343 + struct delayed_work check_work; 344 + struct work_struct prop_work; 345 + struct mutex mutex; /* mutex to protect hdcp.value */ 346 + u32 value; 347 + u8 hdcp_content_type; 348 + }; 349 + 346 350 struct cdns_mhdp_device { 347 351 void __iomem *regs; 352 + void __iomem *sapb_regs; 348 353 void __iomem *j721e_regs; 349 354 350 355 struct device *dev; ··· 405 392 406 393 /* Work struct to schedule a uevent on link train failure */ 407 394 struct work_struct modeset_retry_work; 395 + struct work_struct hpd_work; 396 + 397 + wait_queue_head_t sw_events_wq; 398 + u32 sw_events; 399 + 400 + struct cdns_mhdp_hdcp hdcp; 401 + bool hdcp_supported; 408 402 }; 409 403 410 404 #define connector_to_mhdp(x) container_of(x, struct cdns_mhdp_device, connector) 411 405 #define bridge_to_mhdp(x) container_of(x, struct cdns_mhdp_device, bridge) 406 + 407 + u32 cdns_mhdp_wait_for_sw_event(struct cdns_mhdp_device *mhdp, uint32_t event); 412 408 413 409 #endif
+570
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Cadence MHDP8546 DP bridge driver. 4 + * 5 + * Copyright (C) 2020 Cadence Design Systems, Inc. 6 + * 7 + */ 8 + 9 + #include <linux/io.h> 10 + #include <linux/iopoll.h> 11 + 12 + #include <asm/unaligned.h> 13 + 14 + #include <drm/drm_hdcp.h> 15 + 16 + #include "cdns-mhdp8546-hdcp.h" 17 + 18 + static int cdns_mhdp_secure_mailbox_read(struct cdns_mhdp_device *mhdp) 19 + { 20 + int ret, empty; 21 + 22 + WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex)); 23 + 24 + ret = readx_poll_timeout(readl, mhdp->sapb_regs + CDNS_MAILBOX_EMPTY, 25 + empty, !empty, MAILBOX_RETRY_US, 26 + MAILBOX_TIMEOUT_US); 27 + if (ret < 0) 28 + return ret; 29 + 30 + return readl(mhdp->sapb_regs + CDNS_MAILBOX_RX_DATA) & 0xff; 31 + } 32 + 33 + static int cdns_mhdp_secure_mailbox_write(struct cdns_mhdp_device *mhdp, 34 + u8 val) 35 + { 36 + int ret, full; 37 + 38 + WARN_ON(!mutex_is_locked(&mhdp->mbox_mutex)); 39 + 40 + ret = readx_poll_timeout(readl, mhdp->sapb_regs + CDNS_MAILBOX_FULL, 41 + full, !full, MAILBOX_RETRY_US, 42 + MAILBOX_TIMEOUT_US); 43 + if (ret < 0) 44 + return ret; 45 + 46 + writel(val, mhdp->sapb_regs + CDNS_MAILBOX_TX_DATA); 47 + 48 + return 0; 49 + } 50 + 51 + static int cdns_mhdp_secure_mailbox_recv_header(struct cdns_mhdp_device *mhdp, 52 + u8 module_id, 53 + u8 opcode, 54 + u16 req_size) 55 + { 56 + u32 mbox_size, i; 57 + u8 header[4]; 58 + int ret; 59 + 60 + /* read the header of the message */ 61 + for (i = 0; i < sizeof(header); i++) { 62 + ret = cdns_mhdp_secure_mailbox_read(mhdp); 63 + if (ret < 0) 64 + return ret; 65 + 66 + header[i] = ret; 67 + } 68 + 69 + mbox_size = get_unaligned_be16(header + 2); 70 + 71 + if (opcode != header[0] || module_id != header[1] || 72 + (opcode != HDCP_TRAN_IS_REC_ID_VALID && req_size != mbox_size)) { 73 + for (i = 0; i < mbox_size; i++) 74 + if (cdns_mhdp_secure_mailbox_read(mhdp) < 0) 75 + break; 76 + return -EINVAL; 77 + } 78 + 79 + return 0; 80 + } 81 + 82 + static int cdns_mhdp_secure_mailbox_recv_data(struct cdns_mhdp_device *mhdp, 83 + u8 *buff, u16 buff_size) 84 + { 85 + int ret; 86 + u32 i; 87 + 88 + for (i = 0; i < buff_size; i++) { 89 + ret = cdns_mhdp_secure_mailbox_read(mhdp); 90 + if (ret < 0) 91 + return ret; 92 + 93 + buff[i] = ret; 94 + } 95 + 96 + return 0; 97 + } 98 + 99 + static int cdns_mhdp_secure_mailbox_send(struct cdns_mhdp_device *mhdp, 100 + u8 module_id, 101 + u8 opcode, 102 + u16 size, 103 + u8 *message) 104 + { 105 + u8 header[4]; 106 + int ret; 107 + u32 i; 108 + 109 + header[0] = opcode; 110 + header[1] = module_id; 111 + put_unaligned_be16(size, header + 2); 112 + 113 + for (i = 0; i < sizeof(header); i++) { 114 + ret = cdns_mhdp_secure_mailbox_write(mhdp, header[i]); 115 + if (ret) 116 + return ret; 117 + } 118 + 119 + for (i = 0; i < size; i++) { 120 + ret = cdns_mhdp_secure_mailbox_write(mhdp, message[i]); 121 + if (ret) 122 + return ret; 123 + } 124 + 125 + return 0; 126 + } 127 + 128 + static int cdns_mhdp_hdcp_get_status(struct cdns_mhdp_device *mhdp, 129 + u16 *hdcp_port_status) 130 + { 131 + u8 hdcp_status[HDCP_STATUS_SIZE]; 132 + int ret; 133 + 134 + mutex_lock(&mhdp->mbox_mutex); 135 + ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, 136 + HDCP_TRAN_STATUS_CHANGE, 0, NULL); 137 + if (ret) 138 + goto err_get_hdcp_status; 139 + 140 + ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX, 141 + HDCP_TRAN_STATUS_CHANGE, 142 + sizeof(hdcp_status)); 143 + if (ret) 144 + goto err_get_hdcp_status; 145 + 146 + ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, hdcp_status, 147 + sizeof(hdcp_status)); 148 + if (ret) 149 + goto err_get_hdcp_status; 150 + 151 + *hdcp_port_status = ((u16)(hdcp_status[0] << 8) | hdcp_status[1]); 152 + 153 + err_get_hdcp_status: 154 + mutex_unlock(&mhdp->mbox_mutex); 155 + 156 + return ret; 157 + } 158 + 159 + static u8 cdns_mhdp_hdcp_handle_status(struct cdns_mhdp_device *mhdp, 160 + u16 status) 161 + { 162 + u8 err = GET_HDCP_PORT_STS_LAST_ERR(status); 163 + 164 + if (err) 165 + dev_dbg(mhdp->dev, "HDCP Error = %d", err); 166 + 167 + return err; 168 + } 169 + 170 + static int cdns_mhdp_hdcp_rx_id_valid_response(struct cdns_mhdp_device *mhdp, 171 + u8 valid) 172 + { 173 + int ret; 174 + 175 + mutex_lock(&mhdp->mbox_mutex); 176 + ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, 177 + HDCP_TRAN_RESPOND_RECEIVER_ID_VALID, 178 + 1, &valid); 179 + mutex_unlock(&mhdp->mbox_mutex); 180 + 181 + return ret; 182 + } 183 + 184 + static int cdns_mhdp_hdcp_rx_id_valid(struct cdns_mhdp_device *mhdp, 185 + u8 *recv_num, u8 *hdcp_rx_id) 186 + { 187 + u8 rec_id_hdr[2]; 188 + u8 status; 189 + int ret; 190 + 191 + mutex_lock(&mhdp->mbox_mutex); 192 + ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, 193 + HDCP_TRAN_IS_REC_ID_VALID, 0, NULL); 194 + if (ret) 195 + goto err_rx_id_valid; 196 + 197 + ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX, 198 + HDCP_TRAN_IS_REC_ID_VALID, 199 + sizeof(status)); 200 + if (ret) 201 + goto err_rx_id_valid; 202 + 203 + ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, rec_id_hdr, 2); 204 + if (ret) 205 + goto err_rx_id_valid; 206 + 207 + *recv_num = rec_id_hdr[0]; 208 + 209 + ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, hdcp_rx_id, 5 * *recv_num); 210 + 211 + err_rx_id_valid: 212 + mutex_unlock(&mhdp->mbox_mutex); 213 + 214 + return ret; 215 + } 216 + 217 + static int cdns_mhdp_hdcp_km_stored_resp(struct cdns_mhdp_device *mhdp, 218 + u32 size, u8 *km) 219 + { 220 + int ret; 221 + 222 + mutex_lock(&mhdp->mbox_mutex); 223 + ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, 224 + HDCP2X_TX_RESPOND_KM, size, km); 225 + mutex_unlock(&mhdp->mbox_mutex); 226 + 227 + return ret; 228 + } 229 + 230 + static int cdns_mhdp_hdcp_tx_is_km_stored(struct cdns_mhdp_device *mhdp, 231 + u8 *resp, u32 size) 232 + { 233 + int ret; 234 + 235 + mutex_lock(&mhdp->mbox_mutex); 236 + ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, 237 + HDCP2X_TX_IS_KM_STORED, 0, NULL); 238 + if (ret) 239 + goto err_is_km_stored; 240 + 241 + ret = cdns_mhdp_secure_mailbox_recv_header(mhdp, MB_MODULE_ID_HDCP_TX, 242 + HDCP2X_TX_IS_KM_STORED, 243 + size); 244 + if (ret) 245 + goto err_is_km_stored; 246 + 247 + ret = cdns_mhdp_secure_mailbox_recv_data(mhdp, resp, size); 248 + err_is_km_stored: 249 + mutex_unlock(&mhdp->mbox_mutex); 250 + 251 + return ret; 252 + } 253 + 254 + static int cdns_mhdp_hdcp_tx_config(struct cdns_mhdp_device *mhdp, 255 + u8 hdcp_cfg) 256 + { 257 + int ret; 258 + 259 + mutex_lock(&mhdp->mbox_mutex); 260 + ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, 261 + HDCP_TRAN_CONFIGURATION, 1, &hdcp_cfg); 262 + mutex_unlock(&mhdp->mbox_mutex); 263 + 264 + return ret; 265 + } 266 + 267 + static int cdns_mhdp_hdcp_set_config(struct cdns_mhdp_device *mhdp, 268 + u8 hdcp_config, bool enable) 269 + { 270 + u16 hdcp_port_status; 271 + u32 ret_event; 272 + u8 hdcp_cfg; 273 + int ret; 274 + 275 + hdcp_cfg = hdcp_config | (enable ? 0x04 : 0) | 276 + (HDCP_CONTENT_TYPE_0 << 3); 277 + cdns_mhdp_hdcp_tx_config(mhdp, hdcp_cfg); 278 + ret_event = cdns_mhdp_wait_for_sw_event(mhdp, CDNS_HDCP_TX_STATUS); 279 + if (!ret_event) 280 + return -1; 281 + 282 + ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status); 283 + if (ret || cdns_mhdp_hdcp_handle_status(mhdp, hdcp_port_status)) 284 + return -1; 285 + 286 + return 0; 287 + } 288 + 289 + static int cdns_mhdp_hdcp_auth_check(struct cdns_mhdp_device *mhdp) 290 + { 291 + u16 hdcp_port_status; 292 + u32 ret_event; 293 + int ret; 294 + 295 + ret_event = cdns_mhdp_wait_for_sw_event(mhdp, CDNS_HDCP_TX_STATUS); 296 + if (!ret_event) 297 + return -1; 298 + 299 + ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status); 300 + if (ret || cdns_mhdp_hdcp_handle_status(mhdp, hdcp_port_status)) 301 + return -1; 302 + 303 + if (hdcp_port_status & 1) { 304 + dev_dbg(mhdp->dev, "Authentication completed successfully!\n"); 305 + return 0; 306 + } 307 + 308 + dev_dbg(mhdp->dev, "Authentication failed\n"); 309 + 310 + return -1; 311 + } 312 + 313 + static int cdns_mhdp_hdcp_check_receviers(struct cdns_mhdp_device *mhdp) 314 + { 315 + u8 hdcp_rec_id[HDCP_MAX_RECEIVERS][HDCP_RECEIVER_ID_SIZE_BYTES]; 316 + u8 hdcp_num_rec; 317 + u32 ret_event; 318 + 319 + ret_event = cdns_mhdp_wait_for_sw_event(mhdp, 320 + CDNS_HDCP_TX_IS_RCVR_ID_VALID); 321 + if (!ret_event) 322 + return -1; 323 + 324 + hdcp_num_rec = 0; 325 + memset(&hdcp_rec_id, 0, sizeof(hdcp_rec_id)); 326 + cdns_mhdp_hdcp_rx_id_valid(mhdp, &hdcp_num_rec, (u8 *)hdcp_rec_id); 327 + cdns_mhdp_hdcp_rx_id_valid_response(mhdp, 1); 328 + 329 + return 0; 330 + } 331 + 332 + static int cdns_mhdp_hdcp_auth_22(struct cdns_mhdp_device *mhdp) 333 + { 334 + u8 resp[HDCP_STATUS_SIZE]; 335 + u16 hdcp_port_status; 336 + u32 ret_event; 337 + int ret; 338 + 339 + dev_dbg(mhdp->dev, "HDCP: Start 2.2 Authentication\n"); 340 + ret_event = cdns_mhdp_wait_for_sw_event(mhdp, 341 + CDNS_HDCP2_TX_IS_KM_STORED); 342 + if (!ret_event) 343 + return -1; 344 + 345 + if (ret_event & CDNS_HDCP_TX_STATUS) { 346 + mhdp->sw_events &= ~CDNS_HDCP_TX_STATUS; 347 + ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status); 348 + if (ret || cdns_mhdp_hdcp_handle_status(mhdp, hdcp_port_status)) 349 + return -1; 350 + } 351 + 352 + cdns_mhdp_hdcp_tx_is_km_stored(mhdp, resp, sizeof(resp)); 353 + cdns_mhdp_hdcp_km_stored_resp(mhdp, 0, NULL); 354 + 355 + if (cdns_mhdp_hdcp_check_receviers(mhdp)) 356 + return -1; 357 + 358 + return 0; 359 + } 360 + 361 + static inline int cdns_mhdp_hdcp_auth_14(struct cdns_mhdp_device *mhdp) 362 + { 363 + dev_dbg(mhdp->dev, "HDCP: Starting 1.4 Authentication\n"); 364 + return cdns_mhdp_hdcp_check_receviers(mhdp); 365 + } 366 + 367 + static int cdns_mhdp_hdcp_auth(struct cdns_mhdp_device *mhdp, 368 + u8 hdcp_config) 369 + { 370 + int ret; 371 + 372 + ret = cdns_mhdp_hdcp_set_config(mhdp, hdcp_config, true); 373 + if (ret) 374 + goto auth_failed; 375 + 376 + if (hdcp_config == HDCP_TX_1) 377 + ret = cdns_mhdp_hdcp_auth_14(mhdp); 378 + else 379 + ret = cdns_mhdp_hdcp_auth_22(mhdp); 380 + 381 + if (ret) 382 + goto auth_failed; 383 + 384 + ret = cdns_mhdp_hdcp_auth_check(mhdp); 385 + if (ret) 386 + ret = cdns_mhdp_hdcp_auth_check(mhdp); 387 + 388 + auth_failed: 389 + return ret; 390 + } 391 + 392 + static int _cdns_mhdp_hdcp_disable(struct cdns_mhdp_device *mhdp) 393 + { 394 + int ret; 395 + 396 + dev_dbg(mhdp->dev, "[%s:%d] HDCP is being disabled...\n", 397 + mhdp->connector.name, mhdp->connector.base.id); 398 + 399 + ret = cdns_mhdp_hdcp_set_config(mhdp, 0, false); 400 + 401 + return ret; 402 + } 403 + 404 + static int _cdns_mhdp_hdcp_enable(struct cdns_mhdp_device *mhdp, u8 content_type) 405 + { 406 + int ret, tries = 3; 407 + u32 i; 408 + 409 + for (i = 0; i < tries; i++) { 410 + if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0 || 411 + content_type == DRM_MODE_HDCP_CONTENT_TYPE1) { 412 + ret = cdns_mhdp_hdcp_auth(mhdp, HDCP_TX_2); 413 + if (!ret) 414 + return 0; 415 + _cdns_mhdp_hdcp_disable(mhdp); 416 + } 417 + 418 + if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0) { 419 + ret = cdns_mhdp_hdcp_auth(mhdp, HDCP_TX_1); 420 + if (!ret) 421 + return 0; 422 + _cdns_mhdp_hdcp_disable(mhdp); 423 + } 424 + } 425 + 426 + dev_err(mhdp->dev, "HDCP authentication failed (%d tries/%d)\n", 427 + tries, ret); 428 + 429 + return ret; 430 + } 431 + 432 + static int cdns_mhdp_hdcp_check_link(struct cdns_mhdp_device *mhdp) 433 + { 434 + u16 hdcp_port_status; 435 + int ret = 0; 436 + 437 + mutex_lock(&mhdp->hdcp.mutex); 438 + if (mhdp->hdcp.value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED) 439 + goto out; 440 + 441 + ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status); 442 + if (!ret && hdcp_port_status & HDCP_PORT_STS_AUTH) 443 + goto out; 444 + 445 + dev_err(mhdp->dev, 446 + "[%s:%d] HDCP link failed, retrying authentication\n", 447 + mhdp->connector.name, mhdp->connector.base.id); 448 + 449 + ret = _cdns_mhdp_hdcp_disable(mhdp); 450 + if (ret) { 451 + mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED; 452 + schedule_work(&mhdp->hdcp.prop_work); 453 + goto out; 454 + } 455 + 456 + ret = _cdns_mhdp_hdcp_enable(mhdp, mhdp->hdcp.hdcp_content_type); 457 + if (ret) { 458 + mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED; 459 + schedule_work(&mhdp->hdcp.prop_work); 460 + } 461 + out: 462 + mutex_unlock(&mhdp->hdcp.mutex); 463 + return ret; 464 + } 465 + 466 + static void cdns_mhdp_hdcp_check_work(struct work_struct *work) 467 + { 468 + struct delayed_work *d_work = to_delayed_work(work); 469 + struct cdns_mhdp_hdcp *hdcp = container_of(d_work, 470 + struct cdns_mhdp_hdcp, 471 + check_work); 472 + struct cdns_mhdp_device *mhdp = container_of(hdcp, 473 + struct cdns_mhdp_device, 474 + hdcp); 475 + 476 + if (!cdns_mhdp_hdcp_check_link(mhdp)) 477 + schedule_delayed_work(&hdcp->check_work, 478 + DRM_HDCP_CHECK_PERIOD_MS); 479 + } 480 + 481 + static void cdns_mhdp_hdcp_prop_work(struct work_struct *work) 482 + { 483 + struct cdns_mhdp_hdcp *hdcp = container_of(work, 484 + struct cdns_mhdp_hdcp, 485 + prop_work); 486 + struct cdns_mhdp_device *mhdp = container_of(hdcp, 487 + struct cdns_mhdp_device, 488 + hdcp); 489 + struct drm_device *dev = mhdp->connector.dev; 490 + struct drm_connector_state *state; 491 + 492 + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); 493 + mutex_lock(&mhdp->hdcp.mutex); 494 + if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { 495 + state = mhdp->connector.state; 496 + state->content_protection = mhdp->hdcp.value; 497 + } 498 + mutex_unlock(&mhdp->hdcp.mutex); 499 + drm_modeset_unlock(&dev->mode_config.connection_mutex); 500 + } 501 + 502 + int cdns_mhdp_hdcp_set_lc(struct cdns_mhdp_device *mhdp, u8 *val) 503 + { 504 + int ret; 505 + 506 + mutex_lock(&mhdp->mbox_mutex); 507 + ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_GENERAL, 508 + HDCP_GENERAL_SET_LC_128, 509 + 16, val); 510 + mutex_unlock(&mhdp->mbox_mutex); 511 + 512 + return ret; 513 + } 514 + 515 + int 516 + cdns_mhdp_hdcp_set_public_key_param(struct cdns_mhdp_device *mhdp, 517 + struct cdns_hdcp_tx_public_key_param *val) 518 + { 519 + int ret; 520 + 521 + mutex_lock(&mhdp->mbox_mutex); 522 + ret = cdns_mhdp_secure_mailbox_send(mhdp, MB_MODULE_ID_HDCP_TX, 523 + HDCP2X_TX_SET_PUBLIC_KEY_PARAMS, 524 + sizeof(*val), (u8 *)val); 525 + mutex_unlock(&mhdp->mbox_mutex); 526 + 527 + return ret; 528 + } 529 + 530 + int cdns_mhdp_hdcp_enable(struct cdns_mhdp_device *mhdp, u8 content_type) 531 + { 532 + int ret; 533 + 534 + mutex_lock(&mhdp->hdcp.mutex); 535 + ret = _cdns_mhdp_hdcp_enable(mhdp, content_type); 536 + if (ret) 537 + goto out; 538 + 539 + mhdp->hdcp.hdcp_content_type = content_type; 540 + mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_ENABLED; 541 + schedule_work(&mhdp->hdcp.prop_work); 542 + schedule_delayed_work(&mhdp->hdcp.check_work, 543 + DRM_HDCP_CHECK_PERIOD_MS); 544 + out: 545 + mutex_unlock(&mhdp->hdcp.mutex); 546 + return ret; 547 + } 548 + 549 + int cdns_mhdp_hdcp_disable(struct cdns_mhdp_device *mhdp) 550 + { 551 + int ret = 0; 552 + 553 + mutex_lock(&mhdp->hdcp.mutex); 554 + if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { 555 + mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_UNDESIRED; 556 + schedule_work(&mhdp->hdcp.prop_work); 557 + ret = _cdns_mhdp_hdcp_disable(mhdp); 558 + } 559 + mutex_unlock(&mhdp->hdcp.mutex); 560 + cancel_delayed_work_sync(&mhdp->hdcp.check_work); 561 + 562 + return ret; 563 + } 564 + 565 + void cdns_mhdp_hdcp_init(struct cdns_mhdp_device *mhdp) 566 + { 567 + INIT_DELAYED_WORK(&mhdp->hdcp.check_work, cdns_mhdp_hdcp_check_work); 568 + INIT_WORK(&mhdp->hdcp.prop_work, cdns_mhdp_hdcp_prop_work); 569 + mutex_init(&mhdp->hdcp.mutex); 570 + }
+92
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Cadence MHDP8546 DP bridge driver. 4 + * 5 + * Copyright (C) 2020 Cadence Design Systems, Inc. 6 + * 7 + */ 8 + 9 + #ifndef CDNS_MHDP8546_HDCP_H 10 + #define CDNS_MHDP8546_HDCP_H 11 + 12 + #include "cdns-mhdp8546-core.h" 13 + 14 + #define HDCP_MAX_RECEIVERS 32 15 + #define HDCP_RECEIVER_ID_SIZE_BYTES 5 16 + #define HDCP_STATUS_SIZE 0x5 17 + #define HDCP_PORT_STS_AUTH 0x1 18 + #define HDCP_PORT_STS_LAST_ERR_SHIFT 0x5 19 + #define HDCP_PORT_STS_LAST_ERR_MASK (0x0F << 5) 20 + #define GET_HDCP_PORT_STS_LAST_ERR(__sts__) \ 21 + (((__sts__) & HDCP_PORT_STS_LAST_ERR_MASK) >> \ 22 + HDCP_PORT_STS_LAST_ERR_SHIFT) 23 + 24 + #define HDCP_CONFIG_1_4 BIT(0) /* use HDCP 1.4 only */ 25 + #define HDCP_CONFIG_2_2 BIT(1) /* use HDCP 2.2 only */ 26 + /* use All HDCP versions */ 27 + #define HDCP_CONFIG_ALL (BIT(0) | BIT(1)) 28 + #define HDCP_CONFIG_NONE 0 29 + 30 + enum { 31 + HDCP_GENERAL_SET_LC_128, 32 + HDCP_SET_SEED, 33 + }; 34 + 35 + enum { 36 + HDCP_TRAN_CONFIGURATION, 37 + HDCP2X_TX_SET_PUBLIC_KEY_PARAMS, 38 + HDCP2X_TX_SET_DEBUG_RANDOM_NUMBERS, 39 + HDCP2X_TX_RESPOND_KM, 40 + HDCP1_TX_SEND_KEYS, 41 + HDCP1_TX_SEND_RANDOM_AN, 42 + HDCP_TRAN_STATUS_CHANGE, 43 + HDCP2X_TX_IS_KM_STORED, 44 + HDCP2X_TX_STORE_KM, 45 + HDCP_TRAN_IS_REC_ID_VALID, 46 + HDCP_TRAN_RESPOND_RECEIVER_ID_VALID, 47 + HDCP_TRAN_TEST_KEYS, 48 + HDCP2X_TX_SET_KM_KEY_PARAMS, 49 + HDCP_NUM_OF_SUPPORTED_MESSAGES 50 + }; 51 + 52 + enum { 53 + HDCP_CONTENT_TYPE_0, 54 + HDCP_CONTENT_TYPE_1, 55 + }; 56 + 57 + #define DRM_HDCP_CHECK_PERIOD_MS (128 * 16) 58 + 59 + #define HDCP_PAIRING_R_ID 5 60 + #define HDCP_PAIRING_M_LEN 16 61 + #define HDCP_KM_LEN 16 62 + #define HDCP_PAIRING_M_EKH 16 63 + 64 + struct cdns_hdcp_pairing_data { 65 + u8 receiver_id[HDCP_PAIRING_R_ID]; 66 + u8 m[HDCP_PAIRING_M_LEN]; 67 + u8 km[HDCP_KM_LEN]; 68 + u8 ekh[HDCP_PAIRING_M_EKH]; 69 + }; 70 + 71 + enum { 72 + HDCP_TX_2, 73 + HDCP_TX_1, 74 + HDCP_TX_BOTH, 75 + }; 76 + 77 + #define DLP_MODULUS_N 384 78 + #define DLP_E 3 79 + 80 + struct cdns_hdcp_tx_public_key_param { 81 + u8 N[DLP_MODULUS_N]; 82 + u8 E[DLP_E]; 83 + }; 84 + 85 + int cdns_mhdp_hdcp_set_public_key_param(struct cdns_mhdp_device *mhdp, 86 + struct cdns_hdcp_tx_public_key_param *val); 87 + int cdns_mhdp_hdcp_set_lc(struct cdns_mhdp_device *mhdp, u8 *val); 88 + int cdns_mhdp_hdcp_enable(struct cdns_mhdp_device *mhdp, u8 content_type); 89 + int cdns_mhdp_hdcp_disable(struct cdns_mhdp_device *mhdp); 90 + void cdns_mhdp_hdcp_init(struct cdns_mhdp_device *mhdp); 91 + 92 + #endif