diff options
| -rw-r--r-- | drivers/media/video/uvc/Makefile | 3 | ||||
| -rw-r--r-- | drivers/media/video/uvc/uvc_driver.c | 29 | ||||
| -rw-r--r-- | drivers/media/video/uvc/uvc_entity.c | 94 | ||||
| -rw-r--r-- | drivers/media/video/uvc/uvcvideo.h | 13 |
4 files changed, 136 insertions, 3 deletions
diff --git a/drivers/media/video/uvc/Makefile b/drivers/media/video/uvc/Makefile index 968c1994eda0..2071ca8a2f03 100644 --- a/drivers/media/video/uvc/Makefile +++ b/drivers/media/video/uvc/Makefile | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \ | 1 | uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \ |
| 2 | uvc_status.o uvc_isight.o | 2 | uvc_status.o uvc_isight.o |
| 3 | ifeq ($(CONFIG_MEDIA_CONTROLLER),y) | ||
| 4 | uvcvideo-objs += uvc_entity.o | ||
| 5 | endif | ||
| 3 | obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o | 6 | obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o |
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 0e8cd1fd870f..0bf3413e8d37 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
| @@ -248,7 +248,7 @@ uint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator) | |||
| 248 | * Terminal and unit management | 248 | * Terminal and unit management |
| 249 | */ | 249 | */ |
| 250 | 250 | ||
| 251 | static struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id) | 251 | struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id) |
| 252 | { | 252 | { |
| 253 | struct uvc_entity *entity; | 253 | struct uvc_entity *entity; |
| 254 | 254 | ||
| @@ -795,9 +795,12 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, | |||
| 795 | struct uvc_entity *entity; | 795 | struct uvc_entity *entity; |
| 796 | unsigned int num_inputs; | 796 | unsigned int num_inputs; |
| 797 | unsigned int size; | 797 | unsigned int size; |
| 798 | unsigned int i; | ||
| 798 | 799 | ||
| 800 | extra_size = ALIGN(extra_size, sizeof(*entity->pads)); | ||
| 799 | num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1; | 801 | num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1; |
| 800 | size = sizeof(*entity) + extra_size + num_inputs; | 802 | size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads |
| 803 | + num_inputs; | ||
| 801 | entity = kzalloc(size, GFP_KERNEL); | 804 | entity = kzalloc(size, GFP_KERNEL); |
| 802 | if (entity == NULL) | 805 | if (entity == NULL) |
| 803 | return NULL; | 806 | return NULL; |
| @@ -805,8 +808,17 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, | |||
| 805 | entity->id = id; | 808 | entity->id = id; |
| 806 | entity->type = type; | 809 | entity->type = type; |
| 807 | 810 | ||
| 811 | entity->num_links = 0; | ||
| 812 | entity->num_pads = num_pads; | ||
| 813 | entity->pads = ((void *)(entity + 1)) + extra_size; | ||
| 814 | |||
| 815 | for (i = 0; i < num_inputs; ++i) | ||
| 816 | entity->pads[i].flags = MEDIA_PAD_FL_SINK; | ||
| 817 | if (!UVC_ENTITY_IS_OTERM(entity)) | ||
| 818 | entity->pads[num_pads-1].flags = MEDIA_PAD_FL_SOURCE; | ||
| 819 | |||
| 808 | entity->bNrInPins = num_inputs; | 820 | entity->bNrInPins = num_inputs; |
| 809 | entity->baSourceID = ((__u8 *)entity) + sizeof(*entity) + extra_size; | 821 | entity->baSourceID = (__u8 *)(&entity->pads[num_pads]); |
| 810 | 822 | ||
| 811 | return entity; | 823 | return entity; |
| 812 | } | 824 | } |
| @@ -1601,6 +1613,9 @@ static void uvc_delete(struct uvc_device *dev) | |||
| 1601 | list_for_each_safe(p, n, &dev->entities) { | 1613 | list_for_each_safe(p, n, &dev->entities) { |
| 1602 | struct uvc_entity *entity; | 1614 | struct uvc_entity *entity; |
| 1603 | entity = list_entry(p, struct uvc_entity, list); | 1615 | entity = list_entry(p, struct uvc_entity, list); |
| 1616 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
| 1617 | uvc_mc_cleanup_entity(entity); | ||
| 1618 | #endif | ||
| 1604 | kfree(entity); | 1619 | kfree(entity); |
| 1605 | } | 1620 | } |
| 1606 | 1621 | ||
| @@ -1752,6 +1767,14 @@ static int uvc_register_chains(struct uvc_device *dev) | |||
| 1752 | ret = uvc_register_terms(dev, chain); | 1767 | ret = uvc_register_terms(dev, chain); |
| 1753 | if (ret < 0) | 1768 | if (ret < 0) |
| 1754 | return ret; | 1769 | return ret; |
| 1770 | |||
| 1771 | #ifdef CONFIG_MEDIA_CONTROLLER | ||
| 1772 | ret = uvc_mc_register_entities(chain); | ||
| 1773 | if (ret < 0) { | ||
| 1774 | uvc_printk(KERN_INFO, "Failed to register entites " | ||
| 1775 | "(%d).\n", ret); | ||
| 1776 | } | ||
| 1777 | #endif | ||
| 1755 | } | 1778 | } |
| 1756 | 1779 | ||
| 1757 | return 0; | 1780 | return 0; |
diff --git a/drivers/media/video/uvc/uvc_entity.c b/drivers/media/video/uvc/uvc_entity.c new file mode 100644 index 000000000000..8e8e7efb4608 --- /dev/null +++ b/drivers/media/video/uvc/uvc_entity.c | |||
| @@ -0,0 +1,94 @@ | |||
| 1 | /* | ||
| 2 | * uvc_entity.c -- USB Video Class driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005-2011 | ||
| 5 | * Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/list.h> | ||
| 16 | #include <linux/videodev2.h> | ||
| 17 | |||
| 18 | #include <media/v4l2-common.h> | ||
| 19 | |||
| 20 | #include "uvcvideo.h" | ||
| 21 | |||
| 22 | /* ------------------------------------------------------------------------ | ||
| 23 | * Video subdevices registration and unregistration | ||
| 24 | */ | ||
| 25 | |||
| 26 | static int uvc_mc_register_entity(struct uvc_video_chain *chain, | ||
| 27 | struct uvc_entity *entity) | ||
| 28 | { | ||
| 29 | const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE; | ||
| 30 | struct uvc_entity *remote; | ||
| 31 | unsigned int i; | ||
| 32 | u8 remote_pad; | ||
| 33 | int ret; | ||
| 34 | |||
| 35 | for (i = 0; i < entity->num_pads; ++i) { | ||
| 36 | if (!(entity->pads[i].flags & MEDIA_PAD_FL_SINK)) | ||
| 37 | continue; | ||
| 38 | |||
| 39 | remote = uvc_entity_by_id(chain->dev, entity->baSourceID[i]); | ||
| 40 | if (remote == NULL) | ||
| 41 | return -EINVAL; | ||
| 42 | |||
| 43 | remote_pad = remote->num_pads - 1; | ||
| 44 | ret = media_entity_create_link(&remote->subdev.entity, | ||
| 45 | remote_pad, &entity->subdev.entity, i, flags); | ||
| 46 | if (ret < 0) | ||
| 47 | return ret; | ||
| 48 | } | ||
| 49 | |||
| 50 | return v4l2_device_register_subdev(&chain->dev->vdev, &entity->subdev); | ||
| 51 | } | ||
| 52 | |||
| 53 | static struct v4l2_subdev_ops uvc_subdev_ops = { | ||
| 54 | }; | ||
| 55 | |||
| 56 | void uvc_mc_cleanup_entity(struct uvc_entity *entity) | ||
| 57 | { | ||
| 58 | media_entity_cleanup(&entity->subdev.entity); | ||
| 59 | } | ||
| 60 | |||
| 61 | static int uvc_mc_init_entity(struct uvc_entity *entity) | ||
| 62 | { | ||
| 63 | v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops); | ||
| 64 | strlcpy(entity->subdev.name, entity->name, sizeof(entity->subdev.name)); | ||
| 65 | |||
| 66 | return media_entity_init(&entity->subdev.entity, entity->num_pads, | ||
| 67 | entity->pads, 0); | ||
| 68 | } | ||
| 69 | |||
| 70 | int uvc_mc_register_entities(struct uvc_video_chain *chain) | ||
| 71 | { | ||
| 72 | struct uvc_entity *entity; | ||
| 73 | int ret; | ||
| 74 | |||
| 75 | list_for_each_entry(entity, &chain->entities, chain) { | ||
| 76 | ret = uvc_mc_init_entity(entity); | ||
| 77 | if (ret < 0) { | ||
| 78 | uvc_printk(KERN_INFO, "Failed to initialize entity for " | ||
| 79 | "entity %u\n", entity->id); | ||
| 80 | return ret; | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 84 | list_for_each_entry(entity, &chain->entities, chain) { | ||
| 85 | ret = uvc_mc_register_entity(chain, entity); | ||
| 86 | if (ret < 0) { | ||
| 87 | uvc_printk(KERN_INFO, "Failed to register entity for " | ||
| 88 | "entity %u\n", entity->id); | ||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | return 0; | ||
| 94 | } | ||
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index aab7508f2bd2..3906f6ed4061 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/ | |||
