diff options
| author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2010-01-21 06:56:19 -0500 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-05-25 18:51:09 -0400 |
| commit | 8a65a9485832f90e18e2f7069b75a4181e2840c0 (patch) | |
| tree | 151551e14937c7b1a2d28e738eed3ee154486497 | |
| parent | 4ffc2d89f38a7fbb3b24adb7fb066a159c351c11 (diff) | |
[media] uvcvideo: Connect video devices to media entities
The video devices associated to USB streaming terminals must be
connected to their associated terminal's media entity instead of being
standalone entities.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
| -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 0bf3413e8d37..b6eae48d7fb8 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) | |||
| 1616 | #ifdef CONFIG_MEDIA_CONTROLLER | 1616 | #ifdef CONFIG_MEDIA_CONTROLLER |
| 1617 | uvc_mc_cleanup_entity(entity); | 1617 | uvc_mc_cleanup_entity(entity); |
| 1618 | #endif | 1618 | #endif |
| 1619 | if (entity->vdev) { | ||
| 1620 | video_device_release(entity->vdev); | ||
| 1621 | entity->vdev = NULL; | ||
| 1622 | } | ||
| 1619 | kfree(entity); | 1623 | kfree(entity); |
| 1620 | } | 1624 | } |
| 1621 | 1625 | ||
| @@ -1638,8 +1642,6 @@ static void uvc_release(struct video_device *vdev) | |||
| 1638 | struct uvc_streaming *stream = video_get_drvdata(vdev); | 1642 | struct uvc_streaming *stream = video_get_drvdata(vdev); |
| 1639 | struct uvc_device *dev = stream->dev; | 1643 | struct uvc_device *dev = stream->dev; |
| 1640 | 1644 | ||
| 1641 | video_device_release(vdev); | ||
| 1642 | |||
| 1643 | /* Decrement the registered streams count and delete the device when it | 1645 | /* Decrement the registered streams count and delete the device when it |
| 1644 | * reaches zero. | 1646 | * reaches zero. |
| 1645 | */ | 1647 | */ |
| @@ -1753,6 +1755,8 @@ static int uvc_register_terms(struct uvc_device *dev, | |||
| 1753 | ret = uvc_register_video(dev, stream); | 1755 | ret = uvc_register_video(dev, stream); |
| 1754 | if (ret < 0) | 1756 | if (ret < 0) |
| 1755 | return ret; | 1757 | return ret; |
| 1758 | |||
| 1759 | term->vdev = stream->vdev; | ||
| 1756 | } | 1760 | } |
| 1757 | 1761 | ||
| 1758 | return 0; | 1762 | return 0; |
diff --git a/drivers/media/video/uvc/uvc_entity.c b/drivers/media/video/uvc/uvc_entity.c index 8e8e7efb4608..ede7852bb1df 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, | |||
| 33 | int ret; | 33 | int ret; |
| 34 | 34 | ||
| 35 | for (i = 0; i < entity->num_pads; ++i) { | 35 | for (i = 0; i < entity->num_pads; ++i) { |
| 36 | struct media_entity *source; | ||
| 37 | struct media_entity *sink; | ||
| 38 | |||
| 36 | if (!(entity->pads[i].flags & MEDIA_PAD_FL_SINK)) | 39 | if (!(entity->pads[i].flags & MEDIA_PAD_FL_SINK)) |
| 37 | continue; | 40 | continue; |
| 38 | 41 | ||
| @@ -40,14 +43,23 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain, | |||
| 40 | if (remote == NULL) | 43 | if (remote == NULL) |
| 41 | return -EINVAL; | 44 | return -EINVAL; |
| 42 | 45 | ||
| 46 | source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING) | ||
| 47 | ? &remote->vdev->entity : &remote->subdev.entity; | ||
| 48 | sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING) | ||
| 49 | ? &entity->vdev->entity : &entity->subdev.entity; | ||
| 50 | |||
| 43 | remote_pad = remote->num_pads - 1; | 51 | remote_pad = remote->num_pads - 1; |
| 44 | ret = media_entity_create_link(&remote->subdev.entity, | 52 | ret = media_entity_create_link(source, remote_pad, |
| 45 | remote_pad, &entity->subdev.entity, i, flags); | 53 | sink, i, flags); |
| 46 | if (ret < 0) | 54 | if (ret < 0) |
| 47 | return ret; | 55 | return ret; |
| 48 | } | 56 | } |
| 49 | 57 | ||
| 50 | return v4l2_device_register_subdev(&chain->dev->vdev, &entity->subdev); | 58 | if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) |
| 59 | ret = v4l2_device_register_subdev(&chain->dev->vdev, | ||
| 60 | &entity->subdev); | ||
| 61 | |||
| 62 | return ret; | ||
| 51 | } | 63 | } |
| 52 | 64 | ||
| 53 | static struct v4l2_subdev_ops uvc_subdev_ops = { | 65 | static struct v4l2_subdev_ops uvc_subdev_ops = { |
| @@ -55,16 +67,28 @@ static struct v4l2_subdev_ops uvc_subdev_ops = { | |||
| 55 | 67 | ||
| 56 | void uvc_mc_cleanup_entity(struct uvc_entity *entity) | 68 | void uvc_mc_cleanup_entity(struct uvc_entity *entity) |
| 57 | { | 69 | { |
| 58 | media_entity_cleanup(&entity->subdev.entity); | 70 | if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) |
| 71 | media_entity_cleanup(&entity->subdev.entity); | ||
| 72 | else if (entity->vdev != NULL) | ||
| 73 | media_entity_cleanup(&entity->vdev->entity); | ||
| 59 | } | 74 | } |
| 60 | 75 | ||
| 61 | static int uvc_mc_init_entity(struct uvc_entity *entity) | 76 | static int uvc_mc_init_entity(struct uvc_entity *entity) |
| 62 | { | 77 | { |
| 63 | v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops); | 78 | int ret; |
| 64 | strlcpy(entity->subdev.name, entity->name, sizeof(entity->subdev.name)); | 79 | |
| 80 | if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) { | ||
| 81 | v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops); | ||
| 82 | strlcpy(entity->subdev.name, entity->name, | ||
| 83 | sizeof(entity->subdev.name)); | ||
| 84 | |||
| 85 | ret = media_entity_init(&entity->subdev.entity, | ||
| 86 | entity->num_pads, entity->pads, 0); | ||
| 87 | } else | ||
| 88 | ret = media_entity_init(&entity->vdev->entity, | ||
| 89 | entity->num_pads, entity->pads, 0); | ||
| 65 | 90 | ||
| 66 | return media_entity_init(&entity->subdev.entity, entity->num_pads, | 91 | return ret; |
| 67 | entity->pads, 0); | ||
| 68 | } | 92 | } |
| 69 | 93 | ||
| 70 | int uvc_mc_register_entities(struct uvc_video_chain *chain) | 94 | 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 3906f6ed4061..20107fd3574d 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
| @@ -305,6 +305,7 @@ struct uvc_entity { | |||
| 305 | char name[64]; | 305 | char name[64]; |
| 306 | 306 | ||
| 307 | /* Media controller-related fields. */ | 307 | /* Media controller-related fields. */ |
| 308 | struct video_device *vdev; | ||
| 308 | struct v4l2_subdev subdev; | 309 | struct v4l2_subdev subdev; |
| 309 | unsigned int num_pads; | 310 | unsigned int num_pads; |
| 310 | unsigned int num_links; | 311 | unsigned int num_links; |
