Skip to content

Commit 6a3608e

Browse files
pthombarcdnsrobertfoss
authored andcommitted
drm: bridge: cdns-mhdp8546: Enable HDCP
This patch enable HDCP in MHDP driver. Signed-off-by: Parshuram Thombare <[email protected]> Reviewed-by: Robert Foss <[email protected]> Signed-off-by: Robert Foss <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 7169d08 commit 6a3608e

File tree

5 files changed

+801
-13
lines changed

5 files changed

+801
-13
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
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
44
cdns-mhdp8546-$(CONFIG_DRM_CDNS_MHDP8546_J721E) += cdns-mhdp8546-j721e.o

drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c

Lines changed: 116 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,15 @@
4242
#include <drm/drm_connector.h>
4343
#include <drm/drm_crtc_helper.h>
4444
#include <drm/drm_dp_helper.h>
45+
#include <drm/drm_hdcp.h>
4546
#include <drm/drm_modeset_helper_vtables.h>
4647
#include <drm/drm_print.h>
4748
#include <drm/drm_probe_helper.h>
4849

4950
#include <asm/unaligned.h>
5051

5152
#include "cdns-mhdp8546-core.h"
52-
53+
#include "cdns-mhdp8546-hdcp.h"
5354
#include "cdns-mhdp8546-j721e.h"
5455

5556
static int cdns_mhdp_mailbox_read(struct cdns_mhdp_device *mhdp)
@@ -1614,10 +1615,51 @@ enum drm_mode_status cdns_mhdp_mode_valid(struct drm_connector *conn,
16141615
return MODE_OK;
16151616
}
16161617

1618+
static int cdns_mhdp_connector_atomic_check(struct drm_connector *conn,
1619+
struct drm_atomic_state *state)
1620+
{
1621+
struct cdns_mhdp_device *mhdp = connector_to_mhdp(conn);
1622+
struct drm_connector_state *old_state, *new_state;
1623+
struct drm_crtc_state *crtc_state;
1624+
u64 old_cp, new_cp;
1625+
1626+
if (!mhdp->hdcp_supported)
1627+
return 0;
1628+
1629+
old_state = drm_atomic_get_old_connector_state(state, conn);
1630+
new_state = drm_atomic_get_new_connector_state(state, conn);
1631+
old_cp = old_state->content_protection;
1632+
new_cp = new_state->content_protection;
1633+
1634+
if (old_state->hdcp_content_type != new_state->hdcp_content_type &&
1635+
new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
1636+
new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
1637+
goto mode_changed;
1638+
}
1639+
1640+
if (!new_state->crtc) {
1641+
if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)
1642+
new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
1643+
return 0;
1644+
}
1645+
1646+
if (old_cp == new_cp ||
1647+
(old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
1648+
new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED))
1649+
return 0;
1650+
1651+
mode_changed:
1652+
crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc);
1653+
crtc_state->mode_changed = true;
1654+
1655+
return 0;
1656+
}
1657+
16171658
static const struct drm_connector_helper_funcs cdns_mhdp_conn_helper_funcs = {
16181659
.detect_ctx = cdns_mhdp_connector_detect,
16191660
.get_modes = cdns_mhdp_get_modes,
16201661
.mode_valid = cdns_mhdp_mode_valid,
1662+
.atomic_check = cdns_mhdp_connector_atomic_check,
16211663
};
16221664

16231665
static const struct drm_connector_funcs cdns_mhdp_conn_funcs = {
@@ -1662,7 +1704,10 @@ static int cdns_mhdp_connector_init(struct cdns_mhdp_device *mhdp)
16621704
return ret;
16631705
}
16641706

1665-
return 0;
1707+
if (mhdp->hdcp_supported)
1708+
ret = drm_connector_attach_content_protection_property(conn, true);
1709+
1710+
return ret;
16661711
}
16671712

