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

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c
Extension
.c
Size
12843 bytes
Lines
554
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (content_type == DRM_MODE_HDCP_CONTENT_TYPE0) {
			ret = cdns_mhdp_hdcp_auth(mhdp, HDCP_TX_1);
			if (!ret)
				return 0;
			_cdns_mhdp_hdcp_disable(mhdp);
		}
	}

	dev_err(mhdp->dev, "HDCP authentication failed (%d tries/%d)\n",
		tries, ret);

	return ret;
}

static int cdns_mhdp_hdcp_check_link(struct cdns_mhdp_device *mhdp)
{
	u16 hdcp_port_status;
	int ret = 0;

	mutex_lock(&mhdp->hdcp.mutex);

	if (!mhdp->connector)
		goto out;

	if (mhdp->hdcp.value == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
		goto out;

	ret = cdns_mhdp_hdcp_get_status(mhdp, &hdcp_port_status);
	if (!ret && hdcp_port_status & HDCP_PORT_STS_AUTH)
		goto out;

	dev_err(mhdp->dev,
		"[%s:%d] HDCP link failed, retrying authentication\n",
		mhdp->connector->name, mhdp->connector->base.id);

	ret = _cdns_mhdp_hdcp_disable(mhdp);
	if (ret) {
		mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
		schedule_work(&mhdp->hdcp.prop_work);
		goto out;
	}

	ret = _cdns_mhdp_hdcp_enable(mhdp, mhdp->hdcp.hdcp_content_type);
	if (ret) {
		mhdp->hdcp.value = DRM_MODE_CONTENT_PROTECTION_DESIRED;
		schedule_work(&mhdp->hdcp.prop_work);
	}
out:
	mutex_unlock(&mhdp->hdcp.mutex);
	return ret;
}

static void cdns_mhdp_hdcp_check_work(struct work_struct *work)
{
	struct delayed_work *d_work = to_delayed_work(work);
	struct cdns_mhdp_hdcp *hdcp = container_of(d_work,
						   struct cdns_mhdp_hdcp,
						   check_work);
	struct cdns_mhdp_device *mhdp = container_of(hdcp,
						     struct cdns_mhdp_device,
						     hdcp);

	if (!cdns_mhdp_hdcp_check_link(mhdp))
		schedule_delayed_work(&hdcp->check_work,
				      DRM_HDCP_CHECK_PERIOD_MS);
}

static void cdns_mhdp_hdcp_prop_work(struct work_struct *work)
{
	struct cdns_mhdp_hdcp *hdcp = container_of(work,
						   struct cdns_mhdp_hdcp,
						   prop_work);
	struct cdns_mhdp_device *mhdp = container_of(hdcp,
						     struct cdns_mhdp_device,
						     hdcp);
	struct drm_device *dev = NULL;
	struct drm_connector_state *state;

	if (mhdp->connector)
		dev = mhdp->connector->dev;

	if (!dev)
		return;

	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
	mutex_lock(&mhdp->hdcp.mutex);
	if (mhdp->hdcp.value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
		state = mhdp->connector->state;
		state->content_protection = mhdp->hdcp.value;
	}

Annotation

Implementation Notes