static void fimc_device_run(void *priv) { struct vb2_buffer *vb = NULL; struct fimc_ctx *ctx = priv; struct fimc_frame *sf, *df; struct fimc_dev *fimc; unsigned long flags; u32 ret; if (WARN(!ctx, "Null context\n")) return; fimc = ctx->fimc_dev; spin_lock_irqsave(&fimc->slock, flags); set_bit(ST_M2M_PEND, &fimc->state); sf = &ctx->s_frame; df = &ctx->d_frame; if (ctx->state & FIMC_PARAMS) { /* Prepare the DMA offsets for scaler */ fimc_prepare_dma_offset(ctx, sf); fimc_prepare_dma_offset(ctx, df); } vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx); ret = fimc_prepare_addr(ctx, vb, sf, &sf->paddr); if (ret) goto dma_unlock; vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); ret = fimc_prepare_addr(ctx, vb, df, &df->paddr); if (ret) goto dma_unlock; /* Reconfigure hardware if the context has changed. */ if (fimc->m2m.ctx != ctx) { ctx->state |= FIMC_PARAMS; fimc->m2m.ctx = ctx; } if (ctx->state & FIMC_PARAMS) { fimc_set_yuv_order(ctx); fimc_hw_set_input_path(ctx); fimc_hw_set_in_dma(ctx); ret = fimc_set_scaler_info(ctx); if (ret) goto dma_unlock; fimc_hw_set_prescaler(ctx); fimc_hw_set_mainscaler(ctx); fimc_hw_set_target_format(ctx); fimc_hw_set_rotation(ctx); fimc_hw_set_effect(ctx); fimc_hw_set_out_dma(ctx); if (fimc->variant->has_alpha) fimc_hw_set_rgb_alpha(ctx); fimc_hw_set_output_path(ctx); } fimc_hw_set_input_addr(fimc, &sf->paddr); fimc_hw_set_output_addr(fimc, &df->paddr, -1); fimc_activate_capture(ctx); ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP | FIMC_SRC_FMT | FIMC_DST_FMT); fimc_hw_activate_input_dma(fimc, true); dma_unlock: spin_unlock_irqrestore(&fimc->slock, flags); }
void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf) { struct fimc_vid_cap *cap = &fimc->vid_cap; struct fimc_vid_buffer *v_buf; struct timeval *tv; struct timespec ts; if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) { wake_up(&fimc->irq_queue); goto done; } if (!list_empty(&cap->active_buf_q) && test_bit(ST_CAPT_RUN, &fimc->state) && deq_buf) { ktime_get_real_ts(&ts); v_buf = fimc_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 (!list_empty(&cap->pending_buf_q)) { v_buf = fimc_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 */ 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; } 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 void fimc_device_run(void *priv) { struct vb2_v4l2_buffer *src_vb, *dst_vb; struct fimc_ctx *ctx = priv; struct fimc_frame *sf, *df; struct fimc_dev *fimc; unsigned long flags; int ret; if (WARN(!ctx, "Null context\n")) return; fimc = ctx->fimc_dev; spin_lock_irqsave(&fimc->slock, flags); set_bit(ST_M2M_PEND, &fimc->state); sf = &ctx->s_frame; df = &ctx->d_frame; if (ctx->state & FIMC_PARAMS) { /* Prepare the DMA offsets for scaler */ fimc_prepare_dma_offset(ctx, sf); fimc_prepare_dma_offset(ctx, df); } src_vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); ret = fimc_prepare_addr(ctx, &src_vb->vb2_buf, sf, &sf->paddr); if (ret) goto dma_unlock; dst_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); ret = fimc_prepare_addr(ctx, &dst_vb->vb2_buf, df, &df->paddr); if (ret) goto dma_unlock; dst_vb->timestamp = src_vb->timestamp; dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; dst_vb->flags |= src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; /* Reconfigure hardware if the context has changed. */ if (fimc->m2m.ctx != ctx) { ctx->state |= FIMC_PARAMS; fimc->m2m.ctx = ctx; } if (ctx->state & FIMC_PARAMS) { fimc_set_yuv_order(ctx); fimc_hw_set_input_path(ctx); fimc_hw_set_in_dma(ctx); ret = fimc_set_scaler_info(ctx); if (ret) goto dma_unlock; fimc_hw_set_prescaler(ctx); fimc_hw_set_mainscaler(ctx); fimc_hw_set_target_format(ctx); fimc_hw_set_rotation(ctx); fimc_hw_set_effect(ctx); fimc_hw_set_out_dma(ctx); if (fimc->drv_data->alpha_color) fimc_hw_set_rgb_alpha(ctx); fimc_hw_set_output_path(ctx); } fimc_hw_set_input_addr(fimc, &sf->paddr); fimc_hw_set_output_addr(fimc, &df->paddr, -1); fimc_activate_capture(ctx); ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP); fimc_hw_activate_input_dma(fimc, true); dma_unlock: spin_unlock_irqrestore(&fimc->slock, flags); }