16681713
static int cdns_mhdp_attach(struct drm_bridge *bridge,
@@ -1957,6 +2002,15 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
19572002
if (WARN_ON(!conn_state))
19582003
goto out;
19592004

2005+
if (mhdp->hdcp_supported &&
2006+
mhdp->hw_state == MHDP_HW_READY &&
2007+
conn_state->content_protection ==
2008+
DRM_MODE_CONTENT_PROTECTION_DESIRED) {
2009+
mutex_unlock(&mhdp->link_mutex);
2010+
cdns_mhdp_hdcp_enable(mhdp, conn_state->hdcp_content_type);
2011+
mutex_lock(&mhdp->link_mutex);
2012+
}
2013+
19602014
crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
19612015
if (WARN_ON(!crtc_state))
19622016
goto out;
@@ -2000,6 +2054,9 @@ static void cdns_mhdp_atomic_disable(struct drm_bridge *bridge,
20002054

20012055
mutex_lock(&mhdp->link_mutex);
20022056

2057+
if (mhdp->hdcp_supported)
2058+
cdns_mhdp_hdcp_disable(mhdp);
2059+
20032060
mhdp->bridge_enabled = false;
20042061
cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp);
20052062
resp &= ~CDNS_DP_FRAMER_EN;
@@ -2288,7 +2345,6 @@ static irqreturn_t cdns_mhdp_irq_handler(int irq, void *data)
22882345
struct cdns_mhdp_device *mhdp = data;
22892346
u32 apb_stat, sw_ev0;
22902347
bool bridge_attached;
2291-
int ret;
22922348

22932349
apb_stat = readl(mhdp->regs + CDNS_APB_INT_STATUS);
22942350
if (!(apb_stat & CDNS_APB_INT_MASK_SW_EVENT_INT))
@@ -2307,20 +2363,54 @@ static irqreturn_t cdns_mhdp_irq_handler(int irq, void *data)
23072363
spin_unlock(&mhdp->start_lock);
23082364

23092365
if (bridge_attached && (sw_ev0 & CDNS_DPTX_HPD)) {
2310-
ret = cdns_mhdp_update_link_status(mhdp);
2311-
if (mhdp->connector.dev) {
2312-
if (ret < 0)
2313-
schedule_work(&mhdp->modeset_retry_work);
2314-
else
2315-
drm_kms_helper_hotplug_event(mhdp->bridge.dev);
2316-
} else {
2317-
drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp));
2318-
}
2366+
schedule_work(&mhdp->hpd_work);
2367+
}
2368+
2369+
if (sw_ev0 & ~CDNS_DPTX_HPD) {
2370+
mhdp->sw_events |= (sw_ev0 & ~CDNS_DPTX_HPD);
2371+
wake_up(&mhdp->sw_events_wq);
23192372
}
23202373

23212374
return IRQ_HANDLED;
23222375
}
23232376

2377+
u32 cdns_mhdp_wait_for_sw_event(struct cdns_mhdp_device *mhdp, u32 event)
2378+
{
2379+
u32 ret;
2380+
2381+
ret = wait_event_timeout(mhdp->sw_events_wq,
2382+
mhdp->sw_events & event,
2383+
msecs_to_jiffies(500));
2384+
if (!ret) {
2385+
dev_dbg(mhdp->dev, "SW event 0x%x timeout\n", event);
2386+
goto sw_event_out;
2387+
}
2388+
2389+
ret = mhdp->sw_events;
2390+
mhdp->sw_events &= ~event;
2391+
2392+
sw_event_out:
2393+
return ret;
2394+
}
2395+
2396+
static void cdns_mhdp_hpd_work(struct work_struct *work)
2397+
{
2398+
struct cdns_mhdp_device *mhdp = container_of(work,
2399+
struct cdns_mhdp_device,
2400+
hpd_work);
2401+
int ret;
2402+
2403+
ret = cdns_mhdp_update_link_status(mhdp);
2404+
if (mhdp->connector.dev) {
2405+
if (ret < 0)
2406+
schedule_work(&mhdp->modeset_retry_work);
2407+
else
2408+
drm_kms_helper_hotplug_event(mhdp->bridge.dev);
2409+
} else {
2410+
drm_bridge_hpd_notify(&mhdp->bridge, cdns_mhdp_detect(mhdp));
2411+
}
2412+
}
2413+
23242414
static int cdns_mhdp_probe(struct platform_device *pdev)
23252415
{
23262416
struct device *dev = &pdev->dev;
@@ -2356,6 +2446,15 @@ static int cdns_mhdp_probe(struct platform_device *pdev)
23562446
return PTR_ERR(mhdp->regs);
23572447
}
23582448

