drivers/media/platform/samsung/exynos4-is/fimc-capture.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/samsung/exynos4-is/fimc-capture.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/samsung/exynos4-is/fimc-capture.c
Extension
.c
Size
50304 bytes
Lines
1896
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

test_bit(ST_CAPT_RUN, &fimc->state) && deq_buf) {
		v_buf = fimc_active_queue_pop(cap);

		v_buf->vb.vb2_buf.timestamp = ktime_get_ns();
		v_buf->vb.sequence = cap->frame_count++;

		vb2_buffer_done(&v_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
	}

	if (!list_empty(&cap->pending_buf_q)) {

		v_buf = fimc_pending_queue_pop(cap);
		fimc_hw_set_output_addr(fimc, &v_buf->addr, cap->buf_index);
		v_buf->index = cap->buf_index;

		/* Move the buffer to the capture active queue */
		fimc_active_queue_add(cap, v_buf);

		dbg("next frame: %d, done frame: %d",
		    fimc_hw_get_frame_index(fimc), v_buf->index);

		if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
			cap->buf_index = 0;
	}
	/*
	 * Set up a buffer at MIPI-CSIS if current image format
	 * requires the frame embedded data capture.
	 */
	if (f->fmt->mdataplanes && !list_empty(&cap->active_buf_q)) {
		unsigned int plane = ffs(f->fmt->mdataplanes) - 1;
		unsigned int size = f->payload[plane];
		s32 index = fimc_hw_get_frame_index(fimc);
		void *vaddr;

		list_for_each_entry(v_buf, &cap->active_buf_q, list) {
			if (v_buf->index != index)
				continue;
			vaddr = vb2_plane_vaddr(&v_buf->vb.vb2_buf, plane);
			v4l2_subdev_call(csis, video, s_rx_buffer,
					 vaddr, &size);
			break;
		}
	}

	if (cap->active_buf_cnt == 0) {
		if (deq_buf)
			clear_bit(ST_CAPT_RUN, &fimc->state);

		if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
			cap->buf_index = 0;
	} else {
		set_bit(ST_CAPT_RUN, &fimc->state);
	}

	if (test_bit(ST_CAPT_APPLY_CFG, &fimc->state))
		fimc_capture_config_update(cap->ctx);
done:
	if (cap->active_buf_cnt == 1) {
		fimc_deactivate_capture(fimc);
		clear_bit(ST_CAPT_STREAM, &fimc->state);
	}

	dbg("frame: %d, active_buf_cnt: %d",
	    fimc_hw_get_frame_index(fimc), cap->active_buf_cnt);
}


static int start_streaming(struct vb2_queue *q, unsigned int count)
{
	struct fimc_ctx *ctx = q->drv_priv;
	struct fimc_dev *fimc = ctx->fimc_dev;
	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
	int min_bufs;
	int ret;

	vid_cap->frame_count = 0;

	ret = fimc_capture_hw_init(fimc);
	if (ret) {
		fimc_capture_state_cleanup(fimc, false);
		return ret;
	}

	set_bit(ST_CAPT_PEND, &fimc->state);

	min_bufs = fimc->vid_cap.reqbufs_count > 1 ? 2 : 1;

	if (vid_cap->active_buf_cnt >= min_bufs &&
	    !test_and_set_bit(ST_CAPT_STREAM, &fimc->state)) {
		fimc_activate_capture(ctx);

Annotation

Implementation Notes