drivers/gpu/drm/msm/dp/dp_link.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/msm/dp/dp_link.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/msm/dp/dp_link.c
Extension
.c
Size
36284 bytes
Lines
1351
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

struct msm_dp_link_request {
	u32 test_requested;
	u32 test_link_rate;
	u32 test_lane_count;
};

struct msm_dp_link_private {
	u32 prev_sink_count;
	struct drm_device *drm_dev;
	struct drm_dp_aux *aux;
	struct msm_dp_link msm_dp_link;

	struct msm_dp_link_request request;
	struct mutex psm_mutex;
	u8 link_status[DP_LINK_STATUS_SIZE];
};

static int msm_dp_aux_link_power_up(struct drm_dp_aux *aux,
					struct msm_dp_link_info *link)
{
	u8 value;
	ssize_t len;
	int i;

	if (link->revision < 0x11)
		return 0;

	len = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
	if (len < 0)
		return len;

	value &= ~DP_SET_POWER_MASK;
	value |= DP_SET_POWER_D0;

	/* retry for 1ms to give the sink time to wake up */
	for (i = 0; i < 3; i++) {
		len = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
		usleep_range(1000, 2000);
		if (len == 1)
			break;
	}

	return 0;
}

static int msm_dp_aux_link_power_down(struct drm_dp_aux *aux,
					struct msm_dp_link_info *link)
{
	u8 value;
	int err;

	if (link->revision < 0x11)
		return 0;

	err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
	if (err < 0)
		return err;

	value &= ~DP_SET_POWER_MASK;
	value |= DP_SET_POWER_D3;

	err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
	if (err < 0)
		return err;

	return 0;
}

static int msm_dp_link_get_period(struct msm_dp_link_private *link, int const addr)
{
	int ret = 0;
	u8 data;
	u32 const max_audio_period = 0xA;

	/* TEST_AUDIO_PERIOD_CH_XX */
	if (drm_dp_dpcd_readb(link->aux, addr, &data) < 0) {
		DRM_ERROR("failed to read test_audio_period (0x%x)\n", addr);
		ret = -EINVAL;
		goto exit;
	}

	/* Period - Bits 3:0 */
	data = data & 0xF;
	if ((int)data > max_audio_period) {
		DRM_ERROR("invalid test_audio_period_ch_1 = 0x%x\n", data);
		ret = -EINVAL;
		goto exit;
	}

	ret = data;

Annotation

Implementation Notes