/** * fimc_capture_ctrls_create - initialize the control handler * Initialize the capture video node control handler and fill it * with the FIMC controls. Inherit any sensor's controls if the * 'user_subdev_api' flag is false (default behaviour). * This function need to be called with the graph mutex held. */ int fimc_capture_ctrls_create(struct fimc_dev *fimc) { struct fimc_vid_cap *vid_cap = &fimc->vid_cap; int ret; if (WARN_ON(vid_cap->ctx == NULL)) return -ENXIO; if (vid_cap->ctx->ctrls_rdy) return 0; ret = fimc_ctrls_create(vid_cap->ctx); if (ret || vid_cap->user_subdev_api) return ret; return v4l2_ctrl_add_handler(&vid_cap->ctx->ctrl_handler, fimc->pipeline.sensor->ctrl_handler); }
static int fimc_m2m_open(struct file *file) { struct fimc_dev *fimc = video_drvdata(file); struct fimc_ctx *ctx; int ret = -EBUSY; pr_debug("pid: %d, state: %#lx\n", task_pid_nr(current), fimc->state); if (mutex_lock_interruptible(&fimc->lock)) return -ERESTARTSYS; /* * Don't allow simultaneous open() of the mem-to-mem and the * capture video node that belong to same FIMC IP instance. */ if (test_bit(ST_CAPT_BUSY, &fimc->state)) goto unlock; ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) { ret = -ENOMEM; goto unlock; } v4l2_fh_init(&ctx->fh, &fimc->m2m.vfd); ctx->fimc_dev = fimc; /* Default color format */ ctx->s_frame.fmt = fimc_get_format(0); ctx->d_frame.fmt = fimc_get_format(0); ret = fimc_ctrls_create(ctx); if (ret) goto error_fh; /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrls.handler; file->private_data = &ctx->fh; v4l2_fh_add(&ctx->fh); /* Setup the device context for memory-to-memory mode */ ctx->state = FIMC_CTX_M2M; ctx->flags = 0; ctx->in_path = FIMC_IO_DMA; ctx->out_path = FIMC_IO_DMA; ctx->scaler.enabled = 1; ctx->m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init); if (IS_ERR(ctx->m2m_ctx)) { ret = PTR_ERR(ctx->m2m_ctx); goto error_c; } if (fimc->m2m.refcnt++ == 0) set_bit(ST_M2M_RUN, &fimc->state); ret = fimc_m2m_set_default_format(ctx); if (ret < 0) goto error_m2m_ctx; mutex_unlock(&fimc->lock); return 0; error_m2m_ctx: v4l2_m2m_ctx_release(ctx->m2m_ctx); error_c: fimc_ctrls_delete(ctx); error_fh: v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); kfree(ctx); unlock: mutex_unlock(&fimc->lock); return ret; }
static int fimc_m2m_open(struct file *file) { struct fimc_dev *fimc = video_drvdata(file); struct fimc_ctx *ctx; int ret = -EBUSY; dbg("pid: %d, state: 0x%lx, refcnt: %d", task_pid_nr(current), fimc->state, fimc->vid_cap.refcnt); if (mutex_lock_interruptible(&fimc->lock)) return -ERESTARTSYS; /* * Return if the corresponding video capture node * is already opened. */ if (fimc->vid_cap.refcnt > 0) goto unlock; ctx = kzalloc(sizeof *ctx, GFP_KERNEL); if (!ctx) { ret = -ENOMEM; goto unlock; } v4l2_fh_init(&ctx->fh, fimc->m2m.vfd); ctx->fimc_dev = fimc; /* Default color format */ ctx->s_frame.fmt = fimc_get_format(0); ctx->d_frame.fmt = fimc_get_format(0); ret = fimc_ctrls_create(ctx); if (ret) goto error_fh; /* Use separate control handler per file handle */ ctx->fh.ctrl_handler = &ctx->ctrls.handler; file->private_data = &ctx->fh; v4l2_fh_add(&ctx->fh); /* Setup the device context for memory-to-memory mode */ ctx->state = FIMC_CTX_M2M; ctx->flags = 0; ctx->in_path = FIMC_IO_DMA; ctx->out_path = FIMC_IO_DMA; ctx->m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init); if (IS_ERR(ctx->m2m_ctx)) { ret = PTR_ERR(ctx->m2m_ctx); goto error_c; } if (fimc->m2m.refcnt++ == 0) set_bit(ST_M2M_RUN, &fimc->state); mutex_unlock(&fimc->lock); return 0; error_c: fimc_ctrls_delete(ctx); error_fh: v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); kfree(ctx); unlock: mutex_unlock(&fimc->lock); return ret; }