drivers/media/common/saa7146/saa7146_video.c

Source file repositories/reference/linux-study-clean/drivers/media/common/saa7146/saa7146_video.c

File Facts

System
Linux kernel
Corpus path
drivers/media/common/saa7146/saa7146_video.c
Extension
.c
Size
19559 bytes
Lines
724
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

if (formats[i].pixelformat == fourcc) {
			return formats+i;
		}
	}

	DEB_D("unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
	return NULL;
}

/********************************************************************************/
/* common pagetable functions */

static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf)
{
	struct saa7146_vv *vv = dev->vv_data;
	struct pci_dev *pci = dev->pci;
	struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
	struct scatterlist *list = sgt->sgl;
	int length = sgt->nents;
	struct v4l2_pix_format *pix = &vv->video_fmt;
	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pix->pixelformat);

	DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length);

	if( 0 != IS_PLANAR(sfmt->trans)) {
		struct saa7146_pgtable *pt1 = &buf->pt[0];
		struct saa7146_pgtable *pt2 = &buf->pt[1];
		struct saa7146_pgtable *pt3 = &buf->pt[2];
		struct sg_dma_page_iter dma_iter;
		__le32  *ptr1, *ptr2, *ptr3;
		__le32 fill;

		int size = pix->width * pix->height;
		int i, m1, m2, m3, o1, o2;

		switch( sfmt->depth ) {
			case 12: {
				/* create some offsets inside the page table */
				m1 = ((size + PAGE_SIZE) / PAGE_SIZE) - 1;
				m2 = ((size + (size / 4) + PAGE_SIZE) / PAGE_SIZE) - 1;
				m3 = ((size + (size / 2) + PAGE_SIZE) / PAGE_SIZE) - 1;
				o1 = size % PAGE_SIZE;
				o2 = (size + (size / 4)) % PAGE_SIZE;
				DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
					size, m1, m2, m3, o1, o2);
				break;
			}
			case 16: {
				/* create some offsets inside the page table */
				m1 = ((size + PAGE_SIZE) / PAGE_SIZE) - 1;
				m2 = ((size + (size / 2) + PAGE_SIZE) / PAGE_SIZE) - 1;
				m3 = ((2 * size + PAGE_SIZE) / PAGE_SIZE) - 1;
				o1 = size % PAGE_SIZE;
				o2 = (size + (size / 2)) % PAGE_SIZE;
				DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
					size, m1, m2, m3, o1, o2);
				break;
			}
			default: {
				return -1;
			}
		}

		ptr1 = pt1->cpu;
		ptr2 = pt2->cpu;
		ptr3 = pt3->cpu;

		for_each_sg_dma_page(list, &dma_iter, length, 0)
			*ptr1++ = cpu_to_le32(sg_page_iter_dma_address(&dma_iter) - list->offset);

		/* if we have a user buffer, the first page may not be
		   aligned to a page boundary. */
		pt1->offset = sgt->sgl->offset;
		pt2->offset = pt1->offset + o1;
		pt3->offset = pt1->offset + o2;

		/* create video-dma2 page table */
		ptr1 = pt1->cpu;
		for (i = m1; i <= m2; i++, ptr2++)
			*ptr2 = ptr1[i];
		fill = *(ptr2 - 1);
		for (; i < 1024; i++, ptr2++)
			*ptr2 = fill;
		/* create video-dma3 page table */
		ptr1 = pt1->cpu;
		for (i = m2; i <= m3; i++, ptr3++)
			*ptr3 = ptr1[i];
		fill = *(ptr3 - 1);
		for (; i < 1024; i++, ptr3++)
			*ptr3 = fill;

Annotation

Implementation Notes