drivers/gpu/drm/bridge/th1520-dw-hdmi.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/bridge/th1520-dw-hdmi.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/bridge/th1520-dw-hdmi.c
Extension
.c
Size
5324 bytes
Lines
174
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 th1520_hdmi_phy_params {
	unsigned long mpixelclock;
	u16 opmode_pllcfg;
	u16 pllcurrgmpctrl;
	u16 plldivctrl;
	u16 cksymtxctrl;
	u16 vlevctrl;
	u16 txterm;
};

static const struct th1520_hdmi_phy_params th1520_hdmi_phy_params[] = {
	{ 35500000,  0x0003, 0x0283, 0x0628, 0x8088, 0x01a0, 0x0007 },
	{ 44900000,  0x0003, 0x0285, 0x0228, 0x8088, 0x01a0, 0x0007 },
	{ 71000000,  0x0002, 0x1183, 0x0614, 0x8088, 0x01a0, 0x0007 },
	{ 90000000,  0x0002, 0x1142, 0x0214, 0x8088, 0x01a0, 0x0007 },
	{ 121750000, 0x0001, 0x20c0, 0x060a, 0x8088, 0x01a0, 0x0007 },
	{ 165000000, 0x0001, 0x2080, 0x020a, 0x8088, 0x01a0, 0x0007 },
	{ 198000000, 0x0000, 0x3040, 0x0605, 0x83c8, 0x0120, 0x0004 },
	{ 297000000, 0x0000, 0x3041, 0x0205, 0x81dc, 0x0200, 0x0005 },
	{ 371250000, 0x0640, 0x3041, 0x0205, 0x80f6, 0x0140, 0x0000 },
	{ 495000000, 0x0640, 0x3080, 0x0005, 0x80f6, 0x0140, 0x0000 },
	{ 594000000, 0x0640, 0x3080, 0x0005, 0x80fa, 0x01e0, 0x0004 },
};

struct th1520_hdmi {
	struct dw_hdmi_plat_data plat_data;
	struct dw_hdmi *dw_hdmi;
	struct clk *pixclk;
	struct reset_control *mainrst, *prst;
};

static enum drm_mode_status
th1520_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data,
		       const struct drm_display_info *info,
		       const struct drm_display_mode *mode)
{
	/*
	 * The maximum supported clock frequency is 594 MHz, as shown in the PHY
	 * parameters table.
	 */
	if (mode->clock > 594000)
		return MODE_CLOCK_HIGH;

	return MODE_OK;
}

static void th1520_hdmi_phy_set_params(struct dw_hdmi *hdmi,
				const struct th1520_hdmi_phy_params *params)
{
	dw_hdmi_phy_i2c_write(hdmi, params->opmode_pllcfg,
			      TH1520_HDMI_PHY_OPMODE_PLLCFG);
	dw_hdmi_phy_i2c_write(hdmi, params->pllcurrgmpctrl,
			      TH1520_HDMI_PHY_PLLCURRGMPCTRL);
	dw_hdmi_phy_i2c_write(hdmi, params->plldivctrl,
			      TH1520_HDMI_PHY_PLLDIVCTRL);
	dw_hdmi_phy_i2c_write(hdmi, params->vlevctrl,
			      TH1520_HDMI_PHY_VLEVCTRL);
	dw_hdmi_phy_i2c_write(hdmi, params->cksymtxctrl,
			      TH1520_HDMI_PHY_CKSYMTXCTRL);
	dw_hdmi_phy_i2c_write(hdmi, params->txterm,
			      TH1520_HDMI_PHY_TXTERM);
}

static int th1520_hdmi_phy_configure(struct dw_hdmi *hdmi, void *data,
				     unsigned long mpixelclock)
{
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(th1520_hdmi_phy_params); i++) {
		if (mpixelclock <= th1520_hdmi_phy_params[i].mpixelclock) {
			th1520_hdmi_phy_set_params(hdmi,
						   &th1520_hdmi_phy_params[i]);
			return 0;
		}
	}

	return -EINVAL;
}

static int th1520_dw_hdmi_probe(struct platform_device *pdev)
{
	struct th1520_hdmi *hdmi;
	struct dw_hdmi_plat_data *plat_data;
	struct device *dev = &pdev->dev;

	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
	if (!hdmi)
		return -ENOMEM;

	plat_data = &hdmi->plat_data;

Annotation

Implementation Notes