drivers/gpu/drm/imx/dcss/dcss-ctxld.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/imx/dcss/dcss-ctxld.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/imx/dcss/dcss-ctxld.c
Extension
.c
Size
10135 bytes
Lines
417
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 dcss_ctxld_item {
	u32 val;
	u32 ofs;
};

#define CTX_ITEM_SIZE			sizeof(struct dcss_ctxld_item)

struct dcss_ctxld {
	struct device *dev;
	void __iomem *ctxld_reg;
	int irq;
	bool irq_en;

	struct dcss_ctxld_item *db[2];
	struct dcss_ctxld_item *sb_hp[2];
	struct dcss_ctxld_item *sb_lp[2];

	dma_addr_t db_paddr[2];
	dma_addr_t sb_paddr[2];

	u16 ctx_size[2][3]; /* holds the sizes of DB, SB_HP and SB_LP ctx */
	u8 current_ctx;

	bool in_use;
	bool armed;

	spinlock_t lock; /* protects concurent access to private data */
};

static irqreturn_t dcss_ctxld_irq_handler(int irq, void *data)
{
	struct dcss_ctxld *ctxld = data;
	struct dcss_dev *dcss = dcss_drv_dev_to_dcss(ctxld->dev);
	u32 irq_status;

	irq_status = dcss_readl(ctxld->ctxld_reg + DCSS_CTXLD_CONTROL_STATUS);

	if (irq_status & CTXLD_IRQ_COMPLETION &&
	    !(irq_status & CTXLD_ENABLE) && ctxld->in_use) {
		ctxld->in_use = false;

		if (dcss && dcss->disable_callback)
			dcss->disable_callback(dcss);
	} else if (irq_status & CTXLD_IRQ_ERROR) {
		/*
		 * Except for throwing an error message and clearing the status
		 * register, there's not much we can do here.
		 */
		dev_err(ctxld->dev, "ctxld: error encountered: %08x\n",
			irq_status);
		dev_err(ctxld->dev, "ctxld: db=%d, sb_hp=%d, sb_lp=%d\n",
			ctxld->ctx_size[ctxld->current_ctx ^ 1][CTX_DB],
			ctxld->ctx_size[ctxld->current_ctx ^ 1][CTX_SB_HP],
			ctxld->ctx_size[ctxld->current_ctx ^ 1][CTX_SB_LP]);
	}

	dcss_clr(irq_status & (CTXLD_IRQ_ERROR | CTXLD_IRQ_COMPLETION),
		 ctxld->ctxld_reg + DCSS_CTXLD_CONTROL_STATUS);

	return IRQ_HANDLED;
}

static int dcss_ctxld_irq_config(struct dcss_ctxld *ctxld,
				 struct platform_device *pdev)
{
	int ret;

	ctxld->irq = platform_get_irq_byname(pdev, "ctxld");
	if (ctxld->irq < 0)
		return ctxld->irq;

	ret = request_irq(ctxld->irq, dcss_ctxld_irq_handler,
			  0, "dcss_ctxld", ctxld);
	if (ret) {
		dev_err(ctxld->dev, "ctxld: irq request failed.\n");
		return ret;
	}

	ctxld->irq_en = true;

	return 0;
}

static void dcss_ctxld_hw_cfg(struct dcss_ctxld *ctxld)
{
	dcss_writel(RD_ERR_EN | SB_HP_COMP_EN |
		    DB_PEND_SB_REC_EN | AHB_ERR_EN | RD_ERR | AHB_ERR,
		    ctxld->ctxld_reg + DCSS_CTXLD_CONTROL_STATUS);
}

Annotation

Implementation Notes