drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c
Extension
.c
Size
11049 bytes
Lines
342
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 (ret) {
			drm_err(dp->drm_dev, "dp link training failed, ret: %d\n", ret);
			return ret;
		}
	}

	hibmc_dp_display_en(dp, false);
	hibmc_dp_link_cfg(dp_dev, mode);

	return 0;
}

void hibmc_dp_reset_link(struct hibmc_dp *dp)
{
	dp->dp_dev->link.status.clock_recovered = false;
	dp->dp_dev->link.status.channel_equalized = false;
}

u8 hibmc_dp_get_link_rate(struct hibmc_dp *dp)
{
	return dp->dp_dev->link.cap.link_rate;
}

u8 hibmc_dp_get_lanes(struct hibmc_dp *dp)
{
	return dp->dp_dev->link.cap.lanes;
}

static const struct hibmc_dp_color_raw g_rgb_raw[] = {
	{CBAR_COLOR_BAR, 0x000, 0x000, 0x000},
	{CBAR_WHITE,     0xfff, 0xfff, 0xfff},
	{CBAR_RED,       0xfff, 0x000, 0x000},
	{CBAR_ORANGE,    0xfff, 0x800, 0x000},
	{CBAR_YELLOW,    0xfff, 0xfff, 0x000},
	{CBAR_GREEN,     0x000, 0xfff, 0x000},
	{CBAR_CYAN,      0x000, 0x800, 0x800},
	{CBAR_BLUE,      0x000, 0x000, 0xfff},
	{CBAR_PURPLE,    0x800, 0x000, 0x800},
	{CBAR_BLACK,     0x000, 0x000, 0x000},
};

void hibmc_dp_set_cbar(struct hibmc_dp *dp, const struct hibmc_dp_cbar_cfg *cfg)
{
	struct hibmc_dp_dev *dp_dev = dp->dp_dev;
	struct hibmc_dp_color_raw raw_data;

	if (cfg->enable) {
		hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL, BIT(9),
					 cfg->self_timing);
		hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL, GENMASK(8, 1),
					 cfg->dynamic_rate);
		if (cfg->pattern == CBAR_COLOR_BAR) {
			hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL, BIT(10), 0);
		} else {
			raw_data = g_rgb_raw[cfg->pattern];
			drm_dbg_dp(dp->drm_dev, "r:%x g:%x b:%x\n", raw_data.r_value,
				   raw_data.g_value, raw_data.b_value);
			hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL, BIT(10), 1);
			hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL, GENMASK(23, 12),
						 raw_data.r_value);
			hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL1, GENMASK(23, 12),
						 raw_data.g_value);
			hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL1, GENMASK(11, 0),
						 raw_data.b_value);
		}
	}

	hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL, BIT(0), cfg->enable);
	writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL);
}

bool hibmc_dp_check_hpd_status(struct hibmc_dp *dp, int exp_status)
{
	u32 status;
	int ret;

	ret = readl_poll_timeout(dp->dp_dev->base + HIBMC_DP_HPD_STATUS, status,
				 FIELD_GET(HIBMC_DP_HPD_CUR_STATE, status) == exp_status,
				 1000, 100000); /* DP spec says 100ms */
	if (ret) {
		drm_dbg_dp(dp->drm_dev, "wait hpd status timeout");
		return false;
	}

	dp->dp_dev->hpd_status = exp_status;

	return true;
}

Annotation

Implementation Notes