Exemple #1
0
static int fimc_capture_close(struct file *file)
{
	struct fimc_dev *fimc = video_drvdata(file);
	int ret;

	dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);

	if (mutex_lock_interruptible(&fimc->lock))
		return -ERESTARTSYS;

	if (--fimc->vid_cap.refcnt == 0) {
		clear_bit(ST_CAPT_BUSY, &fimc->state);
		fimc_stop_capture(fimc, false);
		fimc_pipeline_call(fimc, close, &fimc->pipeline);
		clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
	}

	pm_runtime_put(&fimc->pdev->dev);

	if (fimc->vid_cap.refcnt == 0) {
		vb2_queue_release(&fimc->vid_cap.vbq);
		fimc_ctrls_delete(fimc->vid_cap.ctx);
	}

	ret = v4l2_fh_release(file);

	mutex_unlock(&fimc->lock);
	return ret;
}
Exemple #2
0
static int fimc_md_link_notify(struct media_pad *source,
			       struct media_pad *sink, u32 flags)
{
	struct fimc_lite *fimc_lite = NULL;
	struct fimc_dev *fimc = NULL;
	struct fimc_pipeline *pipeline;
	struct v4l2_subdev *sd;
	int ret = 0;

	if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
		return 0;

	sd = media_entity_to_v4l2_subdev(sink->entity);

	switch (sd->grp_id) {
	case FLITE_GROUP_ID:
		fimc_lite = v4l2_get_subdevdata(sd);
		pipeline = &fimc_lite->pipeline;
		break;
	case FIMC_GROUP_ID:
		fimc = v4l2_get_subdevdata(sd);
		pipeline = &fimc->pipeline;
		break;
	default:
		return 0;
	}

	if (!(flags & MEDIA_LNK_FL_ENABLED)) {
		ret = __fimc_pipeline_close(pipeline);
		pipeline->subdevs[IDX_SENSOR] = NULL;
		pipeline->subdevs[IDX_CSIS] = NULL;

		if (fimc) {
			mutex_lock(&fimc->lock);
			fimc_ctrls_delete(fimc->vid_cap.ctx);
			mutex_unlock(&fimc->lock);
		}
		return ret;
	}
	/*
	 * Link activation. Enable power of pipeline elements only if the
	 * pipeline is already in use, i.e. its video node is opened.
	 * Recreate the controls destroyed during the link deactivation.
	 */
	if (fimc) {
		mutex_lock(&fimc->lock);
		if (fimc->vid_cap.refcnt > 0) {
			ret = __fimc_pipeline_open(pipeline,
						   source->entity, true);
		if (!ret)
			ret = fimc_capture_ctrls_create(fimc);
		}
		mutex_unlock(&fimc->lock);
	} else {
		mutex_lock(&fimc_lite->lock);
		ret = __fimc_pipeline_open(pipeline, source->entity, true);
		mutex_unlock(&fimc_lite->lock);
	}
	return ret ? -EPIPE : ret;
}
static int fimc_md_link_notify(struct media_pad *source,
			       struct media_pad *sink, u32 flags)
{
	struct v4l2_subdev *sd;
	struct fimc_dev *fimc;
	int ret = 0;

	if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
		return 0;

	sd = media_entity_to_v4l2_subdev(sink->entity);
	fimc = v4l2_get_subdevdata(sd);

	if (!(flags & MEDIA_LNK_FL_ENABLED)) {
		ret = __fimc_pipeline_shutdown(fimc);
		fimc->pipeline.sensor = NULL;
		fimc->pipeline.csis = NULL;

		mutex_lock(&fimc->lock);
		fimc_ctrls_delete(fimc->vid_cap.ctx);
		mutex_unlock(&fimc->lock);
		return ret;
	}
	mutex_lock(&fimc->lock);
	if (fimc->vid_cap.refcnt > 0) {
		ret = __fimc_pipeline_initialize(fimc, source->entity, true);
		if (!ret)
			ret = fimc_capture_ctrls_create(fimc);
	}
	mutex_unlock(&fimc->lock);

	return ret ? -EPIPE : ret;
}
Exemple #4
0
static int fimc_capture_close(struct file *file)
{
	struct fimc_dev *fimc = video_drvdata(file);

	dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);

	if (--fimc->vid_cap.refcnt == 0) {
		clear_bit(ST_CAPT_BUSY, &fimc->state);
		fimc_stop_capture(fimc, false);
		fimc_pipeline_shutdown(fimc);
		clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
	}

	pm_runtime_put(&fimc->pdev->dev);

	if (fimc->vid_cap.refcnt == 0) {
		vb2_queue_release(&fimc->vid_cap.vbq);
		fimc_ctrls_delete(fimc->vid_cap.ctx);
	}
	return v4l2_fh_release(file);
}
Exemple #5
0
static int fimc_m2m_release(struct file *file)
{
    struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
    struct fimc_dev *fimc = ctx->fimc_dev;

    dbg("pid: %d, state: 0x%lx, refcnt= %d",
        task_pid_nr(current), fimc->state, fimc->m2m.refcnt);

    mutex_lock(&fimc->lock);

    v4l2_m2m_ctx_release(ctx->m2m_ctx);
    fimc_ctrls_delete(ctx);
    v4l2_fh_del(&ctx->fh);
    v4l2_fh_exit(&ctx->fh);

    if (--fimc->m2m.refcnt <= 0)
        clear_bit(ST_M2M_RUN, &fimc->state);
    kfree(ctx);

    mutex_unlock(&fimc->lock);
    return 0;
}
static int fimc_md_link_notify(struct media_pad *source,
			       struct media_pad *sink, u32 flags)
{
	struct v4l2_subdev *sd;
	struct fimc_dev *fimc;
	int ret = 0;

	if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
		return 0;

	sd = media_entity_to_v4l2_subdev(sink->entity);
	fimc = v4l2_get_subdevdata(sd);

	if (!(flags & MEDIA_LNK_FL_ENABLED)) {
		ret = __fimc_pipeline_shutdown(fimc);
		fimc->pipeline.sensor = NULL;
		fimc->pipeline.csis = NULL;

		mutex_lock(&fimc->lock);
		fimc_ctrls_delete(fimc->vid_cap.ctx);
		mutex_unlock(&fimc->lock);
		return ret;
	}
	/*
	 * Link activation. Enable power of pipeline elements only if the
	 * pipeline is already in use, i.e. its video node is opened.
	 * Recreate the controls destroyed during the link deactivation.
	 */
	mutex_lock(&fimc->lock);
	if (fimc->vid_cap.refcnt > 0) {
		ret = __fimc_pipeline_initialize(fimc, source->entity, true);
		if (!ret)
			ret = fimc_capture_ctrls_create(fimc);
	}
	mutex_unlock(&fimc->lock);

	return ret ? -EPIPE : ret;
}
Exemple #7
0
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;
}