static void fimc_capture_irq_handler(struct fimc_dev *fimc)
{
	struct fimc_vid_cap *cap = &fimc->vid_cap;
	struct fimc_vid_buffer *v_buf;
	struct timeval *tv;
	struct timespec ts;

	if (!list_empty(&cap->active_buf_q) &&
	    test_bit(ST_CAPT_RUN, &fimc->state)) {
		ktime_get_real_ts(&ts);

		v_buf = active_queue_pop(cap);

		tv = &v_buf->vb.v4l2_buf.timestamp;
		tv->tv_sec = ts.tv_sec;
		tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
		v_buf->vb.v4l2_buf.sequence = cap->frame_count++;

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

	if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) {
		wake_up(&fimc->irq_queue);
		return;
	}

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

		v_buf = pending_queue_pop(cap);
		fimc_hw_set_output_addr(fimc, &v_buf->paddr, cap->buf_index);
		v_buf->index = cap->buf_index;

		/* Move the buffer to the capture active queue */
		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;
	}

	if (cap->active_buf_cnt == 0) {
		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);
	}

	dbg("frame: %d, active_buf_cnt: %d",
	    fimc_hw_get_frame_index(fimc), cap->active_buf_cnt);
}
Beispiel #2
0
static int fimc_stop_capture(struct fimc_dev *fimc)
{
    unsigned long flags;
    struct fimc_vid_cap *cap;
    struct fimc_vid_buffer *buf;

    cap = &fimc->vid_cap;

    if (!fimc_capture_active(fimc))
        return 0;

    spin_lock_irqsave(&fimc->slock, flags);
    set_bit(ST_CAPT_SHUT, &fimc->state);
    fimc_deactivate_capture(fimc);
    spin_unlock_irqrestore(&fimc->slock, flags);

    wait_event_timeout(fimc->irq_queue,
                       !test_bit(ST_CAPT_SHUT, &fimc->state),
                       FIMC_SHUTDOWN_TIMEOUT);

    v4l2_subdev_call(cap->sd, video, s_stream, 0);

    spin_lock_irqsave(&fimc->slock, flags);
    fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_PEND |
                     1 << ST_CAPT_SHUT | 1 << ST_CAPT_STREAM);

    fimc->vid_cap.active_buf_cnt = 0;

    /* Release buffers that were enqueued in the driver by videobuf2. */
    while (!list_empty(&cap->pending_buf_q)) {
        buf = pending_queue_pop(cap);
        vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
    }

    while (!list_empty(&cap->active_buf_q)) {
        buf = active_queue_pop(cap);
        vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
    }

    spin_unlock_irqrestore(&fimc->slock, flags);

    dbg("state: 0x%lx", fimc->state);
    return 0;
}
Beispiel #3
0
static void fimc_capture_irq_handler(struct fimc_dev *fimc)
{
	struct fimc_vid_cap *cap = &fimc->vid_cap;
	struct fimc_vid_buffer *v_buf;

	if (!list_empty(&cap->active_buf_q) &&
	    test_bit(ST_CAPT_RUN, &fimc->state)) {
		v_buf = active_queue_pop(cap);
		vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE);
	}

	if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) {
		wake_up(&fimc->irq_queue);
		return;
	}

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

		v_buf = pending_queue_pop(cap);
		fimc_hw_set_output_addr(fimc, &v_buf->paddr, cap->buf_index);
		v_buf->index = cap->buf_index;

		/* Move the buffer to the capture active queue */
		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;
	}

	if (cap->active_buf_cnt == 0) {
		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);
	}

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