drivers/media/pci/cx88/cx88-core.c

Source file repositories/reference/linux-study-clean/drivers/media/pci/cx88/cx88-core.c

File Facts

System
Linux kernel
Corpus path
drivers/media/pci/cx88/cx88-core.c
Extension
.c
Size
30245 bytes
Lines
1100
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 (offset && offset >= sg_dma_len(sg)) {
			offset -= sg_dma_len(sg);
			sg = sg_next(sg);
		}
		if (lpi && line > 0 && !(line % lpi))
			sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
		else
			sol = RISC_SOL;
		if (bpl <= sg_dma_len(sg) - offset) {
			/* fits into current chunk */
			*(rp++) = cpu_to_le32(RISC_WRITE | sol |
					      RISC_EOL | bpl);
			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
			offset += bpl;
		} else {
			/* scanline needs to be split */
			todo = bpl;
			*(rp++) = cpu_to_le32(RISC_WRITE | sol |
					      (sg_dma_len(sg) - offset));
			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
			todo -= (sg_dma_len(sg) - offset);
			offset = 0;
			sg = sg_next(sg);
			while (todo > sg_dma_len(sg)) {
				*(rp++) = cpu_to_le32(RISC_WRITE |
						      sg_dma_len(sg));
				*(rp++) = cpu_to_le32(sg_dma_address(sg));
				todo -= sg_dma_len(sg);
				sg = sg_next(sg);
			}
			*(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
			*(rp++) = cpu_to_le32(sg_dma_address(sg));
			offset += todo;
		}
		offset += padding;
	}

	return rp;
}

int cx88_risc_buffer(struct pci_dev *pci, struct cx88_riscmem *risc,
		     struct scatterlist *sglist,
		     unsigned int top_offset, unsigned int bottom_offset,
		     unsigned int bpl, unsigned int padding, unsigned int lines)
{
	u32 instructions, fields;
	__le32 *rp;

	fields = 0;
	if (top_offset != UNSET)
		fields++;
	if (bottom_offset != UNSET)
		fields++;

	/*
	 * estimate risc mem: worst case is one write per page border +
	 * one write per scan line + syncs + jump (all 2 dwords).  Padding
	 * can cause next bpl to start close to a page border.  First DMA
	 * region may be smaller than PAGE_SIZE
	 */
	instructions  = fields * (1 + ((bpl + padding) * lines) /
				  PAGE_SIZE + lines);
	instructions += 4;
	risc->size = instructions * 8;
	risc->dma = 0;
	risc->cpu = dma_alloc_coherent(&pci->dev, risc->size, &risc->dma,
				       GFP_KERNEL);
	if (!risc->cpu)
		return -ENOMEM;

	/* write risc instructions */
	rp = risc->cpu;
	if (top_offset != UNSET)
		rp = cx88_risc_field(rp, sglist, top_offset, 0,
				     bpl, padding, lines, 0, true);
	if (bottom_offset != UNSET)
		rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
				     bpl, padding, lines, 0,
				     top_offset == UNSET);

	/* save pointer to jmp instruction address */
	risc->jmp = rp;
	WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
	return 0;
}
EXPORT_SYMBOL(cx88_risc_buffer);

int cx88_risc_databuffer(struct pci_dev *pci, struct cx88_riscmem *risc,
			 struct scatterlist *sglist, unsigned int bpl,
			 unsigned int lines, unsigned int lpi)

Annotation

Implementation Notes