diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2012-09-07 04:43:59 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-01-04 21:51:05 -0500 |
commit | 081b945ed74c9bd37da2ee928f9ad281222a6477 (patch) | |
tree | 4a63554ba3669ae9ce251ce2815285ad3976f591 | |
parent | 8ac7a9493a4380a8a886fbfe311ab00bc424ca0f (diff) |
[media] em28xx: convert to the control framework
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-cards.c | 24 | ||||
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-video.c | 248 | ||||
-rw-r--r-- | drivers/media/usb/em28xx/em28xx.h | 6 |
3 files changed, 53 insertions, 225 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index e17be073c0c3..1aca98f30a8d 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c | |||
@@ -2941,6 +2941,8 @@ void em28xx_release_resources(struct em28xx *dev) | |||
2941 | 2941 | ||
2942 | em28xx_i2c_unregister(dev); | 2942 | em28xx_i2c_unregister(dev); |
2943 | 2943 | ||
2944 | v4l2_ctrl_handler_free(&dev->ctrl_handler); | ||
2945 | |||
2944 | v4l2_device_unregister(&dev->v4l2_dev); | 2946 | v4l2_device_unregister(&dev->v4l2_dev); |
2945 | 2947 | ||
2946 | usb_put_dev(dev->udev); | 2948 | usb_put_dev(dev->udev); |
@@ -2957,6 +2959,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, | |||
2957 | struct usb_interface *interface, | 2959 | struct usb_interface *interface, |
2958 | int minor) | 2960 | int minor) |
2959 | { | 2961 | { |
2962 | struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler; | ||
2960 | int retval; | 2963 | int retval; |
2961 | static const char *default_chip_name = "em28xx"; | 2964 | static const char *default_chip_name = "em28xx"; |
2962 | const char *chip_name = default_chip_name; | 2965 | const char *chip_name = default_chip_name; |
@@ -3084,6 +3087,9 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, | |||
3084 | return retval; | 3087 | return retval; |
3085 | } | 3088 | } |
3086 | 3089 | ||
3090 | v4l2_ctrl_handler_init(hdl, 4); | ||
3091 | dev->v4l2_dev.ctrl_handler = hdl; | ||
3092 | |||
3087 | /* register i2c bus */ | 3093 | /* register i2c bus */ |
3088 | retval = em28xx_i2c_register(dev); | 3094 | retval = em28xx_i2c_register(dev); |
3089 | if (retval < 0) { | 3095 | if (retval < 0) { |
@@ -3109,6 +3115,18 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, | |||
3109 | __func__, retval); | 3115 | __func__, retval); |
3110 | goto fail; | 3116 | goto fail; |
3111 | } | 3117 | } |
3118 | if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { | ||
3119 | v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops, | ||
3120 | V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1); | ||
3121 | v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops, | ||
3122 | V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f); | ||
3123 | } else { | ||
3124 | /* install the em28xx notify callback */ | ||
3125 | v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_MUTE), | ||
3126 | em28xx_ctrl_notify, dev); | ||
3127 | v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_VOLUME), | ||
3128 | em28xx_ctrl_notify, dev); | ||
3129 | } | ||
3112 | 3130 | ||
3113 | /* wake i2c devices */ | 3131 | /* wake i2c devices */ |
3114 | em28xx_wake_i2c(dev); | 3132 | em28xx_wake_i2c(dev); |
@@ -3138,6 +3156,11 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, | |||
3138 | msleep(3); | 3156 | msleep(3); |
3139 | } | 3157 | } |
3140 | 3158 | ||
3159 | v4l2_ctrl_handler_setup(&dev->ctrl_handler); | ||
3160 | retval = dev->ctrl_handler.error; | ||
3161 | if (retval) | ||
3162 | goto fail; | ||
3163 | |||
3141 | retval = em28xx_register_analog_devices(dev); | 3164 | retval = em28xx_register_analog_devices(dev); |
3142 | if (retval < 0) { | 3165 | if (retval < 0) { |
3143 | goto fail; | 3166 | goto fail; |
@@ -3150,6 +3173,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, | |||
3150 | 3173 | ||
3151 | fail: | 3174 | fail: |
3152 | em28xx_i2c_unregister(dev); | 3175 | em28xx_i2c_unregister(dev); |
3176 | v4l2_ctrl_handler_free(&dev->ctrl_handler); | ||
3153 | 3177 | ||
3154 | unregister_dev: | 3178 | unregister_dev: |
3155 | v4l2_device_unregister(&dev->v4l2_dev); | 3179 | v4l2_device_unregister(&dev->v4l2_dev); |
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 89cbfaf17bda..ebbf775fcaba 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c | |||
@@ -125,30 +125,6 @@ static struct em28xx_fmt format[] = { | |||
125 | }, | 125 | }, |
126 | }; | 126 | }; |
127 | 127 | ||
128 | /* supported controls */ | ||
129 | /* Common to all boards */ | ||
130 | static struct v4l2_queryctrl ac97_qctrl[] = { | ||
131 | { | ||
132 | .id = V4L2_CID_AUDIO_VOLUME, | ||
133 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
134 | .name = "Volume", | ||
135 | .minimum = 0x0, | ||
136 | .maximum = 0x1f, | ||
137 | .step = 0x1, | ||
138 | .default_value = 0x1f, | ||
139 | .flags = V4L2_CTRL_FLAG_SLIDER, | ||
140 | }, { | ||
141 | .id = V4L2_CID_AUDIO_MUTE, | ||
142 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
143 | .name = "Mute", | ||
144 | .minimum = 0, | ||
145 | .maximum = 1, | ||
146 | .step = 1, | ||
147 | .default_value = 1, | ||
148 | .flags = 0, | ||
149 | } | ||
150 | }; | ||
151 | |||
152 | /* ------------------------------------------------------------------ | 128 | /* ------------------------------------------------------------------ |
153 | DMA and thread functions | 129 | DMA and thread functions |
154 | ------------------------------------------------------------------*/ | 130 | ------------------------------------------------------------------*/ |
@@ -718,76 +694,48 @@ static int get_ressource(struct em28xx_fh *fh) | |||
718 | } | 694 | } |
719 | } | 695 | } |
720 | 696 | ||
721 | /* | 697 | void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv) |
722 | * ac97_queryctrl() | ||
723 | * return the ac97 supported controls | ||
724 | */ | ||
725 | static int ac97_queryctrl(struct v4l2_queryctrl *qc) | ||
726 | { | 698 | { |
727 | int i; | 699 | struct em28xx *dev = priv; |
728 | |||
729 | for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) { | ||
730 | if (qc->id && qc->id == ac97_qctrl[i].id) { | ||
731 | memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc)); | ||
732 | return 0; | ||
733 | } | ||
734 | } | ||
735 | |||
736 | /* Control is not ac97 related */ | ||
737 | return 1; | ||
738 | } | ||
739 | 700 | ||
740 | /* | 701 | /* |
741 | * ac97_get_ctrl() | 702 | * In the case of non-AC97 volume controls, we still need |
742 | * return the current values for ac97 mute and volume | 703 | * to do some setups at em28xx, in order to mute/unmute |
743 | */ | 704 | * and to adjust audio volume. However, the value ranges |
744 | static int ac97_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl) | 705 | * should be checked by the corresponding V4L subdriver. |
745 | { | 706 | */ |
746 | switch (ctrl->id) { | 707 | switch (ctrl->id) { |
747 | case V4L2_CID_AUDIO_MUTE: | 708 | case V4L2_CID_AUDIO_MUTE: |
748 | ctrl->value = dev->mute; | 709 | dev->mute = ctrl->val; |
749 | return 0; | 710 | em28xx_audio_analog_set(dev); |
711 | break; | ||
750 | case V4L2_CID_AUDIO_VOLUME: | 712 | case V4L2_CID_AUDIO_VOLUME: |
751 | ctrl->value = dev->volume; | 713 | dev->volume = ctrl->val; |
752 | return 0; | 714 | em28xx_audio_analog_set(dev); |
753 | default: | 715 | break; |
754 | /* Control is not ac97 related */ | ||
755 | return 1; | ||
756 | } | 716 | } |
757 | } | 717 | } |
758 | 718 | ||
759 | /* | 719 | static int em28xx_s_ctrl(struct v4l2_ctrl *ctrl) |
760 | * ac97_set_ctrl() | ||
761 | * set values for ac97 mute and volume | ||
762 | */ | ||
763 | static int ac97_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) | ||
764 | { | 720 | { |
765 | int i; | 721 | struct em28xx *dev = container_of(ctrl->handler, struct em28xx, ctrl_handler); |
766 | |||
767 | for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) | ||
768 | if (ctrl->id == ac97_qctrl[i].id) | ||
769 | goto handle; | ||
770 | |||
771 | /* Announce that hasn't handle it */ | ||
772 | return 1; | ||
773 | |||
774 | handle: | ||
775 | if (ctrl->value < ac97_qctrl[i].minimum || | ||
776 | ctrl->value > ac97_qctrl[i].maximum) | ||
777 | return -ERANGE; | ||
778 | 722 | ||
779 | switch (ctrl->id) { | 723 | switch (ctrl->id) { |
780 | case V4L2_CID_AUDIO_MUTE: | 724 | case V4L2_CID_AUDIO_MUTE: |
781 | dev->mute = ctrl->value; | 725 | dev->mute = ctrl->val; |
782 | break; | 726 | break; |
783 | case V4L2_CID_AUDIO_VOLUME: | 727 | case V4L2_CID_AUDIO_VOLUME: |
784 | dev->volume = ctrl->value; | 728 | dev->volume = ctrl->val; |
785 | break; | 729 | break; |
786 | } | 730 | } |
787 | 731 | ||
788 | return em28xx_audio_analog_set(dev); | 732 | return em28xx_audio_analog_set(dev); |
789 | } | 733 | } |
790 | 734 | ||
735 | const struct v4l2_ctrl_ops em28xx_ctrl_ops = { | ||
736 | .s_ctrl = em28xx_s_ctrl, | ||
737 | }; | ||
738 | |||
791 | static int check_dev(struct em28xx *dev) | 739 | static int check_dev(struct em28xx *dev) |
792 | { | 740 | { |
793 | if (dev->state & DEV_DISCONNECTED) { | 741 | if (dev->state & DEV_DISCONNECTED) { |
@@ -1182,131 +1130,6 @@ static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio | |||
1182 | return 0; | 1130 | return 0; |
1183 | } | 1131 | } |
1184 | 1132 | ||
1185 | static int vidioc_queryctrl(struct file *file, void *priv, | ||
1186 | struct v4l2_queryctrl *qc) | ||
1187 | { | ||
1188 | struct em28xx_fh *fh = priv; | ||
1189 | struct em28xx *dev = fh->dev; | ||
1190 | int id = qc->id; | ||
1191 | int rc; | ||
1192 | |||
1193 | rc = check_dev(dev); | ||
1194 | if (rc < 0) | ||
1195 | return rc; | ||
1196 | |||
1197 | memset(qc, 0, sizeof(*qc)); | ||
1198 | |||
1199 | qc->id = id; | ||
1200 | |||
1201 | /* enumerate AC97 controls */ | ||
1202 | if (dev->audio_mode.ac97 != EM28XX_NO_AC97) { | ||
1203 | rc = ac97_queryctrl(qc); | ||
1204 | if (!rc) | ||
1205 | return 0; | ||
1206 | } | ||
1207 | |||
1208 | /* enumerate V4L2 device controls */ | ||
1209 | v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc); | ||
1210 | |||
1211 | if (qc->type) | ||
1212 | return 0; | ||
1213 | else | ||
1214 | return -EINVAL; | ||
1215 | } | ||
1216 | |||
1217 | /* | ||
1218 | * FIXME: This is an indirect way to check if a control exists at a | ||
1219 | * subdev. Instead of that hack, maybe the better would be to change all | ||
1220 | * subdevs to return -ENOIOCTLCMD, if an ioctl is not supported. | ||
1221 | */ | ||
1222 | static int check_subdev_ctrl(struct em28xx *dev, int id) | ||
1223 | { | ||
1224 | struct v4l2_queryctrl qc; | ||
1225 | |||
1226 | memset(&qc, 0, sizeof(qc)); | ||
1227 | qc.id = id; | ||
1228 | |||
1229 | /* enumerate V4L2 device controls */ | ||
1230 | v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, &qc); | ||
1231 | |||
1232 | if (qc.type) | ||
1233 | return 0; | ||
1234 | else | ||
1235 | return -EINVAL; | ||
1236 | } | ||
1237 | |||
1238 | static int vidioc_g_ctrl(struct file *file, void *priv, | ||
1239 | struct v4l2_control *ctrl) | ||
1240 | { | ||
1241 | struct em28xx_fh *fh = priv; | ||
1242 | struct em28xx *dev = fh->dev; | ||
1243 | int rc; | ||
1244 | |||
1245 | rc = check_dev(dev); | ||
1246 | if (rc < 0) | ||
1247 | return rc; | ||
1248 | rc = 0; | ||
1249 | |||
1250 | /* Set an AC97 control */ | ||
1251 | if (dev->audio_mode.ac97 != EM28XX_NO_AC97) | ||
1252 | rc = ac97_get_ctrl(dev, ctrl); | ||
1253 | else | ||
1254 | rc = 1; | ||
1255 | |||
1256 | /* It were not an AC97 control. Sends it to the v4l2 dev interface */ | ||
1257 | if (rc == 1) { | ||
1258 | if (check_subdev_ctrl(dev, ctrl->id)) | ||
1259 | return -EINVAL; | ||
1260 | |||
1261 | v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl); | ||
1262 | rc = 0; | ||
1263 | } | ||
1264 | |||
1265 | return rc; | ||
1266 | } | ||
1267 | |||
1268 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
1269 | struct v4l2_control *ctrl) | ||
1270 | { | ||
1271 | struct em28xx_fh *fh = priv; | ||
1272 | struct em28xx *dev = fh->dev; | ||
1273 | int rc; | ||
1274 | |||
1275 | rc = check_dev(dev); | ||
1276 | if (rc < 0) | ||
1277 | return rc; | ||
1278 | |||
1279 | /* Set an AC97 control */ | ||
1280 | if (dev->audio_mode.ac97 != EM28XX_NO_AC97) | ||
1281 | rc = ac97_set_ctrl(dev, ctrl); | ||
1282 | else | ||
1283 | rc = 1; | ||
1284 | |||
1285 | /* It isn't an AC97 control. Sends it to the v4l2 dev interface */ | ||
1286 | if (rc == 1) { | ||
1287 | rc = check_subdev_ctrl(dev, ctrl->id); | ||
1288 | if (!rc) | ||
1289 | v4l2_device_call_all(&dev->v4l2_dev, 0, | ||
1290 | core, s_ctrl, ctrl); | ||
1291 | /* | ||
1292 | * In the case of non-AC97 volume controls, we still need | ||
1293 | * to do some setups at em28xx, in order to mute/unmute | ||
1294 | * and to adjust audio volume. However, the value ranges | ||
1295 | * should be checked by the corresponding V4L subdriver. | ||
1296 | */ | ||
1297 | switch (ctrl->id) { | ||
1298 | case V4L2_CID_AUDIO_MUTE: | ||
1299 | dev->mute = ctrl->value; | ||
1300 | rc = em28xx_audio_analog_set(dev); | ||
1301 | break; | ||
1302 | case V4L2_CID_AUDIO_VOLUME: | ||
1303 | dev->volume = ctrl->value; | ||
1304 | rc = em28xx_audio_analog_set(dev); | ||
1305 | } | ||
1306 | } | ||
1307 | return (rc < 0) ? rc : 0; | ||
1308 | } | ||
1309 | |||
1310 | static int vidioc_g_tuner(struct file *file, void *priv, | 1133 | static int vidioc_g_tuner(struct file *file, void *priv, |
1311 | struct v4l2_tuner *t) | 1134 | struct v4l2_tuner *t) |
1312 | { | 1135 | { |
@@ -1874,25 +1697,6 @@ static int radio_s_tuner(struct file *file, void *priv, | |||
1874 | return 0; | 1697 | return 0; |
1875 | } | 1698 | } |
1876 | 1699 | ||
1877 | static int radio_queryctrl(struct file *file, void *priv, | ||
1878 | struct v4l2_queryctrl *qc) | ||
1879 | { | ||
1880 | int i; | ||
1881 | |||
1882 | if (qc->id < V4L2_CID_BASE || | ||
1883 | qc->id >= V4L2_CID_LASTP1) | ||
1884 | return -EINVAL; | ||
1885 | |||
1886 | for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) { | ||
1887 | if (qc->id && qc->id == ac97_qctrl[i].id) { | ||
1888 | memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc)); | ||
1889 | return 0; | ||
1890 | } | ||
1891 | } | ||
1892 | |||
1893 | return -EINVAL; | ||
1894 | } | ||
1895 | |||
1896 | /* | 1700 | /* |
1897 | * em28xx_v4l2_open() | 1701 | * em28xx_v4l2_open() |
1898 | * inits the device and starts isoc transfer | 1702 | * inits the device and starts isoc transfer |
@@ -2218,9 +2022,6 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
2218 | .vidioc_enum_input = vidioc_enum_input, | 2022 | .vidioc_enum_input = vidioc_enum_input, |
2219 | .vidioc_g_input = vidioc_g_input, | 2023 | .vidioc_g_input = vidioc_g_input, |
2220 | .vidioc_s_input = vidioc_s_input, | 2024 | .vidioc_s_input = vidioc_s_input, |
2221 | .vidioc_queryctrl = vidioc_queryctrl, | ||
2222 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
2223 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
2224 | .vidioc_streamon = vidioc_streamon, | 2025 | .vidioc_streamon = vidioc_streamon, |
2225 | .vidioc_streamoff = vidioc_streamoff, | 2026 | .vidioc_streamoff = vidioc_streamoff, |
2226 | .vidioc_g_tuner = vidioc_g_tuner, | 2027 | .vidioc_g_tuner = vidioc_g_tuner, |
@@ -2254,9 +2055,6 @@ static const struct v4l2_ioctl_ops radio_ioctl_ops = { | |||
2254 | .vidioc_querycap = vidioc_querycap, | 2055 | .vidioc_querycap = vidioc_querycap, |
2255 | .vidioc_g_tuner = radio_g_tuner, | 2056 | .vidioc_g_tuner = radio_g_tuner, |
2256 | .vidioc_s_tuner = radio_s_tuner, | 2057 | .vidioc_s_tuner = radio_s_tuner, |
2257 | .vidioc_queryctrl = radio_queryctrl, | ||
2258 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
2259 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
2260 | .vidioc_g_frequency = vidioc_g_frequency, | 2058 | .vidioc_g_frequency = vidioc_g_frequency, |
2261 | .vidioc_s_frequency = vidioc_s_frequency, | 2059 | .vidioc_s_frequency = vidioc_s_frequency, |
2262 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 2060 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
@@ -2300,7 +2098,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, | |||
2300 | 2098 | ||
2301 | int em28xx_register_analog_devices(struct em28xx *dev) | 2099 | int em28xx_register_analog_devices(struct em28xx *dev) |
2302 | { | 2100 | { |
2303 | u8 val; | 2101 | u8 val; |
2304 | int ret; | 2102 | int ret; |
2305 | unsigned int maxw; | 2103 | unsigned int maxw; |
2306 | 2104 | ||
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 062841e50722..707319eabe2d 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h | |||
@@ -33,6 +33,7 @@ | |||
33 | 33 | ||
34 | #include <media/videobuf-vmalloc.h> | 34 | #include <media/videobuf-vmalloc.h> |
35 | #include <media/v4l2-device.h> | 35 | #include <media/v4l2-device.h> |
36 | #include <media/v4l2-ctrls.h> | ||
36 | #include <media/ir-kbd-i2c.h> | 37 | #include <media/ir-kbd-i2c.h> |
37 | #include <media/rc-core.h> | 38 | #include <media/rc-core.h> |
38 | #if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) | 39 | #if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE) |
@@ -497,6 +498,9 @@ struct em28xx { | |||
497 | int audio_ifnum; | 498 | int audio_ifnum; |
498 | 499 | ||
499 | struct v4l2_device v4l2_dev; | 500 | struct v4l2_device v4l2_dev; |
501 | struct v4l2_ctrl_handler ctrl_handler; | ||
502 | /* provides ac97 mute and volume overrides */ | ||
503 | struct v4l2_ctrl_handler ac97_ctrl_handler; | ||
500 | struct em28xx_board board; | 504 | struct em28xx_board board; |
501 | 505 | ||
502 | /* Webcam specific fields */ | 506 | /* Webcam specific fields */ |
@@ -705,6 +709,8 @@ void em28xx_close_extension(struct em28xx *dev); | |||
705 | /* Provided by em28xx-video.c */ | 709 | /* Provided by em28xx-video.c */ |
706 | int em28xx_register_analog_devices(struct em28xx *dev); | 710 | int em28xx_register_analog_devices(struct em28xx *dev); |
707 | void em28xx_release_analog_resources(struct em28xx *dev); | 711 | void em28xx_release_analog_resources(struct em28xx *dev); |
712 | void em28xx_ctrl_notify(struct v4l2_ctrl *ctrl, void *priv); | ||
713 | extern const struct v4l2_ctrl_ops em28xx_ctrl_ops; | ||
708 | 714 | ||
709 | /* Provided by em28xx-cards.c */ | 715 | /* Provided by em28xx-cards.c */ |
710 | extern int em2800_variant_detect(struct usb_device *udev, int model); | 716 | extern int em2800_variant_detect(struct usb_device *udev, int model); |