drivers/gpu/drm/mxsfb/mxsfb_drv.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/mxsfb/mxsfb_drv.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/mxsfb/mxsfb_drv.c
Extension
.c
Size
10490 bytes
Lines
436
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 (mxsfb->crc_active) {
			crc = readl(mxsfb->base + LCDC_V4_CRC_STAT);
			vbc = drm_crtc_accurate_vblank_count(&mxsfb->crtc);
			drm_crtc_add_crc_entry(&mxsfb->crtc, true, vbc, &crc);
		}
	}

	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);

	return IRQ_HANDLED;
}

static void mxsfb_irq_disable(struct drm_device *drm)
{
	struct mxsfb_drm_private *mxsfb = drm->dev_private;

	mxsfb_enable_axi_clk(mxsfb);

	/* Disable and clear VBLANK IRQ */
	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);

	mxsfb_disable_axi_clk(mxsfb);
}

static int mxsfb_irq_install(struct drm_device *dev, int irq)
{
	if (irq == IRQ_NOTCONNECTED)
		return -ENOTCONN;

	mxsfb_irq_disable(dev);

	return request_irq(irq, mxsfb_irq_handler, 0,  dev->driver->name, dev);
}

static void mxsfb_irq_uninstall(struct drm_device *dev)
{
	struct mxsfb_drm_private *mxsfb = dev->dev_private;

	mxsfb_irq_disable(dev);
	free_irq(mxsfb->irq, dev);
}

static int mxsfb_load(struct drm_device *drm,
		      const struct mxsfb_devdata *devdata)
{
	struct platform_device *pdev = to_platform_device(drm->dev);
	struct mxsfb_drm_private *mxsfb;
	int ret;

	mxsfb = devm_kzalloc(&pdev->dev, sizeof(*mxsfb), GFP_KERNEL);
	if (!mxsfb)
		return -ENOMEM;

	mxsfb->drm = drm;
	drm->dev_private = mxsfb;
	mxsfb->devdata = devdata;

	mxsfb->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(mxsfb->base))
		return PTR_ERR(mxsfb->base);

	mxsfb->clk = devm_clk_get(drm->dev, NULL);
	if (IS_ERR(mxsfb->clk))
		return PTR_ERR(mxsfb->clk);

	mxsfb->clk_axi = devm_clk_get_optional(drm->dev, "axi");
	if (IS_ERR(mxsfb->clk_axi))
		return PTR_ERR(mxsfb->clk_axi);

	mxsfb->clk_disp_axi = devm_clk_get(drm->dev, "disp_axi");
	if (IS_ERR(mxsfb->clk_disp_axi))
		mxsfb->clk_disp_axi = NULL;

	ret = dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32));
	if (ret)
		return ret;

	pm_runtime_enable(drm->dev);

	/* Modeset init */
	ret = drmm_mode_config_init(drm);
	if (ret) {
		dev_err(drm->dev, "Failed to initialize mode config\n");
		goto err_vblank;
	}

	ret = mxsfb_kms_init(mxsfb);
	if (ret < 0) {
		dev_err(drm->dev, "Failed to initialize KMS pipeline\n");

Annotation

Implementation Notes