diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/uvc/uvc_driver.c | 8 | ||||
-rw-r--r-- | drivers/media/video/uvc/uvc_entity.c | 40 | ||||
-rw-r--r-- | drivers/media/video/uvc/uvcvideo.h | 1 |
3 files changed, 39 insertions, 10 deletions
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 0bf3413..b6eae48 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -1616,6 +1616,10 @@ static void uvc_delete(struct uvc_device *dev) #ifdef CONFIG_MEDIA_CONTROLLER uvc_mc_cleanup_entity(entity); #endif + if (entity->vdev) { + video_device_release(entity->vdev); + entity->vdev = NULL; + } kfree(entity); } @@ -1638,8 +1642,6 @@ static void uvc_release(struct video_device *vdev) struct uvc_streaming *stream = video_get_drvdata(vdev); struct uvc_device *dev = stream->dev; - video_device_release(vdev); - /* Decrement the registered streams count and delete the device when it * reaches zero. */ @@ -1753,6 +1755,8 @@ static int uvc_register_terms(struct uvc_device *dev, ret = uvc_register_video(dev, stream); if (ret < 0) return ret; + + term->vdev = stream->vdev; } return 0; diff --git a/drivers/media/video/uvc/uvc_entity.c b/drivers/media/video/uvc/uvc_entity.c index 8e8e7ef..ede7852 100644 --- a/drivers/media/video/uvc/uvc_entity.c +++ b/drivers/media/video/uvc/uvc_entity.c @@ -33,6 +33,9 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain, int ret; for (i = 0; i < entity->num_pads; ++i) { + struct media_entity *source; + struct media_entity *sink; + if (!(entity->pads[i].flags & MEDIA_PAD_FL_SINK)) continue; @@ -40,14 +43,23 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain, if (remote == NULL) return -EINVAL; + source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING) + ? &remote->vdev->entity : &remote->subdev.entity; + sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING) + ? &entity->vdev->entity : &entity->subdev.entity; + remote_pad = remote->num_pads - 1; - ret = media_entity_create_link(&remote->subdev.entity, - remote_pad, &entity->subdev.entity, i, flags); + ret = media_entity_create_link(source, remote_pad, + sink, i, flags); if (ret < 0) return ret; } - return v4l2_device_register_subdev(&chain->dev->vdev, &entity->subdev); + if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) + ret = v4l2_device_register_subdev(&chain->dev->vdev, + &entity->subdev); + + return ret; } static struct v4l2_subdev_ops uvc_subdev_ops = { @@ -55,16 +67,28 @@ static struct v4l2_subdev_ops uvc_subdev_ops = { void uvc_mc_cleanup_entity(struct uvc_entity *entity) { - media_entity_cleanup(&entity->subdev.entity); + if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) + media_entity_cleanup(&entity->subdev.entity); + else if (entity->vdev != NULL) + media_entity_cleanup(&entity->vdev->entity); } static int uvc_mc_init_entity(struct uvc_entity *entity) { - v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops); - strlcpy(entity->subdev.name, entity->name, sizeof(entity->subdev.name)); + int ret; + + if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) { + v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops); + strlcpy(entity->subdev.name, entity->name, + sizeof(entity->subdev.name)); + + ret = media_entity_init(&entity->subdev.entity, + entity->num_pads, entity->pads, 0); + } else + ret = media_entity_init(&entity->vdev->entity, + entity->num_pads, entity->pads, 0); - return media_entity_init(&entity->subdev.entity, entity->num_pads, - entity->pads, 0); + return ret; } int uvc_mc_register_entities(struct uvc_video_chain *chain) diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 3906f6e..20107fd 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -305,6 +305,7 @@ struct uvc_entity { char name[64]; /* Media controller-related fields. */ + struct video_device *vdev; struct v4l2_subdev subdev; unsigned int num_pads; unsigned int num_links; |