drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
Extension
.c
Size
23435 bytes
Lines
749
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 (IS_ERR(hdmi->reset)) {
			dev_err(dev, "Couldn't get the HDMI reset control\n");
			return PTR_ERR(hdmi->reset);
		}

		ret = reset_control_deassert(hdmi->reset);
		if (ret) {
			dev_err(dev, "Couldn't deassert HDMI reset\n");
			return ret;
		}
	}

	hdmi->bus_clk = devm_clk_get(dev, "ahb");
	if (IS_ERR(hdmi->bus_clk)) {
		dev_err(dev, "Couldn't get the HDMI bus clock\n");
		ret = PTR_ERR(hdmi->bus_clk);
		goto err_assert_reset;
	}
	clk_prepare_enable(hdmi->bus_clk);

	hdmi->mod_clk = devm_clk_get(dev, "mod");
	if (IS_ERR(hdmi->mod_clk)) {
		dev_err(dev, "Couldn't get the HDMI mod clock\n");
		ret = PTR_ERR(hdmi->mod_clk);
		goto err_disable_bus_clk;
	}
	clk_prepare_enable(hdmi->mod_clk);

	hdmi->pll0_clk = devm_clk_get(dev, "pll-0");
	if (IS_ERR(hdmi->pll0_clk)) {
		dev_err(dev, "Couldn't get the HDMI PLL 0 clock\n");
		ret = PTR_ERR(hdmi->pll0_clk);
		goto err_disable_mod_clk;
	}

	hdmi->pll1_clk = devm_clk_get(dev, "pll-1");
	if (IS_ERR(hdmi->pll1_clk)) {
		dev_err(dev, "Couldn't get the HDMI PLL 1 clock\n");
		ret = PTR_ERR(hdmi->pll1_clk);
		goto err_disable_mod_clk;
	}

	hdmi->regmap = devm_regmap_init_mmio(dev, hdmi->base,
					     &sun4i_hdmi_regmap_config);
	if (IS_ERR(hdmi->regmap)) {
		dev_err(dev, "Couldn't create HDMI encoder regmap\n");
		ret = PTR_ERR(hdmi->regmap);
		goto err_disable_mod_clk;
	}

	ret = sun4i_tmds_create(hdmi);
	if (ret) {
		dev_err(dev, "Couldn't create the TMDS clock\n");
		goto err_disable_mod_clk;
	}

	if (hdmi->variant->has_ddc_parent_clk) {
		hdmi->ddc_parent_clk = devm_clk_get(dev, "ddc");
		if (IS_ERR(hdmi->ddc_parent_clk)) {
			dev_err(dev, "Couldn't get the HDMI DDC clock\n");
			ret = PTR_ERR(hdmi->ddc_parent_clk);
			goto err_disable_mod_clk;
		}
	} else {
		hdmi->ddc_parent_clk = hdmi->tmds_clk;
	}

	writel(SUN4I_HDMI_CTRL_ENABLE, hdmi->base + SUN4I_HDMI_CTRL_REG);

	writel(hdmi->variant->pad_ctrl0_init_val,
	       hdmi->base + SUN4I_HDMI_PAD_CTRL0_REG);

	reg = readl(hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);
	reg &= SUN4I_HDMI_PLL_CTRL_DIV_MASK;
	reg |= hdmi->variant->pll_ctrl_init_val;
	writel(reg, hdmi->base + SUN4I_HDMI_PLL_CTRL_REG);

	ret = sun4i_hdmi_i2c_create(dev, hdmi);
	if (ret) {
		dev_err(dev, "Couldn't create the HDMI I2C adapter\n");
		goto err_disable_mod_clk;
	}

	hdmi->ddc_i2c = sun4i_hdmi_get_ddc(dev);
	if (IS_ERR(hdmi->ddc_i2c)) {
		ret = PTR_ERR(hdmi->ddc_i2c);
		if (ret == -ENODEV)
			hdmi->ddc_i2c = NULL;
		else
			goto err_del_i2c_adapter;

Annotation

Implementation Notes