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; }
static int fimc_capture_open(struct file *file) { struct fimc_dev *fimc = video_drvdata(file); int ret = -EBUSY; dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); if (mutex_lock_interruptible(&fimc->lock)) return -ERESTARTSYS; if (fimc_m2m_active(fimc)) goto unlock; set_bit(ST_CAPT_BUSY, &fimc->state); ret = pm_runtime_get_sync(&fimc->pdev->dev); if (ret < 0) goto unlock; ret = v4l2_fh_open(file); if (ret) { pm_runtime_put(&fimc->pdev->dev); goto unlock; } if (++fimc->vid_cap.refcnt == 1) { ret = fimc_pipeline_call(fimc, open, &fimc->pipeline, &fimc->vid_cap.vfd.entity, true); if (!ret && !fimc->vid_cap.user_subdev_api) ret = fimc_capture_set_default_format(fimc); if (!ret) ret = fimc_capture_ctrls_create(fimc); if (ret < 0) { clear_bit(ST_CAPT_BUSY, &fimc->state); pm_runtime_put_sync(&fimc->pdev->dev); fimc->vid_cap.refcnt--; v4l2_fh_release(file); } } unlock: mutex_unlock(&fimc->lock); return 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; } /* * 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; }
static int fimc_capture_open(struct file *file) { struct fimc_dev *fimc = video_drvdata(file); int ret = v4l2_fh_open(file); if (ret) return ret; dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); /* Return if the corresponding video mem2mem node is already opened. */ if (fimc_m2m_active(fimc)) return -EBUSY; set_bit(ST_CAPT_BUSY, &fimc->state); pm_runtime_get_sync(&fimc->pdev->dev); if (++fimc->vid_cap.refcnt == 1) { ret = fimc_pipeline_initialize(fimc, &fimc->vid_cap.vfd->entity, true); if (ret < 0) { dev_err(&fimc->pdev->dev, "Video pipeline initialization failed\n"); pm_runtime_put_sync(&fimc->pdev->dev); fimc->vid_cap.refcnt--; v4l2_fh_release(file); clear_bit(ST_CAPT_BUSY, &fimc->state); return ret; } ret = fimc_capture_ctrls_create(fimc); if (!ret && !fimc->vid_cap.user_subdev_api) ret = fimc_capture_set_default_format(fimc); } return ret; }