/* Return a pointer to the ISP video instance at the far end of the pipeline. */ static int isp_video_get_graph_data(struct isp_video *video, struct isp_pipeline *pipe) { struct media_entity_graph graph; struct media_entity *entity = &video->video.entity; struct media_device *mdev = entity->graph_obj.mdev; struct isp_video *far_end = NULL; int ret; mutex_lock(&mdev->graph_mutex); ret = media_entity_graph_walk_init(&graph, entity->graph_obj.mdev); if (ret) { mutex_unlock(&mdev->graph_mutex); return ret; } media_entity_graph_walk_start(&graph, entity); while ((entity = media_entity_graph_walk_next(&graph))) { struct isp_video *__video; media_entity_enum_set(&pipe->ent_enum, entity); if (far_end != NULL) continue; if (entity == &video->video.entity) continue; if (!is_media_entity_v4l2_video_device(entity)) continue; __video = to_isp_video(media_entity_to_video_device(entity)); if (__video->type != video->type) far_end = __video; } mutex_unlock(&mdev->graph_mutex); media_entity_graph_walk_cleanup(&graph); if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { pipe->input = far_end; pipe->output = video; } else { if (far_end == NULL) return -EPIPE; pipe->input = video; pipe->output = far_end; } return 0; }
/* * iss_pipeline_disable - Disable streaming on a pipeline * @pipe: ISS pipeline * @until: entity at which to stop pipeline walk * * Walk the entities chain starting at the pipeline output video node and stop * all modules in the chain. Wait synchronously for the modules to be stopped if * necessary. * * If the until argument isn't NULL, stop the pipeline walk when reaching the * until entity. This is used to disable a partially started pipeline due to a * subdev start error. */ static int iss_pipeline_disable(struct iss_pipeline *pipe, struct media_entity *until) { struct iss_device *iss = pipe->output->iss; struct media_entity *entity; struct media_pad *pad; struct v4l2_subdev *subdev; int failure = 0; int ret; entity = &pipe->output->video.entity; while (1) { pad = &entity->pads[0]; if (!(pad->flags & MEDIA_PAD_FL_SINK)) break; pad = media_entity_remote_pad(pad); if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) break; entity = pad->entity; if (entity == until) break; subdev = media_entity_to_v4l2_subdev(entity); ret = v4l2_subdev_call(subdev, video, s_stream, 0); if (ret < 0) { dev_warn(iss->dev, "%s: module stop timeout.\n", subdev->name); /* If the entity failed to stopped, assume it has * crashed. Mark it as such, the ISS will be reset when * applications will release it. */ media_entity_enum_set(&iss->crashed, &subdev->entity); failure = -ETIMEDOUT; } } return failure; }