drivers/media/platform/chips-media/wave5/wave5-vpu.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/chips-media/wave5/wave5-vpu.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/chips-media/wave5/wave5-vpu.c
Extension
.c
Size
12799 bytes
Lines
485
Domain
Driver Families
Bucket
drivers/media
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 wave5_match_data {
	int flags;
	const char *fw_name;
	u32 sram_size;
};

static int vpu_poll_interval = 5;
module_param(vpu_poll_interval, int, 0644);

int wave5_vpu_wait_interrupt(struct vpu_instance *inst, unsigned int timeout)
{
	int ret;

	ret = wait_for_completion_timeout(&inst->irq_done,
					  msecs_to_jiffies(timeout));
	if (!ret)
		return -ETIMEDOUT;

	reinit_completion(&inst->irq_done);

	return 0;
}

static void wave5_vpu_handle_irq(void *dev_id)
{
	u32 seq_done;
	u32 cmd_done;
	u32 irq_reason;
	u32 irq_subreason;
	struct vpu_instance *inst, *tmp;
	struct vpu_device *dev = dev_id;
	int val;
	unsigned long flags;

	irq_reason = wave5_vdi_read_register(dev, W5_VPU_VINT_REASON);
	seq_done = wave5_vdi_read_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO);
	cmd_done = wave5_vdi_read_register(dev, W5_RET_QUEUE_CMD_DONE_INST);
	wave5_vdi_write_register(dev, W5_VPU_VINT_REASON_CLR, irq_reason);
	wave5_vdi_write_register(dev, W5_VPU_VINT_CLEAR, 0x1);

	spin_lock_irqsave(&dev->irq_spinlock, flags);
	list_for_each_entry_safe(inst, tmp, &dev->instances, list) {

		if (irq_reason & BIT(INT_WAVE5_INIT_SEQ) ||
		    irq_reason & BIT(INT_WAVE5_ENC_SET_PARAM)) {
			if (dev->product_code == WAVE515_CODE &&
			    (cmd_done & BIT(inst->id))) {
				cmd_done &= ~BIT(inst->id);
				wave5_vdi_write_register(dev, W5_RET_QUEUE_CMD_DONE_INST,
							 cmd_done);
				complete(&inst->irq_done);
			} else if (seq_done & BIT(inst->id)) {
				seq_done &= ~BIT(inst->id);
				wave5_vdi_write_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO,
							 seq_done);
				complete(&inst->irq_done);
			}
		}

		if (irq_reason & BIT(INT_WAVE5_DEC_PIC) ||
		    irq_reason & BIT(INT_WAVE5_ENC_PIC)) {
			if (cmd_done & BIT(inst->id)) {
				cmd_done &= ~BIT(inst->id);
				if (dev->irq >= 0) {
					irq_subreason =
						wave5_vdi_read_register(dev, W5_VPU_VINT_REASON);
					if (!(irq_subreason & BIT(INT_WAVE5_DEC_PIC)))
						wave5_vdi_write_register(dev,
									 W5_RET_QUEUE_CMD_DONE_INST,
									 cmd_done);
				}
				val = BIT(INT_WAVE5_DEC_PIC);
				kfifo_in(&inst->irq_status, &val, sizeof(int));
			}
		}
	}
	spin_unlock_irqrestore(&dev->irq_spinlock, flags);

	if (dev->irq < 0)
		up(&dev->irq_sem);
}

static irqreturn_t wave5_vpu_irq(int irq, void *dev_id)
{
	struct vpu_device *dev = dev_id;

	if (wave5_vdi_read_register(dev, W5_VPU_VPU_INT_STS)) {
		wave5_vpu_handle_irq(dev);
		return IRQ_WAKE_THREAD;
	}

Annotation

Implementation Notes