drivers/media/platform/mediatek/vpu/mtk_vpu.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/mediatek/vpu/mtk_vpu.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/mediatek/vpu/mtk_vpu.c
Extension
.c
Size
26475 bytes
Lines
1056
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations vpu_debug_fops = {
	.open = simple_open,
	.read = vpu_debug_read,
};
#endif /* CONFIG_DEBUG_FS */

static void vpu_free_ext_mem(struct mtk_vpu *vpu, u8 fw_type)
{
	struct device *dev = vpu->dev;
	size_t fw_ext_size = fw_type ? VPU_EXT_D_SIZE : VPU_EXT_P_SIZE;

	dma_free_coherent(dev, fw_ext_size, vpu->extmem[fw_type].va,
			  vpu->extmem[fw_type].pa);
}

static int vpu_alloc_ext_mem(struct mtk_vpu *vpu, u32 fw_type)
{
	struct device *dev = vpu->dev;
	size_t fw_ext_size = fw_type ? VPU_EXT_D_SIZE : VPU_EXT_P_SIZE;
	u32 vpu_ext_mem0 = fw_type ? VPU_DMEM_EXT0_ADDR : VPU_PMEM_EXT0_ADDR;
	u32 vpu_ext_mem1 = fw_type ? VPU_DMEM_EXT1_ADDR : VPU_PMEM_EXT1_ADDR;
	u32 offset_4gb = vpu->enable_4GB ? 0x40000000 : 0;

	vpu->extmem[fw_type].va = dma_alloc_coherent(dev,
					       fw_ext_size,
					       &vpu->extmem[fw_type].pa,
					       GFP_KERNEL);
	if (!vpu->extmem[fw_type].va) {
		dev_err(dev, "Failed to allocate the extended program memory\n");
		return -ENOMEM;
	}

	/* Disable extend0. Enable extend1 */
	vpu_cfg_writel(vpu, 0x1, vpu_ext_mem0);
	vpu_cfg_writel(vpu, (vpu->extmem[fw_type].pa & 0xFFFFF000) + offset_4gb,
		       vpu_ext_mem1);

	dev_info(dev, "%s extend memory phy=0x%llx virt=0x%p\n",
		 fw_type ? "Data" : "Program",
		 (unsigned long long)vpu->extmem[fw_type].pa,
		 vpu->extmem[fw_type].va);

	return 0;
}

static void vpu_ipi_handler(struct mtk_vpu *vpu)
{
	struct share_obj __iomem *rcv_obj = vpu->recv_buf;
	struct vpu_ipi_desc *ipi_desc = vpu->ipi_desc;
	unsigned char data[SHARE_BUF_SIZE];
	s32 id = readl(&rcv_obj->id);

	memcpy_fromio(data, rcv_obj->share_buf, sizeof(data));
	if (id < IPI_MAX && ipi_desc[id].handler) {
		ipi_desc[id].handler(data, readl(&rcv_obj->len),
				     ipi_desc[id].priv);
		if (id > IPI_VPU_INIT) {
			vpu->ipi_id_ack[id] = true;
			wake_up(&vpu->ack_wq);
		}
	} else {
		dev_err(vpu->dev, "No such ipi id = %d\n", id);
	}
}

static int vpu_ipi_init(struct mtk_vpu *vpu)
{
	/* Disable VPU to host interrupt */
	vpu_cfg_writel(vpu, 0x0, VPU_TO_HOST);

	/* shared buffer initialization */
	vpu->recv_buf = vpu->reg.tcm + VPU_DTCM_OFFSET;
	vpu->send_buf = vpu->recv_buf + 1;
	memset_io(vpu->recv_buf, 0, sizeof(struct share_obj));
	memset_io(vpu->send_buf, 0, sizeof(struct share_obj));

	return 0;
}

static irqreturn_t vpu_irq_handler(int irq, void *priv)
{
	struct mtk_vpu *vpu = priv;
	u32 vpu_to_host;
	int ret;

	/*
	 * Clock should have been enabled already.
	 * Enable again in case vpu_ipi_send times out
	 * and has disabled the clock.
	 */

Annotation

Implementation Notes