drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c
Source file repositories/reference/linux-study-clean/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c- Extension
.c- Size
- 41270 bytes
- Lines
- 1474
- 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.
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/device.hlinux/dma-mapping.hlinux/errno.hlinux/kernel.hlinux/media-bus-format.hlinux/minmax.hlinux/pm_runtime.hlinux/string.hlinux/types.hlinux/videodev2.hmedia/media-entity.hmedia/v4l2-ctrls.hmedia/v4l2-dev.hmedia/v4l2-event.hmedia/v4l2-fh.hmedia/v4l2-ioctl.hmedia/v4l2-subdev.hmedia/videobuf2-core.hmedia/videobuf2-dma-contig.hmedia/videobuf2-v4l2.himx8-isi-core.himx8-isi-regs.h
Detected Declarations
function mxc_isi_format_by_fourccfunction mxc_isi_format_enumfunction mxc_isi_format_tryfunction mxc_isi_video_frame_write_donefunction interruptfunction mxc_isi_video_free_discard_buffersfunction mxc_isi_video_alloc_discard_buffersfunction mxc_isi_video_validate_formatfunction mxc_isi_video_return_buffersfunction mxc_isi_video_queue_first_buffersfunction mxc_isi_video_queue_setupfunction mxc_isi_video_buffer_initfunction mxc_isi_video_buffer_preparefunction mxc_isi_vb2_queue_setupfunction mxc_isi_vb2_buffer_initfunction mxc_isi_vb2_buffer_preparefunction mxc_isi_vb2_buffer_queuefunction mxc_isi_video_init_channelfunction mxc_isi_vb2_prepare_streamingfunction mxc_isi_vb2_start_streamingfunction mxc_isi_vb2_stop_streamingfunction mxc_isi_vb2_unprepare_streamingfunction mxc_isi_video_s_ctrlfunction mxc_isi_video_ctrls_createfunction mxc_isi_video_ctrls_deletefunction mxc_isi_video_querycapfunction mxc_isi_video_enum_fmtfunction mxc_isi_video_g_fmtfunction mxc_isi_video_try_fmtfunction mxc_isi_video_s_fmtfunction mxc_isi_video_enum_framesizesfunction mxc_isi_video_openfunction mxc_isi_video_releasefunction mxc_isi_video_suspendfunction mxc_isi_video_resumefunction mxc_isi_video_registerfunction mxc_isi_video_unregister
Annotated Snippet
if (!next_buf) {
dev_warn(dev, "trying to access empty discard list\n");
goto done;
}
}
mxc_isi_channel_set_outbuf(pipe, next_buf->dma_addrs, buf_id);
next_buf->id = buf_id;
/*
* Check if we have raced with the end of frame interrupt. If so, we
* can't tell if the ISI has recorded the new address, or is still
* using the previous buffer. We must assume the latter as that is the
* worst case.
*
* For instance, if we are handling IRQ1 and now detect the FRM
* interrupt, assume B2 has completed and the ISI has switched to BUF2
* using B1 just before we programmed B3. Unlike in the previous race
* condition, B3 has been programmed and will be written to the next
* time the ISI switches to BUF2. We can however handle this exactly as
* the first race condition, as we'll program B3 (still at the head of
* the pending list) when handling IRQ3.
*/
status = mxc_isi_channel_irq_status(pipe, false);
if (status & CHNL_STS_FRM_STRD) {
dev_dbg(dev, "raced with frame end interrupt\n");
video->frame_count += 2;
goto done;
}
/*
* The next buffer has been queued successfully, move it to the active
* list, and complete the current buffer.
*/
list_move_tail(&next_buf->list, &video->out_active);
if (!buf->discard) {
list_del_init(&buf->list);
buf->v4l2_buf.sequence = video->frame_count;
buf->v4l2_buf.vb2_buf.timestamp = ktime_get_ns();
vb2_buffer_done(&buf->v4l2_buf.vb2_buf, VB2_BUF_STATE_DONE);
} else {
list_move_tail(&buf->list, &video->out_discard);
}
video->frame_count++;
done:
spin_unlock(&video->buf_lock);
}
static void mxc_isi_video_free_discard_buffers(struct mxc_isi_video *video)
{
unsigned int i;
for (i = 0; i < video->pix.num_planes; i++) {
struct mxc_isi_dma_buffer *buf = &video->discard_buffer[i];
if (!buf->addr)
continue;
dma_free_coherent(video->pipe->isi->dev, buf->size, buf->addr,
buf->dma);
buf->addr = NULL;
}
}
static int mxc_isi_video_alloc_discard_buffers(struct mxc_isi_video *video)
{
unsigned int i, j;
/* Allocate memory for each plane. */
for (i = 0; i < video->pix.num_planes; i++) {
struct mxc_isi_dma_buffer *buf = &video->discard_buffer[i];
buf->size = PAGE_ALIGN(video->pix.plane_fmt[i].sizeimage);
buf->addr = dma_alloc_coherent(video->pipe->isi->dev, buf->size,
&buf->dma, GFP_DMA | GFP_KERNEL);
if (!buf->addr) {
mxc_isi_video_free_discard_buffers(video);
return -ENOMEM;
}
dev_dbg(video->pipe->isi->dev,
"discard buffer plane %u: %zu bytes @%pad (CPU address %p)\n",
i, buf->size, &buf->dma, buf->addr);
}
/* Fill the DMA addresses in the discard buffers. */
for (i = 0; i < ARRAY_SIZE(video->buf_discard); ++i) {
Annotation
- Immediate include surface: `linux/device.h`, `linux/dma-mapping.h`, `linux/errno.h`, `linux/kernel.h`, `linux/media-bus-format.h`, `linux/minmax.h`, `linux/pm_runtime.h`, `linux/string.h`.
- Detected declarations: `function mxc_isi_format_by_fourcc`, `function mxc_isi_format_enum`, `function mxc_isi_format_try`, `function mxc_isi_video_frame_write_done`, `function interrupt`, `function mxc_isi_video_free_discard_buffers`, `function mxc_isi_video_alloc_discard_buffers`, `function mxc_isi_video_validate_format`, `function mxc_isi_video_return_buffers`, `function mxc_isi_video_queue_first_buffers`.
- Atlas domain: Driver Families / drivers/media.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.