2449+
mhdp->sapb_regs = devm_platform_ioremap_resource_byname(pdev, "mhdptx-sapb");
2450+
if (IS_ERR(mhdp->sapb_regs)) {
2451+
mhdp->hdcp_supported = false;
2452+
dev_warn(dev,
2453+
"Failed to get SAPB memory resource, HDCP not supported\n");
2454+
} else {
2455+
mhdp->hdcp_supported = true;
2456+
}
2457+
23592458
mhdp->phy = devm_of_phy_get_by_index(dev, pdev->dev.of_node, 0);
23602459
if (IS_ERR(mhdp->phy)) {
23612460
dev_err(dev, "no PHY configured\n");
@@ -2430,13 +2529,18 @@ static int cdns_mhdp_probe(struct platform_device *pdev)
24302529

24312530
/* Initialize the work for modeset in case of link train failure */
24322531
INIT_WORK(&mhdp->modeset_retry_work, cdns_mhdp_modeset_retry_fn);
2532+
INIT_WORK(&mhdp->hpd_work, cdns_mhdp_hpd_work);
24332533

24342534
init_waitqueue_head(&mhdp->fw_load_wq);
2535+
init_waitqueue_head(&mhdp->sw_events_wq);
24352536

24362537
ret = cdns_mhdp_load_firmware(mhdp);
24372538
if (ret)
24382539
goto phy_exit;
24392540

2541+
if (mhdp->hdcp_supported)
2542+
cdns_mhdp_hdcp_init(mhdp);
2543+
24402544
drm_bridge_add(&mhdp->bridge);
24412545

24422546
return 0;

drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ struct phy;
4747

4848
#define CDNS_SW_EVENT0 0x00044
4949
#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)
5054

5155
#define CDNS_SW_EVENT1 0x00048
5256
#define CDNS_SW_EVENT2 0x0004c
@@ -339,8 +343,17 @@ struct cdns_mhdp_platform_info {
339343
#define to_cdns_mhdp_bridge_state(s) \
340344
container_of(s, struct cdns_mhdp_bridge_state, base)
341345

346+
struct cdns_mhdp_hdcp {
347+
struct delayed_work check_work;
348+
struct work_struct prop_work;
349+
struct mutex mutex; /* mutex to protect hdcp.value */
350+
u32 value;
351+
u8 hdcp_content_type;
352+
};
353+
342354
struct cdns_mhdp_device {
343355
void __iomem *regs;
356+
void __iomem *sapb_regs;
344357
void __iomem *j721e_regs;
345358

346359
struct device *dev;
@@ -392,9 +405,18 @@ struct cdns_mhdp_device {
392405

393406
/* Work struct to schedule a uevent on link train failure */
394407
struct work_struct modeset_retry_work;
408+
struct work_struct hpd_work;
409+
410+
wait_queue_head_t sw_events_wq;
411+
u32 sw_events;
412+
413+
struct cdns_mhdp_hdcp hdcp;
414+
bool hdcp_supported;
395415
};
396416

397417
#define connector_to_mhdp(x) container_of(x, struct cdns_mhdp_device, connector)
398418
#define bridge_to_mhdp(x) container_of(x, struct cdns_mhdp_device, bridge)
399419

420+
u32 cdns_mhdp_wait_for_sw_event(struct cdns_mhdp_device *mhdp, uint32_t event);
421+
400422
#endif

0 commit comments

Comments
 (0)