drivers/media/pci/tw686x/tw686x-video.c

Source file repositories/reference/linux-study-clean/drivers/media/pci/tw686x/tw686x-video.c

File Facts

System
Linux kernel
Corpus path
drivers/media/pci/tw686x/tw686x-video.c
Extension
.c
Size
33565 bytes
Lines
1308
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

while (len && buf_len) {

			if (count == TW686X_MAX_SG_DESC_COUNT)
				return -ENOMEM;

			entry_len = min_t(unsigned int, len,
					  TW686X_MAX_SG_ENTRY_SIZE);
			entry_len = min_t(unsigned int, entry_len, buf_len);
			descs[count].phys = cpu_to_le32(phys);
			descs[count++].flags_length =
					cpu_to_le32(BIT(30) | entry_len);
			phys += entry_len;
			len -= entry_len;
			buf_len -= entry_len;
		}

		if (!buf_len)
			return 0;
	}

	return -ENOMEM;
}

static void tw686x_sg_buf_refill(struct tw686x_video_channel *vc,
				 unsigned int pb)
{
	struct tw686x_dev *dev = vc->dev;
	struct tw686x_v4l2_buf *buf;

	while (!list_empty(&vc->vidq_queued)) {
		unsigned int buf_len;

		buf = list_first_entry(&vc->vidq_queued,
			struct tw686x_v4l2_buf, list);
		list_del(&buf->list);

		buf_len = (vc->width * vc->height * vc->format->depth) >> 3;
		if (tw686x_sg_desc_fill(vc->sg_descs[pb], buf, buf_len)) {
			v4l2_err(&dev->v4l2_dev,
				 "dma%d: unable to fill %s-buffer\n",
				 vc->ch, pb ? "B" : "P");
			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
			continue;
		}

		buf->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
		vc->curr_bufs[pb] = buf;
		return;
	}

	vc->curr_bufs[pb] = NULL;
}

static void tw686x_sg_dma_free(struct tw686x_video_channel *vc,
			       unsigned int pb)
{
	struct tw686x_dma_desc *desc = &vc->dma_descs[pb];
	struct tw686x_dev *dev = vc->dev;

	if (desc->size) {
		dma_free_coherent(&dev->pci_dev->dev, desc->size, desc->virt,
				  desc->phys);
		desc->virt = NULL;
	}

	vc->sg_descs[pb] = NULL;
}

static int tw686x_sg_dma_alloc(struct tw686x_video_channel *vc,
			       unsigned int pb)
{
	struct tw686x_dma_desc *desc = &vc->dma_descs[pb];
	struct tw686x_dev *dev = vc->dev;
	u32 reg = pb ? DMA_PAGE_TABLE1_ADDR[vc->ch] :
		       DMA_PAGE_TABLE0_ADDR[vc->ch];
	void *virt;

	if (desc->size) {
		virt = dma_alloc_coherent(&dev->pci_dev->dev, desc->size,
					  &desc->phys, GFP_KERNEL);
		if (!virt) {
			v4l2_err(&dev->v4l2_dev,
				 "dma%d: unable to allocate %s-buffer\n",
				 vc->ch, pb ? "B" : "P");
			return -ENOMEM;
		}
		desc->virt = virt;
		reg_write(dev, reg, desc->phys);
	} else {
		virt = dev->video_channels[0].dma_descs[pb].virt +

Annotation

Implementation Notes