diff options
Diffstat (limited to 'drivers/media/video')
113 files changed, 8141 insertions, 958 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index fe743aa7f645..5ccb0aeca8cc 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -44,6 +44,10 @@ config VIDEO_TVEEPROM | |||
44 | tristate | 44 | tristate |
45 | depends on I2C | 45 | depends on I2C |
46 | 46 | ||
47 | config VIDEO_TUNER | ||
48 | tristate | ||
49 | depends on MEDIA_TUNER | ||
50 | |||
47 | # | 51 | # |
48 | # Multimedia Video device configuration | 52 | # Multimedia Video device configuration |
49 | # | 53 | # |
@@ -690,7 +694,7 @@ config VIDEO_MXB | |||
690 | tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" | 694 | tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" |
691 | depends on PCI && VIDEO_V4L1 && I2C | 695 | depends on PCI && VIDEO_V4L1 && I2C |
692 | select VIDEO_SAA7146_VV | 696 | select VIDEO_SAA7146_VV |
693 | select MEDIA_TUNER | 697 | select VIDEO_TUNER |
694 | select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO | 698 | select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO |
695 | select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO | 699 | select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO |
696 | select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO | 700 | select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO |
@@ -789,6 +793,14 @@ menuconfig V4L_USB_DRIVERS | |||
789 | 793 | ||
790 | if V4L_USB_DRIVERS && USB | 794 | if V4L_USB_DRIVERS && USB |
791 | 795 | ||
796 | config USB_VIDEO_CLASS | ||
797 | tristate "USB Video Class (UVC)" | ||
798 | ---help--- | ||
799 | Support for the USB Video Class (UVC). Currently only video | ||
800 | input devices, such as webcams, are supported. | ||
801 | |||
802 | For more information see: <http://linux-uvc.berlios.de/> | ||
803 | |||
792 | source "drivers/media/video/pvrusb2/Kconfig" | 804 | source "drivers/media/video/pvrusb2/Kconfig" |
793 | 805 | ||
794 | source "drivers/media/video/em28xx/Kconfig" | 806 | source "drivers/media/video/em28xx/Kconfig" |
@@ -897,7 +909,7 @@ endif # V4L_USB_DRIVERS | |||
897 | 909 | ||
898 | config SOC_CAMERA | 910 | config SOC_CAMERA |
899 | tristate "SoC camera support" | 911 | tristate "SoC camera support" |
900 | depends on VIDEO_V4L2 | 912 | depends on VIDEO_V4L2 && HAS_DMA |
901 | select VIDEOBUF_DMA_SG | 913 | select VIDEOBUF_DMA_SG |
902 | help | 914 | help |
903 | SoC Camera is a common API to several cameras, not connecting | 915 | SoC Camera is a common API to several cameras, not connecting |
@@ -906,7 +918,7 @@ config SOC_CAMERA | |||
906 | 918 | ||
907 | config SOC_CAMERA_MT9M001 | 919 | config SOC_CAMERA_MT9M001 |
908 | tristate "mt9m001 support" | 920 | tristate "mt9m001 support" |
909 | depends on SOC_CAMERA | 921 | depends on SOC_CAMERA && I2C |
910 | select GPIO_PCA953X if MT9M001_PCA9536_SWITCH | 922 | select GPIO_PCA953X if MT9M001_PCA9536_SWITCH |
911 | help | 923 | help |
912 | This driver supports MT9M001 cameras from Micron, monochrome | 924 | This driver supports MT9M001 cameras from Micron, monochrome |
@@ -921,7 +933,7 @@ config MT9M001_PCA9536_SWITCH | |||
921 | 933 | ||
922 | config SOC_CAMERA_MT9V022 | 934 | config SOC_CAMERA_MT9V022 |
923 | tristate "mt9v022 support" | 935 | tristate "mt9v022 support" |
924 | depends on SOC_CAMERA | 936 | depends on SOC_CAMERA && I2C |
925 | select GPIO_PCA953X if MT9V022_PCA9536_SWITCH | 937 | select GPIO_PCA953X if MT9V022_PCA9536_SWITCH |
926 | help | 938 | help |
927 | This driver supports MT9V022 cameras from Micron | 939 | This driver supports MT9V022 cameras from Micron |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index a352c6e31f0c..ecbbfaab24d5 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -84,7 +84,7 @@ obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o | |||
84 | obj-$(CONFIG_VIDEO_DPC) += dpc7146.o | 84 | obj-$(CONFIG_VIDEO_DPC) += dpc7146.o |
85 | obj-$(CONFIG_TUNER_3036) += tuner-3036.o | 85 | obj-$(CONFIG_TUNER_3036) += tuner-3036.o |
86 | 86 | ||
87 | obj-$(CONFIG_MEDIA_TUNER) += tuner.o | 87 | obj-$(CONFIG_VIDEO_TUNER) += tuner.o |
88 | 88 | ||
89 | obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o | 89 | obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o |
90 | obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o | 90 | obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o |
@@ -136,6 +136,8 @@ obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o | |||
136 | 136 | ||
137 | obj-$(CONFIG_VIDEO_AU0828) += au0828/ | 137 | obj-$(CONFIG_VIDEO_AU0828) += au0828/ |
138 | 138 | ||
139 | obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ | ||
140 | |||
139 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | 141 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core |
140 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | 142 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends |
141 | EXTRA_CFLAGS += -Idrivers/media/common/tuners | 143 | EXTRA_CFLAGS += -Idrivers/media/common/tuners |
diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig index cab277fafa63..52b2491581a8 100644 --- a/drivers/media/video/au0828/Kconfig +++ b/drivers/media/video/au0828/Kconfig | |||
@@ -1,8 +1,9 @@ | |||
1 | 1 | ||
2 | config VIDEO_AU0828 | 2 | config VIDEO_AU0828 |
3 | tristate "Auvitek AU0828 support" | 3 | tristate "Auvitek AU0828 support" |
4 | depends on VIDEO_DEV && I2C && INPUT && DVB_CORE | 4 | depends on I2C && INPUT && DVB_CORE && USB |
5 | select I2C_ALGOBIT | 5 | select I2C_ALGOBIT |
6 | select VIDEO_TVEEPROM | ||
6 | select DVB_AU8522 if !DVB_FE_CUSTOMIZE | 7 | select DVB_AU8522 if !DVB_FE_CUSTOMIZE |
7 | select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE | 8 | select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE |
8 | ---help--- | 9 | ---help--- |
diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index a2a6983444fa..898e12395e7c 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c | |||
@@ -77,8 +77,14 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) | |||
77 | 77 | ||
78 | /* Make sure we support the board model */ | 78 | /* Make sure we support the board model */ |
79 | switch (tv.model) { | 79 | switch (tv.model) { |
80 | case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */ | ||
80 | case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */ | 81 | case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */ |
82 | case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ | ||
83 | case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ | ||
84 | case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ | ||
85 | case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and basic analog video */ | ||
81 | case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */ | 86 | case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */ |
87 | case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */ | ||
82 | break; | 88 | break; |
83 | default: | 89 | default: |
84 | printk(KERN_WARNING "%s: warning: " | 90 | printk(KERN_WARNING "%s: warning: " |
@@ -175,6 +181,18 @@ struct usb_device_id au0828_usb_id_table [] = { | |||
175 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 }, | 181 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 }, |
176 | { USB_DEVICE(0x0fe9, 0xd620), | 182 | { USB_DEVICE(0x0fe9, 0xd620), |
177 | .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 }, | 183 | .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 }, |
184 | { USB_DEVICE(0x2040, 0x7210), | ||
185 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, | ||
186 | { USB_DEVICE(0x2040, 0x7217), | ||
187 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, | ||
188 | { USB_DEVICE(0x2040, 0x721b), | ||
189 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, | ||
190 | { USB_DEVICE(0x2040, 0x721f), | ||
191 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, | ||
192 | { USB_DEVICE(0x2040, 0x7280), | ||
193 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, | ||
194 | { USB_DEVICE(0x0fd9, 0x0008), | ||
195 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, | ||
178 | { }, | 196 | { }, |
179 | }; | 197 | }; |
180 | 198 | ||
diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index 1371b4e4b5f1..c6d470590380 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c | |||
@@ -337,12 +337,10 @@ int au0828_dvb_register(struct au0828_dev *dev) | |||
337 | dvb->frontend = dvb_attach(au8522_attach, | 337 | dvb->frontend = dvb_attach(au8522_attach, |
338 | &hauppauge_hvr950q_config, | 338 | &hauppauge_hvr950q_config, |
339 | &dev->i2c_adap); | 339 | &dev->i2c_adap); |
340 | if (dvb->frontend != NULL) { | 340 | if (dvb->frontend != NULL) |
341 | hauppauge_hvr950q_tunerconfig.priv = dev; | ||
342 | dvb_attach(xc5000_attach, dvb->frontend, | 341 | dvb_attach(xc5000_attach, dvb->frontend, |
343 | &dev->i2c_adap, | 342 | &dev->i2c_adap, |
344 | &hauppauge_hvr950q_tunerconfig); | 343 | &hauppauge_hvr950q_tunerconfig, dev); |
345 | } | ||
346 | break; | 344 | break; |
347 | default: | 345 | default: |
348 | printk(KERN_WARNING "The frontend of your DVB/ATSC card " | 346 | printk(KERN_WARNING "The frontend of your DVB/ATSC card " |
@@ -355,12 +353,6 @@ int au0828_dvb_register(struct au0828_dev *dev) | |||
355 | return -1; | 353 | return -1; |
356 | } | 354 | } |
357 | 355 | ||
358 | /* Put the analog decoder in standby to keep it quiet */ | ||
359 | au0828_call_i2c_clients(dev, TUNER_SET_STANDBY, NULL); | ||
360 | |||
361 | if (dvb->frontend->ops.analog_ops.standby) | ||
362 | dvb->frontend->ops.analog_ops.standby(dvb->frontend); | ||
363 | |||
364 | /* register everything */ | 356 | /* register everything */ |
365 | ret = dvb_register(dev); | 357 | ret = dvb_register(dev); |
366 | if (ret < 0) { | 358 | if (ret < 0) { |
diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig index 7431ef6de9f1..24a34fc1f2b3 100644 --- a/drivers/media/video/bt8xx/Kconfig +++ b/drivers/media/video/bt8xx/Kconfig | |||
@@ -1,12 +1,13 @@ | |||
1 | config VIDEO_BT848 | 1 | config VIDEO_BT848 |
2 | tristate "BT848 Video For Linux" | 2 | tristate "BT848 Video For Linux" |
3 | depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 && INPUT | 3 | depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 && INPUT |
4 | depends on HOTPLUG # due to FW_LOADER | ||
4 | select I2C_ALGOBIT | 5 | select I2C_ALGOBIT |
5 | select FW_LOADER | 6 | select FW_LOADER |
6 | select VIDEO_BTCX | 7 | select VIDEO_BTCX |
7 | select VIDEOBUF_DMA_SG | 8 | select VIDEOBUF_DMA_SG |
8 | select VIDEO_IR | 9 | select VIDEO_IR |
9 | select MEDIA_TUNER | 10 | select VIDEO_TUNER |
10 | select VIDEO_TVEEPROM | 11 | select VIDEO_TVEEPROM |
11 | select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO | 12 | select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO |
12 | select VIDEO_TVAUDIO if VIDEO_HELPER_CHIPS_AUTO | 13 | select VIDEO_TVAUDIO if VIDEO_HELPER_CHIPS_AUTO |
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index f20a01cfc73e..8ef0424c26c4 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/firmware.h> | 34 | #include <linux/firmware.h> |
35 | #include <net/checksum.h> | 35 | #include <net/checksum.h> |
36 | 36 | ||
37 | #include <asm/unaligned.h> | ||
37 | #include <asm/io.h> | 38 | #include <asm/io.h> |
38 | 39 | ||
39 | #include "bttvp.h" | 40 | #include "bttvp.h" |
@@ -3858,7 +3859,7 @@ static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256]) | |||
3858 | ee += i; | 3859 | ee += i; |
3859 | 3860 | ||
3860 | /* found a valid descriptor */ | 3861 | /* found a valid descriptor */ |
3861 | type = be16_to_cpup((u16*)(ee+4)); | 3862 | type = get_unaligned_be16((__be16 *)(ee+4)); |
3862 | 3863 | ||
3863 | switch(type) { | 3864 | switch(type) { |
3864 | /* 848 based */ | 3865 | /* 848 based */ |
@@ -3918,7 +3919,7 @@ static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256]) | |||
3918 | btv->c.nr, type); | 3919 | btv->c.nr, type); |
3919 | break; | 3920 | break; |
3920 | } | 3921 | } |
3921 | serial = be32_to_cpup((u32*)(ee+6)); | 3922 | serial = get_unaligned_be32((__be32 *)(ee+6)); |
3922 | } | 3923 | } |
3923 | 3924 | ||
3924 | printk(KERN_INFO "bttv%d: osprey eeprom: card=%d '%s' serial=%u\n", | 3925 | printk(KERN_INFO "bttv%d: osprey eeprom: card=%d '%s' serial=%u\n", |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 2ca3e9cfb2bb..0165aac533bf 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -2613,7 +2613,7 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) | |||
2613 | struct bttv_fh *fh = priv; | 2613 | struct bttv_fh *fh = priv; |
2614 | 2614 | ||
2615 | mutex_lock(&fh->cap.vb_lock); | 2615 | mutex_lock(&fh->cap.vb_lock); |
2616 | retval = videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize, | 2616 | retval = __videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize, |
2617 | V4L2_MEMORY_MMAP); | 2617 | V4L2_MEMORY_MMAP); |
2618 | if (retval < 0) { | 2618 | if (retval < 0) { |
2619 | mutex_unlock(&fh->cap.vb_lock); | 2619 | mutex_unlock(&fh->cap.vb_lock); |
diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c index e5979f77504c..0af586876e72 100644 --- a/drivers/media/video/bt8xx/bttv-risc.c +++ b/drivers/media/video/bt8xx/bttv-risc.c | |||
@@ -48,7 +48,7 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, | |||
48 | { | 48 | { |
49 | u32 instructions,line,todo; | 49 | u32 instructions,line,todo; |
50 | struct scatterlist *sg; | 50 | struct scatterlist *sg; |
51 | u32 *rp; | 51 | __le32 *rp; |
52 | int rc; | 52 | int rc; |
53 | 53 | ||
54 | /* estimate risc mem: worst case is one write per page border + | 54 | /* estimate risc mem: worst case is one write per page border + |
@@ -128,7 +128,8 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc, | |||
128 | unsigned int cpadding) | 128 | unsigned int cpadding) |
129 | { | 129 | { |
130 | unsigned int instructions,line,todo,ylen,chroma; | 130 | unsigned int instructions,line,todo,ylen,chroma; |
131 | u32 *rp,ri; | 131 | __le32 *rp; |
132 | u32 ri; | ||
132 | struct scatterlist *ysg; | 133 | struct scatterlist *ysg; |
133 | struct scatterlist *usg; | 134 | struct scatterlist *usg; |
134 | struct scatterlist *vsg; | 135 | struct scatterlist *vsg; |
@@ -244,7 +245,8 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, | |||
244 | { | 245 | { |
245 | int dwords,rc,line,maxy,start,end,skip,nskips; | 246 | int dwords,rc,line,maxy,start,end,skip,nskips; |
246 | struct btcx_skiplist *skips; | 247 | struct btcx_skiplist *skips; |
247 | u32 *rp,ri,ra; | 248 | __le32 *rp; |
249 | u32 ri,ra; | ||
248 | u32 addr; | 250 | u32 addr; |
249 | 251 | ||
250 | /* skip list for window clipping */ | 252 | /* skip list for window clipping */ |
diff --git a/drivers/media/video/btcx-risc.c b/drivers/media/video/btcx-risc.c index ce0840ccd594..f42701f82e7f 100644 --- a/drivers/media/video/btcx-risc.c +++ b/drivers/media/video/btcx-risc.c | |||
@@ -63,7 +63,7 @@ int btcx_riscmem_alloc(struct pci_dev *pci, | |||
63 | struct btcx_riscmem *risc, | 63 | struct btcx_riscmem *risc, |
64 | unsigned int size) | 64 | unsigned int size) |
65 | { | 65 | { |
66 | u32 *cpu; | 66 | __le32 *cpu; |
67 | dma_addr_t dma; | 67 | dma_addr_t dma; |
68 | 68 | ||
69 | if (NULL != risc->cpu && risc->size < size) | 69 | if (NULL != risc->cpu && risc->size < size) |
diff --git a/drivers/media/video/btcx-risc.h b/drivers/media/video/btcx-risc.h index 503e6c6d7b69..861bc8112824 100644 --- a/drivers/media/video/btcx-risc.h +++ b/drivers/media/video/btcx-risc.h | |||
@@ -2,8 +2,8 @@ | |||
2 | */ | 2 | */ |
3 | struct btcx_riscmem { | 3 | struct btcx_riscmem { |
4 | unsigned int size; | 4 | unsigned int size; |
5 | u32 *cpu; | 5 | __le32 *cpu; |
6 | u32 *jmp; | 6 | __le32 *jmp; |
7 | dma_addr_t dma; | 7 | dma_addr_t dma; |
8 | }; | 8 | }; |
9 | 9 | ||
diff --git a/drivers/media/video/cs5345.c b/drivers/media/video/cs5345.c index 2a429f9e32cd..03411503457e 100644 --- a/drivers/media/video/cs5345.c +++ b/drivers/media/video/cs5345.c | |||
@@ -160,10 +160,17 @@ static int cs5345_probe(struct i2c_client *client, | |||
160 | 160 | ||
161 | /* ----------------------------------------------------------------------- */ | 161 | /* ----------------------------------------------------------------------- */ |
162 | 162 | ||
163 | static const struct i2c_device_id cs5345_id[] = { | ||
164 | { "cs5345", 0 }, | ||
165 | { } | ||
166 | }; | ||
167 | MODULE_DEVICE_TABLE(i2c, cs5345_id); | ||
168 | |||
163 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 169 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
164 | .name = "cs5345", | 170 | .name = "cs5345", |
165 | .driverid = I2C_DRIVERID_CS5345, | 171 | .driverid = I2C_DRIVERID_CS5345, |
166 | .command = cs5345_command, | 172 | .command = cs5345_command, |
167 | .probe = cs5345_probe, | 173 | .probe = cs5345_probe, |
174 | .id_table = cs5345_id, | ||
168 | }; | 175 | }; |
169 | 176 | ||
diff --git a/drivers/media/video/cs53l32a.c b/drivers/media/video/cs53l32a.c index 2dfd0afc62db..d965af860ab2 100644 --- a/drivers/media/video/cs53l32a.c +++ b/drivers/media/video/cs53l32a.c | |||
@@ -144,7 +144,8 @@ static int cs53l32a_probe(struct i2c_client *client, | |||
144 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 144 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
145 | return -EIO; | 145 | return -EIO; |
146 | 146 | ||
147 | snprintf(client->name, sizeof(client->name) - 1, "cs53l32a"); | 147 | if (!id) |
148 | strlcpy(client->name, "cs53l32a", sizeof(client->name)); | ||
148 | 149 | ||
149 | v4l_info(client, "chip found @ 0x%x (%s)\n", | 150 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
150 | client->addr << 1, client->adapter->name); | 151 | client->addr << 1, client->adapter->name); |
@@ -175,10 +176,17 @@ static int cs53l32a_probe(struct i2c_client *client, | |||
175 | return 0; | 176 | return 0; |
176 | } | 177 | } |
177 | 178 | ||
179 | static const struct i2c_device_id cs53l32a_id[] = { | ||
180 | { "cs53l32a", 0 }, | ||
181 | { } | ||
182 | }; | ||
183 | MODULE_DEVICE_TABLE(i2c, cs53l32a_id); | ||
184 | |||
178 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 185 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
179 | .name = "cs53l32a", | 186 | .name = "cs53l32a", |
180 | .driverid = I2C_DRIVERID_CS53L32A, | 187 | .driverid = I2C_DRIVERID_CS53L32A, |
181 | .command = cs53l32a_command, | 188 | .command = cs53l32a_command, |
182 | .probe = cs53l32a_probe, | 189 | .probe = cs53l32a_probe, |
190 | .id_table = cs53l32a_id, | ||
183 | }; | 191 | }; |
184 | 192 | ||
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig index acc4b47f1d1d..9aefdc5ea79a 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/video/cx18/Kconfig | |||
@@ -1,14 +1,17 @@ | |||
1 | config VIDEO_CX18 | 1 | config VIDEO_CX18 |
2 | tristate "Conexant cx23418 MPEG encoder support" | 2 | tristate "Conexant cx23418 MPEG encoder support" |
3 | depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL | 3 | depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL |
4 | depends on INPUT # due to VIDEO_IR | ||
5 | depends on HOTPLUG # due to FW_LOADER | ||
4 | select I2C_ALGOBIT | 6 | select I2C_ALGOBIT |
5 | select FW_LOADER | 7 | select FW_LOADER |
6 | select VIDEO_IR | 8 | select VIDEO_IR |
7 | select MEDIA_TUNER | 9 | select VIDEO_TUNER |
8 | select VIDEO_TVEEPROM | 10 | select VIDEO_TVEEPROM |
9 | select VIDEO_CX2341X | 11 | select VIDEO_CX2341X |
10 | select VIDEO_CS5345 | 12 | select VIDEO_CS5345 |
11 | select DVB_S5H1409 | 13 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE |
14 | select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE | ||
12 | ---help--- | 15 | ---help--- |
13 | This is a video4linux driver for Conexant cx23418 based | 16 | This is a video4linux driver for Conexant cx23418 based |
14 | PCI combo video recorder devices. | 17 | PCI combo video recorder devices. |
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 66864904c99b..faca43eb940f 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c | |||
@@ -69,6 +69,58 @@ int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask, | |||
69 | or_value); | 69 | or_value); |
70 | } | 70 | } |
71 | 71 | ||
72 | int cx18_av_write_no_acfg(struct cx18 *cx, u16 addr, u8 value, int no_acfg_mask) | ||
73 | { | ||
74 | int retval; | ||
75 | u32 saved_reg[8] = {0}; | ||
76 | |||
77 | if (no_acfg_mask & CXADEC_NO_ACFG_AFE) { | ||
78 | saved_reg[0] = cx18_av_read4(cx, CXADEC_CHIP_CTRL); | ||
79 | saved_reg[1] = cx18_av_read4(cx, CXADEC_AFE_CTRL); | ||
80 | } | ||
81 | |||
82 | if (no_acfg_mask & CXADEC_NO_ACFG_PLL) { | ||
83 | saved_reg[2] = cx18_av_read4(cx, CXADEC_PLL_CTRL1); | ||
84 | saved_reg[3] = cx18_av_read4(cx, CXADEC_VID_PLL_FRAC); | ||
85 | } | ||
86 | |||
87 | if (no_acfg_mask & CXADEC_NO_ACFG_VID) { | ||
88 | saved_reg[4] = cx18_av_read4(cx, CXADEC_HORIZ_TIM_CTRL); | ||
89 | saved_reg[5] = cx18_av_read4(cx, CXADEC_VERT_TIM_CTRL); | ||
90 | saved_reg[6] = cx18_av_read4(cx, CXADEC_SRC_COMB_CFG); | ||
91 | saved_reg[7] = cx18_av_read4(cx, CXADEC_CHROMA_VBIOFF_CFG); | ||
92 | } | ||
93 | |||
94 | retval = cx18_av_write(cx, addr, value); | ||
95 | |||
96 | if (no_acfg_mask & CXADEC_NO_ACFG_AFE) { | ||
97 | cx18_av_write4(cx, CXADEC_CHIP_CTRL, saved_reg[0]); | ||
98 | cx18_av_write4(cx, CXADEC_AFE_CTRL, saved_reg[1]); | ||
99 | } | ||
100 | |||
101 | if (no_acfg_mask & CXADEC_NO_ACFG_PLL) { | ||
102 | cx18_av_write4(cx, CXADEC_PLL_CTRL1, saved_reg[2]); | ||
103 | cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, saved_reg[3]); | ||
104 | } | ||
105 | |||
106 | if (no_acfg_mask & CXADEC_NO_ACFG_VID) { | ||
107 | cx18_av_write4(cx, CXADEC_HORIZ_TIM_CTRL, saved_reg[4]); | ||
108 | cx18_av_write4(cx, CXADEC_VERT_TIM_CTRL, saved_reg[5]); | ||
109 | cx18_av_write4(cx, CXADEC_SRC_COMB_CFG, saved_reg[6]); | ||
110 | cx18_av_write4(cx, CXADEC_CHROMA_VBIOFF_CFG, saved_reg[7]); | ||
111 | } | ||
112 | |||
113 | return retval; | ||
114 | } | ||
115 | |||
116 | int cx18_av_and_or_no_acfg(struct cx18 *cx, u16 addr, unsigned and_mask, | ||
117 | u8 or_value, int no_acfg_mask) | ||
118 | { | ||
119 | return cx18_av_write_no_acfg(cx, addr, | ||
120 | (cx18_av_read(cx, addr) & and_mask) | | ||
121 | or_value, no_acfg_mask); | ||
122 | } | ||
123 | |||
72 | /* ----------------------------------------------------------------------- */ | 124 | /* ----------------------------------------------------------------------- */ |
73 | 125 | ||
74 | static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, | 126 | static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, |
@@ -170,26 +222,30 @@ static void input_change(struct cx18 *cx) | |||
170 | 222 | ||
171 | /* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */ | 223 | /* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */ |
172 | if (std & V4L2_STD_SECAM) | 224 | if (std & V4L2_STD_SECAM) |
173 | cx18_av_write(cx, 0x402, 0); | 225 | cx18_av_write_no_acfg(cx, 0x402, 0, CXADEC_NO_ACFG_ALL); |
174 | else { | 226 | else { |
175 | cx18_av_write(cx, 0x402, 0x04); | 227 | cx18_av_write_no_acfg(cx, 0x402, 0x04, CXADEC_NO_ACFG_ALL); |
176 | cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11); | 228 | cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11); |
177 | } | 229 | } |
178 | cx18_av_and_or(cx, 0x401, ~0x60, 0); | 230 | cx18_av_and_or_no_acfg(cx, 0x401, ~0x60, 0, |
179 | cx18_av_and_or(cx, 0x401, ~0x60, 0x60); | 231 | CXADEC_NO_ACFG_PLL | CXADEC_NO_ACFG_VID); |
232 | cx18_av_and_or_no_acfg(cx, 0x401, ~0x60, 0x60, | ||
233 | CXADEC_NO_ACFG_PLL | CXADEC_NO_ACFG_VID); | ||
180 | 234 | ||
181 | if (std & V4L2_STD_525_60) { | 235 | if (std & V4L2_STD_525_60) { |
182 | if (std == V4L2_STD_NTSC_M_JP) { | 236 | if (std == V4L2_STD_NTSC_M_JP) { |
183 | /* Japan uses EIAJ audio standard */ | 237 | /* Japan uses EIAJ audio standard */ |
184 | cx18_av_write(cx, 0x808, 0xf7); | 238 | cx18_av_write(cx, 0x808, 0xf7); |
239 | cx18_av_write(cx, 0x80b, 0x02); | ||
185 | } else if (std == V4L2_STD_NTSC_M_KR) { | 240 | } else if (std == V4L2_STD_NTSC_M_KR) { |
186 | /* South Korea uses A2 audio standard */ | 241 | /* South Korea uses A2 audio standard */ |
187 | cx18_av_write(cx, 0x808, 0xf8); | 242 | cx18_av_write(cx, 0x808, 0xf8); |
243 | cx18_av_write(cx, 0x80b, 0x03); | ||
188 | } else { | 244 | } else { |
189 | /* Others use the BTSC audio standard */ | 245 | /* Others use the BTSC audio standard */ |
190 | cx18_av_write(cx, 0x808, 0xf6); | 246 | cx18_av_write(cx, 0x808, 0xf6); |
247 | cx18_av_write(cx, 0x80b, 0x01); | ||
191 | } | 248 | } |
192 | cx18_av_write(cx, 0x80b, 0x00); | ||
193 | } else if (std & V4L2_STD_PAL) { | 249 | } else if (std & V4L2_STD_PAL) { |
194 | /* Follow tuner change procedure for PAL */ | 250 | /* Follow tuner change procedure for PAL */ |
195 | cx18_av_write(cx, 0x808, 0xff); | 251 | cx18_av_write(cx, 0x808, 0xff); |
@@ -226,7 +282,7 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, | |||
226 | 282 | ||
227 | if ((vid_input & ~0xff0) || | 283 | if ((vid_input & ~0xff0) || |
228 | luma < CX18_AV_SVIDEO_LUMA1 || | 284 | luma < CX18_AV_SVIDEO_LUMA1 || |
229 | luma > CX18_AV_SVIDEO_LUMA4 || | 285 | luma > CX18_AV_SVIDEO_LUMA8 || |
230 | chroma < CX18_AV_SVIDEO_CHROMA4 || | 286 | chroma < CX18_AV_SVIDEO_CHROMA4 || |
231 | chroma > CX18_AV_SVIDEO_CHROMA8) { | 287 | chroma > CX18_AV_SVIDEO_CHROMA8) { |
232 | CX18_ERR("0x%04x is not a valid video input!\n", | 288 | CX18_ERR("0x%04x is not a valid video input!\n", |
@@ -260,7 +316,8 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, | |||
260 | 316 | ||
261 | cx18_av_write(cx, 0x103, reg); | 317 | cx18_av_write(cx, 0x103, reg); |
262 | /* Set INPUT_MODE to Composite (0) or S-Video (1) */ | 318 | /* Set INPUT_MODE to Composite (0) or S-Video (1) */ |
263 | cx18_av_and_or(cx, 0x401, ~0x6, is_composite ? 0 : 0x02); | 319 | cx18_av_and_or_no_acfg(cx, 0x401, ~0x6, is_composite ? 0 : 0x02, |
320 | CXADEC_NO_ACFG_PLL | CXADEC_NO_ACFG_VID); | ||
264 | /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ | 321 | /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ |
265 | cx18_av_and_or(cx, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); | 322 | cx18_av_and_or(cx, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); |
266 | /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */ | 323 | /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */ |
@@ -316,12 +373,12 @@ static int set_v4lstd(struct cx18 *cx) | |||
316 | This happens for example with the Yuan MPC622. */ | 373 | This happens for example with the Yuan MPC622. */ |
317 | if (fmt >= 4 && fmt < 8) { | 374 | if (fmt >= 4 && fmt < 8) { |
318 | /* Set format to NTSC-M */ | 375 | /* Set format to NTSC-M */ |
319 | cx18_av_and_or(cx, 0x400, ~0xf, 1); | 376 | cx18_av_and_or_no_acfg(cx, 0x400, ~0xf, 1, CXADEC_NO_ACFG_AFE); |
320 | /* Turn off LCOMB */ | 377 | /* Turn off LCOMB */ |
321 | cx18_av_and_or(cx, 0x47b, ~6, 0); | 378 | cx18_av_and_or(cx, 0x47b, ~6, 0); |
322 | } | 379 | } |
323 | cx18_av_and_or(cx, 0x400, ~0xf, fmt); | 380 | cx18_av_and_or_no_acfg(cx, 0x400, ~0xf, fmt, CXADEC_NO_ACFG_AFE); |
324 | cx18_av_and_or(cx, 0x403, ~0x3, pal_m); | 381 | cx18_av_and_or_no_acfg(cx, 0x403, ~0x3, pal_m, CXADEC_NO_ACFG_ALL); |
325 | cx18_av_vbi_setup(cx); | 382 | cx18_av_vbi_setup(cx); |
326 | input_change(cx); | 383 | input_change(cx); |
327 | return 0; | 384 | return 0; |
@@ -741,8 +798,8 @@ static void log_audio_status(struct cx18 *cx) | |||
741 | { | 798 | { |
742 | struct cx18_av_state *state = &cx->av_state; | 799 | struct cx18_av_state *state = &cx->av_state; |
743 | u8 download_ctl = cx18_av_read(cx, 0x803); | 800 | u8 download_ctl = cx18_av_read(cx, 0x803); |
744 | u8 mod_det_stat0 = cx18_av_read(cx, 0x805); | 801 | u8 mod_det_stat0 = cx18_av_read(cx, 0x804); |
745 | u8 mod_det_stat1 = cx18_av_read(cx, 0x804); | 802 | u8 mod_det_stat1 = cx18_av_read(cx, 0x805); |
746 | u8 audio_config = cx18_av_read(cx, 0x808); | 803 | u8 audio_config = cx18_av_read(cx, 0x808); |
747 | u8 pref_mode = cx18_av_read(cx, 0x809); | 804 | u8 pref_mode = cx18_av_read(cx, 0x809); |
748 | u8 afc0 = cx18_av_read(cx, 0x80b); | 805 | u8 afc0 = cx18_av_read(cx, 0x80b); |
@@ -760,12 +817,12 @@ static void log_audio_status(struct cx18 *cx) | |||
760 | case 0x12: p = "dual with SAP"; break; | 817 | case 0x12: p = "dual with SAP"; break; |
761 | case 0x14: p = "tri with SAP"; break; | 818 | case 0x14: p = "tri with SAP"; break; |
762 | case 0xfe: p = "forced mode"; break; | 819 | case 0xfe: p = "forced mode"; break; |
763 | default: p = "not defined"; | 820 | default: p = "not defined"; break; |
764 | } | 821 | } |
765 | CX18_INFO("Detected audio mode: %s\n", p); | 822 | CX18_INFO("Detected audio mode: %s\n", p); |
766 | 823 | ||
767 | switch (mod_det_stat1) { | 824 | switch (mod_det_stat1) { |
768 | case 0x00: p = "BTSC"; break; | 825 | case 0x00: p = "not defined"; break; |
769 | case 0x01: p = "EIAJ"; break; | 826 | case 0x01: p = "EIAJ"; break; |
770 | case 0x02: p = "A2-M"; break; | 827 | case 0x02: p = "A2-M"; break; |
771 | case 0x03: p = "A2-BG"; break; | 828 | case 0x03: p = "A2-BG"; break; |
@@ -779,8 +836,13 @@ static void log_audio_status(struct cx18 *cx) | |||
779 | case 0x0b: p = "NICAM-I"; break; | 836 | case 0x0b: p = "NICAM-I"; break; |
780 | case 0x0c: p = "NICAM-L"; break; | 837 | case 0x0c: p = "NICAM-L"; break; |
781 | case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break; | 838 | case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break; |
839 | case 0x0e: p = "IF FM Radio"; break; | ||
840 | case 0x0f: p = "BTSC"; break; | ||
841 | case 0x10: p = "detected chrominance"; break; | ||
842 | case 0xfd: p = "unknown audio standard"; break; | ||
843 | case 0xfe: p = "forced audio standard"; break; | ||
782 | case 0xff: p = "no detected audio standard"; break; | 844 | case 0xff: p = "no detected audio standard"; break; |
783 | default: p = "not defined"; | 845 | default: p = "not defined"; break; |
784 | } | 846 | } |
785 | CX18_INFO("Detected audio standard: %s\n", p); | 847 | CX18_INFO("Detected audio standard: %s\n", p); |
786 | CX18_INFO("Audio muted: %s\n", | 848 | CX18_INFO("Audio muted: %s\n", |
@@ -789,22 +851,23 @@ static void log_audio_status(struct cx18 *cx) | |||
789 | (download_ctl & 0x10) ? "running" : "stopped"); | 851 | (download_ctl & 0x10) ? "running" : "stopped"); |
790 | 852 | ||
791 | switch (audio_config >> 4) { | 853 | switch (audio_config >> 4) { |
792 | case 0x00: p = "BTSC"; break; | 854 | case 0x00: p = "undefined"; break; |
793 | case 0x01: p = "EIAJ"; break; | 855 | case 0x01: p = "BTSC"; break; |
794 | case 0x02: p = "A2-M"; break; | 856 | case 0x02: p = "EIAJ"; break; |
795 | case 0x03: p = "A2-BG"; break; | 857 | case 0x03: p = "A2-M"; break; |
796 | case 0x04: p = "A2-DK1"; break; | 858 | case 0x04: p = "A2-BG"; break; |
797 | case 0x05: p = "A2-DK2"; break; | 859 | case 0x05: p = "A2-DK1"; break; |
798 | case 0x06: p = "A2-DK3"; break; | 860 | case 0x06: p = "A2-DK2"; break; |
799 | case 0x07: p = "A1 (6.0 MHz FM Mono)"; break; | 861 | case 0x07: p = "A2-DK3"; break; |
800 | case 0x08: p = "AM-L"; break; | 862 | case 0x08: p = "A1 (6.0 MHz FM Mono)"; break; |
801 | case 0x09: p = "NICAM-BG"; break; | 863 | case 0x09: p = "AM-L"; break; |
802 | case 0x0a: p = "NICAM-DK"; break; | 864 | case 0x0a: p = "NICAM-BG"; break; |
803 | case 0x0b: p = "NICAM-I"; break; | 865 | case 0x0b: p = "NICAM-DK"; break; |
804 | case 0x0c: p = "NICAM-L"; break; | 866 | case 0x0c: p = "NICAM-I"; break; |
805 | case 0x0d: p = "FM radio"; break; | 867 | case 0x0d: p = "NICAM-L"; break; |
868 | case 0x0e: p = "FM radio"; break; | ||
806 | case 0x0f: p = "automatic detection"; break; | 869 | case 0x0f: p = "automatic detection"; break; |
807 | default: p = "undefined"; | 870 | default: p = "undefined"; break; |
808 | } | 871 | } |
809 | CX18_INFO("Configured audio standard: %s\n", p); | 872 | CX18_INFO("Configured audio standard: %s\n", p); |
810 | 873 | ||
@@ -815,12 +878,9 @@ static void log_audio_status(struct cx18 *cx) | |||
815 | case 0x02: p = "MONO3 (STEREO forced MONO)"; break; | 878 | case 0x02: p = "MONO3 (STEREO forced MONO)"; break; |
816 | case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break; | 879 | case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break; |
817 | case 0x04: p = "STEREO"; break; | 880 | case 0x04: p = "STEREO"; break; |
818 | case 0x05: p = "DUAL1 (AB)"; break; | 881 | case 0x05: p = "DUAL1 (AC)"; break; |
819 | case 0x06: p = "DUAL2 (AC) (FM)"; break; | 882 | case 0x06: p = "DUAL2 (BC)"; break; |
820 | case 0x07: p = "DUAL3 (BC) (FM)"; break; | 883 | case 0x07: p = "DUAL3 (AB)"; break; |
821 | case 0x08: p = "DUAL4 (AC) (AM)"; break; | ||
822 | case 0x09: p = "DUAL5 (BC) (AM)"; break; | ||
823 | case 0x0a: p = "SAP"; break; | ||
824 | default: p = "undefined"; | 884 | default: p = "undefined"; |
825 | } | 885 | } |
826 | CX18_INFO("Configured audio mode: %s\n", p); | 886 | CX18_INFO("Configured audio mode: %s\n", p); |
@@ -835,9 +895,11 @@ static void log_audio_status(struct cx18 *cx) | |||
835 | case 0x06: p = "BTSC"; break; | 895 | case 0x06: p = "BTSC"; break; |
836 | case 0x07: p = "EIAJ"; break; | 896 | case 0x07: p = "EIAJ"; break; |
837 | case 0x08: p = "A2-M"; break; | 897 | case 0x08: p = "A2-M"; break; |
838 | case 0x09: p = "FM Radio"; break; | 898 | case 0x09: p = "FM Radio (4.5 MHz)"; break; |
899 | case 0x0a: p = "FM Radio (5.5 MHz)"; break; | ||
900 | case 0x0b: p = "S-Video"; break; | ||
839 | case 0x0f: p = "automatic standard and mode detection"; break; | 901 | case 0x0f: p = "automatic standard and mode detection"; break; |
840 | default: p = "undefined"; | 902 | default: p = "undefined"; break; |
841 | } | 903 | } |
842 | CX18_INFO("Configured audio system: %s\n", p); | 904 | CX18_INFO("Configured audio system: %s\n", p); |
843 | } | 905 | } |
@@ -857,22 +919,24 @@ static void log_audio_status(struct cx18 *cx) | |||
857 | case 5: p = "language AC"; break; | 919 | case 5: p = "language AC"; break; |
858 | case 6: p = "language BC"; break; | 920 | case 6: p = "language BC"; break; |
859 | case 7: p = "language AB"; break; | 921 | case 7: p = "language AB"; break; |
860 | default: p = "undefined"; | 922 | default: p = "undefined"; break; |
861 | } | 923 | } |
862 | CX18_INFO("Preferred audio mode: %s\n", p); | 924 | CX18_INFO("Preferred audio mode: %s\n", p); |
863 | 925 | ||
864 | if ((audio_config & 0xf) == 0xf) { | 926 | if ((audio_config & 0xf) == 0xf) { |
865 | switch ((afc0 >> 2) & 0x1) { | 927 | switch ((afc0 >> 3) & 0x1) { |
866 | case 0: p = "system DK"; break; | 928 | case 0: p = "system DK"; break; |
867 | case 1: p = "system L"; break; | 929 | case 1: p = "system L"; break; |
868 | } | 930 | } |
869 | CX18_INFO("Selected 65 MHz format: %s\n", p); | 931 | CX18_INFO("Selected 65 MHz format: %s\n", p); |
870 | 932 | ||
871 | switch (afc0 & 0x3) { | 933 | switch (afc0 & 0x7) { |
872 | case 0: p = "BTSC"; break; | 934 | case 0: p = "Chroma"; break; |
873 | case 1: p = "EIAJ"; break; | 935 | case 1: p = "BTSC"; break; |
874 | case 2: p = "A2-M"; break; | 936 | case 2: p = "EIAJ"; break; |
875 | default: p = "undefined"; | 937 | case 3: p = "A2-M"; break; |
938 | case 4: p = "autodetect"; break; | ||
939 | default: p = "undefined"; break; | ||
876 | } | 940 | } |
877 | CX18_INFO("Selected 45 MHz format: %s\n", p); | 941 | CX18_INFO("Selected 45 MHz format: %s\n", p); |
878 | } | 942 | } |
diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index 786901d72e9a..c172823ce1d8 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h | |||
@@ -37,12 +37,16 @@ enum cx18_av_video_input { | |||
37 | CX18_AV_COMPOSITE7, | 37 | CX18_AV_COMPOSITE7, |
38 | CX18_AV_COMPOSITE8, | 38 | CX18_AV_COMPOSITE8, |
39 | 39 | ||
40 | /* S-Video inputs consist of one luma input (In1-In4) ORed with one | 40 | /* S-Video inputs consist of one luma input (In1-In8) ORed with one |
41 | chroma input (In5-In8) */ | 41 | chroma input (In5-In8) */ |
42 | CX18_AV_SVIDEO_LUMA1 = 0x10, | 42 | CX18_AV_SVIDEO_LUMA1 = 0x10, |
43 | CX18_AV_SVIDEO_LUMA2 = 0x20, | 43 | CX18_AV_SVIDEO_LUMA2 = 0x20, |
44 | CX18_AV_SVIDEO_LUMA3 = 0x30, | 44 | CX18_AV_SVIDEO_LUMA3 = 0x30, |
45 | CX18_AV_SVIDEO_LUMA4 = 0x40, | 45 | CX18_AV_SVIDEO_LUMA4 = 0x40, |
46 | CX18_AV_SVIDEO_LUMA5 = 0x50, | ||
47 | CX18_AV_SVIDEO_LUMA6 = 0x60, | ||
48 | CX18_AV_SVIDEO_LUMA7 = 0x70, | ||
49 | CX18_AV_SVIDEO_LUMA8 = 0x80, | ||
46 | CX18_AV_SVIDEO_CHROMA4 = 0x400, | 50 | CX18_AV_SVIDEO_CHROMA4 = 0x400, |
47 | CX18_AV_SVIDEO_CHROMA5 = 0x500, | 51 | CX18_AV_SVIDEO_CHROMA5 = 0x500, |
48 | CX18_AV_SVIDEO_CHROMA6 = 0x600, | 52 | CX18_AV_SVIDEO_CHROMA6 = 0x600, |
@@ -291,14 +295,24 @@ struct cx18_av_state { | |||
291 | #define CXADEC_SELECT_AUDIO_STANDARD_FM 0xF9 /* FM radio */ | 295 | #define CXADEC_SELECT_AUDIO_STANDARD_FM 0xF9 /* FM radio */ |
292 | #define CXADEC_SELECT_AUDIO_STANDARD_AUTO 0xFF /* Auto detect */ | 296 | #define CXADEC_SELECT_AUDIO_STANDARD_AUTO 0xFF /* Auto detect */ |
293 | 297 | ||
298 | /* Flags on what to preserve on write to 0x400-0x403 with cx18_av_.*_no_acfg()*/ | ||
299 | #define CXADEC_NO_ACFG_AFE 0x01 /* Preserve 0x100-0x107 */ | ||
300 | #define CXADEC_NO_ACFG_PLL 0x02 /* Preserve 0x108-0x10f */ | ||
301 | #define CXADEC_NO_ACFG_VID 0x04 /* Preserve 0x470-0x47f */ | ||
302 | #define CXADEC_NO_ACFG_ALL 0x07 | ||
303 | |||
294 | /* ----------------------------------------------------------------------- */ | 304 | /* ----------------------------------------------------------------------- */ |
295 | /* cx18_av-core.c */ | 305 | /* cx18_av-core.c */ |
296 | int cx18_av_write(struct cx18 *cx, u16 addr, u8 value); | 306 | int cx18_av_write(struct cx18 *cx, u16 addr, u8 value); |
297 | int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value); | 307 | int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value); |
308 | int cx18_av_write_no_acfg(struct cx18 *cx, u16 addr, u8 value, | ||
309 | int no_acfg_mask); | ||
298 | u8 cx18_av_read(struct cx18 *cx, u16 addr); | 310 | u8 cx18_av_read(struct cx18 *cx, u16 addr); |
299 | u32 cx18_av_read4(struct cx18 *cx, u16 addr); | 311 | u32 cx18_av_read4(struct cx18 *cx, u16 addr); |
300 | int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value); | 312 | int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value); |
301 | int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value); | 313 | int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value); |
314 | int cx18_av_and_or_no_acfg(struct cx18 *cx, u16 addr, unsigned mask, u8 value, | ||
315 | int no_acfg_mask); | ||
302 | int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg); | 316 | int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg); |
303 | 317 | ||
304 | /* ----------------------------------------------------------------------- */ | 318 | /* ----------------------------------------------------------------------- */ |
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index f5e3ba1f5354..c26e0ef5b075 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
25 | #include "cx18-cards.h" | 25 | #include "cx18-cards.h" |
26 | #include "cx18-av-core.h" | ||
26 | #include "cx18-i2c.h" | 27 | #include "cx18-i2c.h" |
27 | #include <media/cs5345.h> | 28 | #include <media/cs5345.h> |
28 | 29 | ||
@@ -47,28 +48,29 @@ static struct cx18_card_tuner_i2c cx18_i2c_std = { | |||
47 | static const struct cx18_card cx18_card_hvr1600_esmt = { | 48 | static const struct cx18_card cx18_card_hvr1600_esmt = { |
48 | .type = CX18_CARD_HVR_1600_ESMT, | 49 | .type = CX18_CARD_HVR_1600_ESMT, |
49 | .name = "Hauppauge HVR-1600", | 50 | .name = "Hauppauge HVR-1600", |
50 | .comment = "DVB & VBI are not yet supported\n", | 51 | .comment = "VBI is not yet supported\n", |
51 | .v4l2_capabilities = CX18_CAP_ENCODER, | 52 | .v4l2_capabilities = CX18_CAP_ENCODER, |
52 | .hw_audio_ctrl = CX18_HW_CX23418, | 53 | .hw_audio_ctrl = CX18_HW_CX23418, |
53 | .hw_muxer = CX18_HW_CS5345, | 54 | .hw_muxer = CX18_HW_CS5345, |
54 | .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | CX18_HW_CS5345, | 55 | .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | |
56 | CX18_HW_CS5345 | CX18_HW_DVB, | ||
55 | .video_inputs = { | 57 | .video_inputs = { |
56 | { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, | 58 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 }, |
57 | { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, | 59 | { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 }, |
58 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 }, | 60 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 }, |
59 | { CX18_CARD_INPUT_SVIDEO2, 2, CX23418_SVIDEO2 }, | 61 | { CX18_CARD_INPUT_SVIDEO2, 2, CX18_AV_SVIDEO2 }, |
60 | { CX18_CARD_INPUT_COMPOSITE2, 2, CX23418_COMPOSITE4 }, | 62 | { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 }, |
61 | }, | 63 | }, |
62 | .audio_inputs = { | 64 | .audio_inputs = { |
63 | { CX18_CARD_INPUT_AUD_TUNER, | 65 | { CX18_CARD_INPUT_AUD_TUNER, |
64 | CX23418_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 }, | 66 | CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 }, |
65 | { CX18_CARD_INPUT_LINE_IN1, | 67 | { CX18_CARD_INPUT_LINE_IN1, |
66 | CX23418_AUDIO_SERIAL, CS5345_IN_2 }, | 68 | CX18_AV_AUDIO_SERIAL, CS5345_IN_2 }, |
67 | { CX18_CARD_INPUT_LINE_IN2, | 69 | { CX18_CARD_INPUT_LINE_IN2, |
68 | CX23418_AUDIO_SERIAL, CS5345_IN_2 }, | 70 | CX18_AV_AUDIO_SERIAL, CS5345_IN_3 }, |
69 | }, | 71 | }, |
70 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, | 72 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, |
71 | CX23418_AUDIO_SERIAL, 0 }, | 73 | CX18_AV_AUDIO_SERIAL, CS5345_IN_4 }, |
72 | .ddr = { | 74 | .ddr = { |
73 | /* ESMT M13S128324A-5B memory */ | 75 | /* ESMT M13S128324A-5B memory */ |
74 | .chip_config = 0x003, | 76 | .chip_config = 0x003, |
@@ -80,34 +82,40 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { | |||
80 | }, | 82 | }, |
81 | .gpio_init.initial_value = 0x3001, | 83 | .gpio_init.initial_value = 0x3001, |
82 | .gpio_init.direction = 0x3001, | 84 | .gpio_init.direction = 0x3001, |
85 | .gpio_i2c_slave_reset = { | ||
86 | .active_lo_mask = 0x3001, | ||
87 | .msecs_asserted = 10, | ||
88 | .msecs_recovery = 40, | ||
89 | }, | ||
83 | .i2c = &cx18_i2c_std, | 90 | .i2c = &cx18_i2c_std, |
84 | }; | 91 | }; |
85 | 92 | ||
86 | static const struct cx18_card cx18_card_hvr1600_samsung = { | 93 | static const struct cx18_card cx18_card_hvr1600_samsung = { |
87 | .type = CX18_CARD_HVR_1600_SAMSUNG, | 94 | .type = CX18_CARD_HVR_1600_SAMSUNG, |
88 | .name = "Hauppauge HVR-1600 (Preproduction)", | 95 | .name = "Hauppauge HVR-1600 (Preproduction)", |
89 | .comment = "DVB & VBI are not yet supported\n", | 96 | .comment = "VBI is not yet supported\n", |
90 | .v4l2_capabilities = CX18_CAP_ENCODER, | 97 | .v4l2_capabilities = CX18_CAP_ENCODER, |
91 | .hw_audio_ctrl = CX18_HW_CX23418, | 98 | .hw_audio_ctrl = CX18_HW_CX23418, |
92 | .hw_muxer = CX18_HW_CS5345, | 99 | .hw_muxer = CX18_HW_CS5345, |
93 | .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | CX18_HW_CS5345, | 100 | .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | |
101 | CX18_HW_CS5345 | CX18_HW_DVB, | ||
94 | .video_inputs = { | 102 | .video_inputs = { |
95 | { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, | 103 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 }, |
96 | { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, | 104 | { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 }, |
97 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 }, | 105 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 }, |
98 | { CX18_CARD_INPUT_SVIDEO2, 2, CX23418_SVIDEO2 }, | 106 | { CX18_CARD_INPUT_SVIDEO2, 2, CX18_AV_SVIDEO2 }, |
99 | { CX18_CARD_INPUT_COMPOSITE2, 2, CX23418_COMPOSITE4 }, | 107 | { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 }, |
100 | }, | 108 | }, |
101 | .audio_inputs = { | 109 | .audio_inputs = { |
102 | { CX18_CARD_INPUT_AUD_TUNER, | 110 | { CX18_CARD_INPUT_AUD_TUNER, |
103 | CX23418_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 }, | 111 | CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 }, |
104 | { CX18_CARD_INPUT_LINE_IN1, | 112 | { CX18_CARD_INPUT_LINE_IN1, |
105 | CX23418_AUDIO_SERIAL, CS5345_IN_2 }, | 113 | CX18_AV_AUDIO_SERIAL, CS5345_IN_2 }, |
106 | { CX18_CARD_INPUT_LINE_IN2, | 114 | { CX18_CARD_INPUT_LINE_IN2, |
107 | CX23418_AUDIO_SERIAL, CS5345_IN_2 }, | 115 | CX18_AV_AUDIO_SERIAL, CS5345_IN_3 }, |
108 | }, | 116 | }, |
109 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, | 117 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, |
110 | CX23418_AUDIO_SERIAL, 0 }, | 118 | CX18_AV_AUDIO_SERIAL, CS5345_IN_4 }, |
111 | .ddr = { | 119 | .ddr = { |
112 | /* Samsung K4D263238G-VC33 memory */ | 120 | /* Samsung K4D263238G-VC33 memory */ |
113 | .chip_config = 0x003, | 121 | .chip_config = 0x003, |
@@ -119,12 +127,17 @@ static const struct cx18_card cx18_card_hvr1600_samsung = { | |||
119 | }, | 127 | }, |
120 | .gpio_init.initial_value = 0x3001, | 128 | .gpio_init.initial_value = 0x3001, |
121 | .gpio_init.direction = 0x3001, | 129 | .gpio_init.direction = 0x3001, |
130 | .gpio_i2c_slave_reset = { | ||
131 | .active_lo_mask = 0x3001, | ||
132 | .msecs_asserted = 10, | ||
133 | .msecs_recovery = 40, | ||
134 | }, | ||
122 | .i2c = &cx18_i2c_std, | 135 | .i2c = &cx18_i2c_std, |
123 | }; | 136 | }; |
124 | 137 | ||
125 | /* ------------------------------------------------------------------------- */ | 138 | /* ------------------------------------------------------------------------- */ |
126 | 139 | ||
127 | /* Compro VideoMate H900: not working at the moment! */ | 140 | /* Compro VideoMate H900: note that this card is analog only! */ |
128 | 141 | ||
129 | static const struct cx18_card_pci_info cx18_pci_h900[] = { | 142 | static const struct cx18_card_pci_info cx18_pci_h900[] = { |
130 | { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_COMPRO, 0xe100 }, | 143 | { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_COMPRO, 0xe100 }, |
@@ -134,23 +147,24 @@ static const struct cx18_card_pci_info cx18_pci_h900[] = { | |||
134 | static const struct cx18_card cx18_card_h900 = { | 147 | static const struct cx18_card cx18_card_h900 = { |
135 | .type = CX18_CARD_COMPRO_H900, | 148 | .type = CX18_CARD_COMPRO_H900, |
136 | .name = "Compro VideoMate H900", | 149 | .name = "Compro VideoMate H900", |
137 | .comment = "Not yet supported!\n", | 150 | .comment = "VBI is not yet supported\n", |
138 | .v4l2_capabilities = 0, | 151 | .v4l2_capabilities = CX18_CAP_ENCODER, |
139 | .hw_audio_ctrl = CX18_HW_CX23418, | 152 | .hw_audio_ctrl = CX18_HW_CX23418, |
140 | .hw_all = CX18_HW_TUNER, | 153 | .hw_all = CX18_HW_TUNER, |
141 | .video_inputs = { | 154 | .video_inputs = { |
142 | { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, | 155 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, |
143 | { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, | 156 | { CX18_CARD_INPUT_SVIDEO1, 1, |
144 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 }, | 157 | CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, |
158 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 }, | ||
145 | }, | 159 | }, |
146 | .audio_inputs = { | 160 | .audio_inputs = { |
147 | { CX18_CARD_INPUT_AUD_TUNER, | 161 | { CX18_CARD_INPUT_AUD_TUNER, |
148 | CX23418_AUDIO8, 0 }, | 162 | CX18_AV_AUDIO8, 0 }, |
149 | { CX18_CARD_INPUT_LINE_IN1, | 163 | { CX18_CARD_INPUT_LINE_IN1, |
150 | CX23418_AUDIO_SERIAL, 0 }, | 164 | CX18_AV_AUDIO_SERIAL, 0 }, |
151 | }, | 165 | }, |
152 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, | 166 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, |
153 | CX23418_AUDIO_SERIAL, 0 }, | 167 | CX18_AV_AUDIO_SERIAL, 0 }, |
154 | .tuners = { | 168 | .tuners = { |
155 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, | 169 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, |
156 | }, | 170 | }, |
@@ -163,6 +177,7 @@ static const struct cx18_card cx18_card_h900 = { | |||
163 | .tune_lane = 0, | 177 | .tune_lane = 0, |
164 | .initial_emrs = 0, | 178 | .initial_emrs = 0, |
165 | }, | 179 | }, |
180 | .xceive_pin = 15, | ||
166 | .pci_list = cx18_pci_h900, | 181 | .pci_list = cx18_pci_h900, |
167 | .i2c = &cx18_i2c_std, | 182 | .i2c = &cx18_i2c_std, |
168 | }; | 183 | }; |
@@ -179,29 +194,30 @@ static const struct cx18_card_pci_info cx18_pci_mpc718[] = { | |||
179 | static const struct cx18_card cx18_card_mpc718 = { | 194 | static const struct cx18_card cx18_card_mpc718 = { |
180 | .type = CX18_CARD_YUAN_MPC718, | 195 | .type = CX18_CARD_YUAN_MPC718, |
181 | .name = "Yuan MPC718", | 196 | .name = "Yuan MPC718", |
182 | .comment = "Not yet supported!\n", | 197 | .comment = "Some Composite and S-Video inputs are currently working.\n", |
183 | .v4l2_capabilities = 0, | 198 | .v4l2_capabilities = CX18_CAP_ENCODER, |
184 | .hw_audio_ctrl = CX18_HW_CX23418, | 199 | .hw_audio_ctrl = CX18_HW_CX23418, |
185 | .hw_all = CX18_HW_TUNER, | 200 | .hw_all = CX18_HW_TUNER, |
186 | .video_inputs = { | 201 | .video_inputs = { |
187 | { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, | 202 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, |
188 | { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, | 203 | { CX18_CARD_INPUT_SVIDEO1, 1, |
189 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 }, | 204 | CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, |
205 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 }, | ||
206 | { CX18_CARD_INPUT_SVIDEO2, 2, | ||
207 | CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 }, | ||
208 | { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 }, | ||
209 | { CX18_CARD_INPUT_COMPOSITE3, 2, CX18_AV_COMPOSITE3 }, | ||
190 | }, | 210 | }, |
191 | .audio_inputs = { | 211 | .audio_inputs = { |
192 | { CX18_CARD_INPUT_AUD_TUNER, | 212 | { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, |
193 | CX23418_AUDIO8, 0 }, | 213 | { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL, 0 }, |
194 | { CX18_CARD_INPUT_LINE_IN1, | 214 | { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL, 0 }, |
195 | CX23418_AUDIO_SERIAL, 0 }, | ||
196 | }, | 215 | }, |
197 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, | 216 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL, 0 }, |
198 | CX23418_AUDIO_SERIAL, 0 }, | ||
199 | .tuners = { | 217 | .tuners = { |
200 | /* XC3028 tuner */ | 218 | /* XC3028 tuner */ |
201 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, | 219 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, |
202 | }, | 220 | }, |
203 | /* tuner reset */ | ||
204 | .gpio_init = { .direction = 0x1000, .initial_value = 0x1000 }, | ||
205 | .ddr = { | 221 | .ddr = { |
206 | /* Probably Samsung K4D263238G-VC33 memory */ | 222 | /* Probably Samsung K4D263238G-VC33 memory */ |
207 | .chip_config = 0x003, | 223 | .chip_config = 0x003, |
@@ -211,6 +227,7 @@ static const struct cx18_card cx18_card_mpc718 = { | |||
211 | .tune_lane = 0, | 227 | .tune_lane = 0, |
212 | .initial_emrs = 2, | 228 | .initial_emrs = 2, |
213 | }, | 229 | }, |
230 | .xceive_pin = 15, | ||
214 | .pci_list = cx18_pci_mpc718, | 231 | .pci_list = cx18_pci_mpc718, |
215 | .i2c = &cx18_i2c_std, | 232 | .i2c = &cx18_i2c_std, |
216 | }; | 233 | }; |
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h index bca249bdd337..dc2dd945d4c3 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/video/cx18/cx18-cards.h | |||
@@ -36,36 +36,6 @@ | |||
36 | #define CX18_CARD_INPUT_COMPOSITE2 5 | 36 | #define CX18_CARD_INPUT_COMPOSITE2 5 |
37 | #define CX18_CARD_INPUT_COMPOSITE3 6 | 37 | #define CX18_CARD_INPUT_COMPOSITE3 6 |
38 | 38 | ||
39 | enum cx34180_video_input { | ||
40 | /* Composite video inputs In1-In8 */ | ||
41 | CX23418_COMPOSITE1 = 1, | ||
42 | CX23418_COMPOSITE2, | ||
43 | CX23418_COMPOSITE3, | ||
44 | CX23418_COMPOSITE4, | ||
45 | CX23418_COMPOSITE5, | ||
46 | CX23418_COMPOSITE6, | ||
47 | CX23418_COMPOSITE7, | ||
48 | CX23418_COMPOSITE8, | ||
49 | |||
50 | /* S-Video inputs consist of one luma input (In1-In4) ORed with one | ||
51 | chroma input (In5-In8) */ | ||
52 | CX23418_SVIDEO_LUMA1 = 0x10, | ||
53 | CX23418_SVIDEO_LUMA2 = 0x20, | ||
54 | CX23418_SVIDEO_LUMA3 = 0x30, | ||
55 | CX23418_SVIDEO_LUMA4 = 0x40, | ||
56 | CX23418_SVIDEO_CHROMA4 = 0x400, | ||
57 | CX23418_SVIDEO_CHROMA5 = 0x500, | ||
58 | CX23418_SVIDEO_CHROMA6 = 0x600, | ||
59 | CX23418_SVIDEO_CHROMA7 = 0x700, | ||
60 | CX23418_SVIDEO_CHROMA8 = 0x800, | ||
61 | |||
62 | /* S-Video aliases for common luma/chroma combinations */ | ||
63 | CX23418_SVIDEO1 = 0x510, | ||
64 | CX23418_SVIDEO2 = 0x620, | ||
65 | CX23418_SVIDEO3 = 0x730, | ||
66 | CX23418_SVIDEO4 = 0x840, | ||
67 | }; | ||
68 | |||
69 | /* audio inputs */ | 39 | /* audio inputs */ |
70 | #define CX18_CARD_INPUT_AUD_TUNER 1 | 40 | #define CX18_CARD_INPUT_AUD_TUNER 1 |
71 | #define CX18_CARD_INPUT_LINE_IN1 2 | 41 | #define CX18_CARD_INPUT_LINE_IN1 2 |
@@ -75,16 +45,6 @@ enum cx34180_video_input { | |||
75 | #define CX18_CARD_MAX_AUDIO_INPUTS 3 | 45 | #define CX18_CARD_MAX_AUDIO_INPUTS 3 |
76 | #define CX18_CARD_MAX_TUNERS 2 | 46 | #define CX18_CARD_MAX_TUNERS 2 |
77 | 47 | ||
78 | enum cx23418_audio_input { | ||
79 | /* Audio inputs: serial or In4-In8 */ | ||
80 | CX23418_AUDIO_SERIAL, | ||
81 | CX23418_AUDIO4 = 4, | ||
82 | CX23418_AUDIO5, | ||
83 | CX23418_AUDIO6, | ||
84 | CX23418_AUDIO7, | ||
85 | CX23418_AUDIO8, | ||
86 | }; | ||
87 | |||
88 | /* V4L2 capability aliases */ | 48 | /* V4L2 capability aliases */ |
89 | #define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ | 49 | #define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ |
90 | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE) | 50 | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE) |
@@ -114,8 +74,15 @@ struct cx18_card_pci_info { | |||
114 | /* The mask is the set of bits used by the operation */ | 74 | /* The mask is the set of bits used by the operation */ |
115 | 75 | ||
116 | struct cx18_gpio_init { /* set initial GPIO DIR and OUT values */ | 76 | struct cx18_gpio_init { /* set initial GPIO DIR and OUT values */ |
117 | u16 direction; /* DIR setting. Leave to 0 if no init is needed */ | 77 | u32 direction; /* DIR setting. Leave to 0 if no init is needed */ |
118 | u16 initial_value; | 78 | u32 initial_value; |
79 | }; | ||
80 | |||
81 | struct cx18_gpio_i2c_slave_reset { | ||
82 | u32 active_lo_mask; /* GPIO outputs that reset i2c chips when low */ | ||
83 | u32 active_hi_mask; /* GPIO outputs that reset i2c chips when high */ | ||
84 | int msecs_asserted; /* time period reset must remain asserted */ | ||
85 | int msecs_recovery; /* time after deassert for chips to be ready */ | ||
119 | }; | 86 | }; |
120 | 87 | ||
121 | struct cx18_card_tuner { | 88 | struct cx18_card_tuner { |
@@ -153,7 +120,9 @@ struct cx18_card { | |||
153 | struct cx18_card_audio_input radio_input; | 120 | struct cx18_card_audio_input radio_input; |
154 | 121 | ||
155 | /* GPIO card-specific settings */ | 122 | /* GPIO card-specific settings */ |
156 | struct cx18_gpio_init gpio_init; | 123 | u8 xceive_pin; /* XCeive tuner GPIO reset pin */ |
124 | struct cx18_gpio_init gpio_init; | ||
125 | struct cx18_gpio_i2c_slave_reset gpio_i2c_slave_reset; | ||
157 | 126 | ||
158 | struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS]; | 127 | struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS]; |
159 | struct cx18_card_tuner_i2c *i2c; | 128 | struct cx18_card_tuner_i2c *i2c; |
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c index 2bdac5ebbb0d..87cf41021665 100644 --- a/drivers/media/video/cx18/cx18-controls.c +++ b/drivers/media/video/cx18/cx18-controls.c | |||
@@ -159,7 +159,7 @@ static int cx18_setup_vbi_fmt(struct cx18 *cx, enum v4l2_mpeg_stream_vbi_fmt fmt | |||
159 | { | 159 | { |
160 | if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE)) | 160 | if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE)) |
161 | return -EINVAL; | 161 | return -EINVAL; |
162 | if (atomic_read(&cx->capturing) > 0) | 162 | if (atomic_read(&cx->ana_capturing) > 0) |
163 | return -EBUSY; | 163 | return -EBUSY; |
164 | 164 | ||
165 | /* First try to allocate sliced VBI buffers if needed. */ | 165 | /* First try to allocate sliced VBI buffers if needed. */ |
@@ -235,7 +235,7 @@ int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg) | |||
235 | CX18_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n"); | 235 | CX18_DEBUG_IOCTL("VIDIOC_S_EXT_CTRLS\n"); |
236 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { | 236 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) { |
237 | struct cx2341x_mpeg_params p = cx->params; | 237 | struct cx2341x_mpeg_params p = cx->params; |
238 | int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->capturing), arg, cmd); | 238 | int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->ana_capturing), arg, cmd); |
239 | 239 | ||
240 | if (err) | 240 | if (err) |
241 | return err; | 241 | return err; |
@@ -295,7 +295,7 @@ int cx18_control_ioctls(struct cx18 *cx, unsigned int cmd, void *arg) | |||
295 | CX18_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n"); | 295 | CX18_DEBUG_IOCTL("VIDIOC_TRY_EXT_CTRLS\n"); |
296 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) | 296 | if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) |
297 | return cx2341x_ext_ctrls(&cx->params, | 297 | return cx2341x_ext_ctrls(&cx->params, |
298 | atomic_read(&cx->capturing), arg, cmd); | 298 | atomic_read(&cx->ana_capturing), arg, cmd); |
299 | return -EINVAL; | 299 | return -EINVAL; |
300 | } | 300 | } |
301 | 301 | ||
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 3f55d47bc4b9..2b810bb2a4c7 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c | |||
@@ -164,16 +164,6 @@ MODULE_LICENSE("GPL"); | |||
164 | 164 | ||
165 | MODULE_VERSION(CX18_VERSION); | 165 | MODULE_VERSION(CX18_VERSION); |
166 | 166 | ||
167 | int cx18_waitq(wait_queue_head_t *waitq) | ||
168 | { | ||
169 | DEFINE_WAIT(wait); | ||
170 | |||
171 | prepare_to_wait(waitq, &wait, TASK_INTERRUPTIBLE); | ||
172 | schedule(); | ||
173 | finish_wait(waitq, &wait); | ||
174 | return signal_pending(current) ? -EINTR : 0; | ||
175 | } | ||
176 | |||
177 | /* Generic utility functions */ | 167 | /* Generic utility functions */ |
178 | int cx18_msleep_timeout(unsigned int msecs, int intr) | 168 | int cx18_msleep_timeout(unsigned int msecs, int intr) |
179 | { | 169 | { |
@@ -220,13 +210,13 @@ static void cx18_process_eeprom(struct cx18 *cx) | |||
220 | 210 | ||
221 | /* Many thanks to Steven Toth from Hauppauge for providing the | 211 | /* Many thanks to Steven Toth from Hauppauge for providing the |
222 | model numbers */ | 212 | model numbers */ |
213 | /* Note: the Samsung memory models cannot be reliably determined | ||
214 | from the model number. Use the cardtype module option if you | ||
215 | have one of these preproduction models. */ | ||
223 | switch (tv.model) { | 216 | switch (tv.model) { |
224 | case 74000 ... 74099: | 217 | case 74000 ... 74999: |
225 | cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); | 218 | cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); |
226 | break; | 219 | break; |
227 | case 74700 ... 74799: | ||
228 | cx->card = cx18_get_card(CX18_CARD_HVR_1600_SAMSUNG); | ||
229 | break; | ||
230 | case 0: | 220 | case 0: |
231 | CX18_ERR("Invalid EEPROM\n"); | 221 | CX18_ERR("Invalid EEPROM\n"); |
232 | return; | 222 | return; |
@@ -548,6 +538,7 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev, | |||
548 | return 0; | 538 | return 0; |
549 | } | 539 | } |
550 | 540 | ||
541 | #ifdef MODULE | ||
551 | static u32 cx18_request_module(struct cx18 *cx, u32 hw, | 542 | static u32 cx18_request_module(struct cx18 *cx, u32 hw, |
552 | const char *name, u32 id) | 543 | const char *name, u32 id) |
553 | { | 544 | { |
@@ -560,12 +551,14 @@ static u32 cx18_request_module(struct cx18 *cx, u32 hw, | |||
560 | CX18_DEBUG_INFO("Loaded module %s\n", name); | 551 | CX18_DEBUG_INFO("Loaded module %s\n", name); |
561 | return hw; | 552 | return hw; |
562 | } | 553 | } |
554 | #endif | ||
563 | 555 | ||
564 | static void cx18_load_and_init_modules(struct cx18 *cx) | 556 | static void cx18_load_and_init_modules(struct cx18 *cx) |
565 | { | 557 | { |
566 | u32 hw = cx->card->hw_all; | 558 | u32 hw = cx->card->hw_all; |
567 | int i; | 559 | int i; |
568 | 560 | ||
561 | #ifdef MODULE | ||
569 | /* load modules */ | 562 | /* load modules */ |
570 | #ifndef CONFIG_MEDIA_TUNER | 563 | #ifndef CONFIG_MEDIA_TUNER |
571 | hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER); | 564 | hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER); |
@@ -573,6 +566,7 @@ static void cx18_load_and_init_modules(struct cx18 *cx) | |||
573 | #ifndef CONFIG_VIDEO_CS5345 | 566 | #ifndef CONFIG_VIDEO_CS5345 |
574 | hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345); | 567 | hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345); |
575 | #endif | 568 | #endif |
569 | #endif | ||
576 | 570 | ||
577 | /* check which i2c devices are actually found */ | 571 | /* check which i2c devices are actually found */ |
578 | for (i = 0; i < 32; i++) { | 572 | for (i = 0; i < 32; i++) { |
@@ -676,7 +670,7 @@ static int __devinit cx18_probe(struct pci_dev *dev, | |||
676 | cx18_init_power(cx, 1); | 670 | cx18_init_power(cx, 1); |
677 | cx18_init_memory(cx); | 671 | cx18_init_memory(cx); |
678 | 672 | ||
679 | cx->scb = (struct cx18_scb *)(cx->enc_mem + SCB_OFFSET); | 673 | cx->scb = (struct cx18_scb __iomem *)(cx->enc_mem + SCB_OFFSET); |
680 | cx18_init_scb(cx); | 674 | cx18_init_scb(cx); |
681 | 675 | ||
682 | cx18_gpio_init(cx); | 676 | cx18_gpio_init(cx); |
@@ -757,17 +751,6 @@ static int __devinit cx18_probe(struct pci_dev *dev, | |||
757 | if (cx->options.radio > 0) | 751 | if (cx->options.radio > 0) |
758 | cx->v4l2_cap |= V4L2_CAP_RADIO; | 752 | cx->v4l2_cap |= V4L2_CAP_RADIO; |
759 | 753 | ||
760 | retval = cx18_streams_setup(cx); | ||
761 | if (retval) { | ||
762 | CX18_ERR("Error %d setting up streams\n", retval); | ||
763 | goto free_irq; | ||
764 | } | ||
765 | retval = cx18_streams_register(cx); | ||
766 | if (retval) { | ||
767 | CX18_ERR("Error %d registering devices\n", retval); | ||
768 | goto free_streams; | ||
769 | } | ||
770 | |||
771 | if (cx->options.tuner > -1) { | 754 | if (cx->options.tuner > -1) { |
772 | struct tuner_setup setup; | 755 | struct tuner_setup setup; |
773 | 756 | ||
@@ -794,14 +777,23 @@ static int __devinit cx18_probe(struct pci_dev *dev, | |||
794 | are not. */ | 777 | are not. */ |
795 | cx->tuner_std = cx->std; | 778 | cx->tuner_std = cx->std; |
796 | 779 | ||
797 | cx18_init_on_first_open(cx); | 780 | retval = cx18_streams_setup(cx); |
781 | if (retval) { | ||
782 | CX18_ERR("Error %d setting up streams\n", retval); | ||
783 | goto free_irq; | ||
784 | } | ||
785 | retval = cx18_streams_register(cx); | ||
786 | if (retval) { | ||
787 | CX18_ERR("Error %d registering devices\n", retval); | ||
788 | goto free_streams; | ||
789 | } | ||
798 | 790 | ||
799 | CX18_INFO("Initialized card #%d: %s\n", cx->num, cx->card_name); | 791 | CX18_INFO("Initialized card #%d: %s\n", cx->num, cx->card_name); |
800 | 792 | ||
801 | return 0; | 793 | return 0; |
802 | 794 | ||
803 | free_streams: | 795 | free_streams: |
804 | cx18_streams_cleanup(cx); | 796 | cx18_streams_cleanup(cx, 1); |
805 | free_irq: | 797 | free_irq: |
806 | free_irq(cx->dev->irq, (void *)cx); | 798 | free_irq(cx->dev->irq, (void *)cx); |
807 | free_i2c: | 799 | free_i2c: |
@@ -895,7 +887,7 @@ static void cx18_remove(struct pci_dev *pci_dev) | |||
895 | 887 | ||
896 | /* Stop all captures */ | 888 | /* Stop all captures */ |
897 | CX18_DEBUG_INFO("Stopping all streams\n"); | 889 | CX18_DEBUG_INFO("Stopping all streams\n"); |
898 | if (atomic_read(&cx->capturing) > 0) | 890 | if (atomic_read(&cx->tot_capturing) > 0) |
899 | cx18_stop_all_captures(cx); | 891 | cx18_stop_all_captures(cx); |
900 | 892 | ||
901 | /* Interrupts */ | 893 | /* Interrupts */ |
@@ -904,14 +896,13 @@ static void cx18_remove(struct pci_dev *pci_dev) | |||
904 | 896 | ||
905 | cx18_halt_firmware(cx); | 897 | cx18_halt_firmware(cx); |
906 | 898 | ||
907 | cx18_streams_cleanup(cx); | 899 | cx18_streams_cleanup(cx, 1); |
908 | 900 | ||
909 | exit_cx18_i2c(cx); | 901 | exit_cx18_i2c(cx); |
910 | 902 | ||
911 | free_irq(cx->dev->irq, (void *)cx); | 903 | free_irq(cx->dev->irq, (void *)cx); |
912 | 904 | ||
913 | if (cx->dev) | 905 | cx18_iounmap(cx); |
914 | cx18_iounmap(cx); | ||
915 | 906 | ||
916 | release_mem_region(cx->base_addr, CX18_MEM_SIZE); | 907 | release_mem_region(cx->base_addr, CX18_MEM_SIZE); |
917 | 908 | ||
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 2ee939193bb7..de14ab59a206 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h | |||
@@ -358,7 +358,7 @@ struct cx18 { | |||
358 | u32 v4l2_cap; /* V4L2 capabilities of card */ | 358 | u32 v4l2_cap; /* V4L2 capabilities of card */ |
359 | u32 hw_flags; /* Hardware description of the board */ | 359 | u32 hw_flags; /* Hardware description of the board */ |
360 | unsigned mdl_offset; | 360 | unsigned mdl_offset; |
361 | struct cx18_scb *scb; /* pointer to SCB */ | 361 | struct cx18_scb __iomem *scb; /* pointer to SCB */ |
362 | 362 | ||
363 | struct cx18_av_state av_state; | 363 | struct cx18_av_state av_state; |
364 | 364 | ||
@@ -380,7 +380,8 @@ struct cx18 { | |||
380 | int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */ | 380 | int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */ |
381 | struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */ | 381 | struct cx18_stream streams[CX18_MAX_STREAMS]; /* Stream data */ |
382 | unsigned long i_flags; /* global cx18 flags */ | 382 | unsigned long i_flags; /* global cx18 flags */ |
383 | atomic_t capturing; /* count number of active capture streams */ | 383 | atomic_t ana_capturing; /* count number of active analog capture streams */ |
384 | atomic_t tot_capturing; /* total count number of active capture streams */ | ||
384 | spinlock_t lock; /* lock access to this struct */ | 385 | spinlock_t lock; /* lock access to this struct */ |
385 | int search_pack_header; | 386 | int search_pack_header; |
386 | 387 | ||
@@ -423,6 +424,10 @@ struct cx18 { | |||
423 | struct mutex i2c_bus_lock[2]; | 424 | struct mutex i2c_bus_lock[2]; |
424 | struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; | 425 | struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; |
425 | 426 | ||
427 | /* gpio */ | ||
428 | u32 gpio_dir; | ||
429 | u32 gpio_val; | ||
430 | |||
426 | /* v4l2 and User settings */ | 431 | /* v4l2 and User settings */ |
427 | 432 | ||
428 | /* codec settings */ | 433 | /* codec settings */ |
@@ -444,9 +449,6 @@ extern spinlock_t cx18_cards_lock; | |||
444 | /* Return non-zero if a signal is pending */ | 449 | /* Return non-zero if a signal is pending */ |
445 | int cx18_msleep_timeout(unsigned int msecs, int intr); | 450 | int cx18_msleep_timeout(unsigned int msecs, int intr); |
446 | 451 | ||
447 | /* Wait on queue, returns -EINTR if interrupted */ | ||
448 | int cx18_waitq(wait_queue_head_t *waitq); | ||
449 | |||
450 | /* Read Hauppauge eeprom */ | 452 | /* Read Hauppauge eeprom */ |
451 | struct tveeprom; /* forward reference */ | 453 | struct tveeprom; /* forward reference */ |
452 | void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv); | 454 | void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv); |
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 65efe69d939a..cae38985b131 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c | |||
@@ -24,25 +24,27 @@ | |||
24 | #include "cx18-streams.h" | 24 | #include "cx18-streams.h" |
25 | #include "cx18-cards.h" | 25 | #include "cx18-cards.h" |
26 | #include "s5h1409.h" | 26 | #include "s5h1409.h" |
27 | 27 | #include "mxl5005s.h" | |
28 | /* Wait until the MXL500X driver is merged */ | ||
29 | #ifdef HAVE_MXL500X | ||
30 | #include "mxl500x.h" | ||
31 | #endif | ||
32 | 28 | ||
33 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 29 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
34 | 30 | ||
35 | #define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000 | 31 | #define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000 |
36 | 32 | ||
37 | #ifdef HAVE_MXL500X | 33 | static struct mxl5005s_config hauppauge_hvr1600_tuner = { |
38 | static struct mxl500x_config hauppauge_hvr1600_tuner = { | 34 | .i2c_address = 0xC6 >> 1, |
39 | .delsys = MXL500x_MODE_ATSC, | 35 | .if_freq = IF_FREQ_5380000HZ, |
40 | .octf = MXL500x_OCTF_CH, | 36 | .xtal_freq = CRYSTAL_FREQ_16000000HZ, |
41 | .xtal_freq = 16000000, | 37 | .agc_mode = MXL_SINGLE_AGC, |
42 | .iflo_freq = 5380000, | 38 | .tracking_filter = MXL_TF_C_H, |
43 | .ref_freq = 322800000, | 39 | .rssi_enable = MXL_RSSI_ENABLE, |
44 | .rssi_ena = MXL_RSSI_ENABLE, | 40 | .cap_select = MXL_CAP_SEL_ENABLE, |
45 | .addr = 0xC6 >> 1, | 41 | .div_out = MXL_DIV_OUT_4, |
42 | .clock_out = MXL_CLOCK_OUT_DISABLE, | ||
43 | .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, | ||
44 | .top = MXL5005S_TOP_25P2, | ||
45 | .mod_mode = MXL_DIGITAL_MODE, | ||
46 | .if_mode = MXL_ZERO_IF, | ||
47 | .AgcMasterByte = 0x00, | ||
46 | }; | 48 | }; |
47 | 49 | ||
48 | static struct s5h1409_config hauppauge_hvr1600_config = { | 50 | static struct s5h1409_config hauppauge_hvr1600_config = { |
@@ -55,7 +57,6 @@ static struct s5h1409_config hauppauge_hvr1600_config = { | |||
55 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK | 57 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK |
56 | 58 | ||
57 | }; | 59 | }; |
58 | #endif | ||
59 | 60 | ||
60 | static int dvb_register(struct cx18_stream *stream); | 61 | static int dvb_register(struct cx18_stream *stream); |
61 | 62 | ||
@@ -68,11 +69,21 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) | |||
68 | struct dvb_demux *demux = feed->demux; | 69 | struct dvb_demux *demux = feed->demux; |
69 | struct cx18_stream *stream = (struct cx18_stream *) demux->priv; | 70 | struct cx18_stream *stream = (struct cx18_stream *) demux->priv; |
70 | struct cx18 *cx = stream->cx; | 71 | struct cx18 *cx = stream->cx; |
71 | int ret = -EINVAL; | 72 | int ret; |
72 | u32 v; | 73 | u32 v; |
73 | 74 | ||
74 | CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n", | 75 | CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n", |
75 | feed->pid, feed->index); | 76 | feed->pid, feed->index); |
77 | |||
78 | mutex_lock(&cx->serialize_lock); | ||
79 | ret = cx18_init_on_first_open(cx); | ||
80 | mutex_unlock(&cx->serialize_lock); | ||
81 | if (ret) { | ||
82 | CX18_ERR("Failed to initialize firmware starting DVB feed\n"); | ||
83 | return ret; | ||
84 | } | ||
85 | ret = -EINVAL; | ||
86 | |||
76 | switch (cx->card->type) { | 87 | switch (cx->card->type) { |
77 | case CX18_CARD_HVR_1600_ESMT: | 88 | case CX18_CARD_HVR_1600_ESMT: |
78 | case CX18_CARD_HVR_1600_SAMSUNG: | 89 | case CX18_CARD_HVR_1600_SAMSUNG: |
@@ -100,6 +111,11 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) | |||
100 | if (stream->dvb.feeding++ == 0) { | 111 | if (stream->dvb.feeding++ == 0) { |
101 | CX18_DEBUG_INFO("Starting Transport DMA\n"); | 112 | CX18_DEBUG_INFO("Starting Transport DMA\n"); |
102 | ret = cx18_start_v4l2_encode_stream(stream); | 113 | ret = cx18_start_v4l2_encode_stream(stream); |
114 | if (ret < 0) { | ||
115 | CX18_DEBUG_INFO( | ||
116 | "Failed to start Transport DMA\n"); | ||
117 | stream->dvb.feeding--; | ||
118 | } | ||
103 | } else | 119 | } else |
104 | ret = 0; | 120 | ret = 0; |
105 | mutex_unlock(&stream->dvb.feedlock); | 121 | mutex_unlock(&stream->dvb.feedlock); |
@@ -252,21 +268,18 @@ static int dvb_register(struct cx18_stream *stream) | |||
252 | int ret = 0; | 268 | int ret = 0; |
253 | 269 | ||
254 | switch (cx->card->type) { | 270 | switch (cx->card->type) { |
255 | /* Wait until the MXL500X driver is merged */ | ||
256 | #ifdef HAVE_MXL500X | ||
257 | case CX18_CARD_HVR_1600_ESMT: | 271 | case CX18_CARD_HVR_1600_ESMT: |
258 | case CX18_CARD_HVR_1600_SAMSUNG: | 272 | case CX18_CARD_HVR_1600_SAMSUNG: |
259 | dvb->fe = dvb_attach(s5h1409_attach, | 273 | dvb->fe = dvb_attach(s5h1409_attach, |
260 | &hauppauge_hvr1600_config, | 274 | &hauppauge_hvr1600_config, |
261 | &cx->i2c_adap[0]); | 275 | &cx->i2c_adap[0]); |
262 | if (dvb->fe != NULL) { | 276 | if (dvb->fe != NULL) { |
263 | dvb_attach(mxl500x_attach, dvb->fe, | 277 | dvb_attach(mxl5005s_attach, dvb->fe, |
264 | &hauppauge_hvr1600_tuner, | 278 | &cx->i2c_adap[0], |
265 | &cx->i2c_adap[0]); | 279 | &hauppauge_hvr1600_tuner); |
266 | ret = 0; | 280 | ret = 0; |
267 | } | 281 | } |
268 | break; | 282 | break; |
269 | #endif | ||
270 | default: | 283 | default: |
271 | /* No Digital Tv Support */ | 284 | /* No Digital Tv Support */ |
272 | break; | 285 | break; |
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 69303065a294..1e537fe04a23 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c | |||
@@ -39,7 +39,7 @@ | |||
39 | associated VBI streams are also automatically claimed. | 39 | associated VBI streams are also automatically claimed. |
40 | Possible error returns: -EBUSY if someone else has claimed | 40 | Possible error returns: -EBUSY if someone else has claimed |
41 | the stream or 0 on success. */ | 41 | the stream or 0 on success. */ |
42 | int cx18_claim_stream(struct cx18_open_id *id, int type) | 42 | static int cx18_claim_stream(struct cx18_open_id *id, int type) |
43 | { | 43 | { |
44 | struct cx18 *cx = id->cx; | 44 | struct cx18 *cx = id->cx; |
45 | struct cx18_stream *s = &cx->streams[type]; | 45 | struct cx18_stream *s = &cx->streams[type]; |
@@ -87,7 +87,7 @@ int cx18_claim_stream(struct cx18_open_id *id, int type) | |||
87 | 87 | ||
88 | /* This function releases a previously claimed stream. It will take into | 88 | /* This function releases a previously claimed stream. It will take into |
89 | account associated VBI streams. */ | 89 | account associated VBI streams. */ |
90 | void cx18_release_stream(struct cx18_stream *s) | 90 | static void cx18_release_stream(struct cx18_stream *s) |
91 | { | 91 | { |
92 | struct cx18 *cx = s->cx; | 92 | struct cx18 *cx = s->cx; |
93 | struct cx18_stream *s_vbi; | 93 | struct cx18_stream *s_vbi; |
@@ -318,7 +318,7 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, | |||
318 | size_t tot_written = 0; | 318 | size_t tot_written = 0; |
319 | int single_frame = 0; | 319 | int single_frame = 0; |
320 | 320 | ||
321 | if (atomic_read(&cx->capturing) == 0 && s->id == -1) { | 321 | if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) { |
322 | /* shouldn't happen */ | 322 | /* shouldn't happen */ |
323 | CX18_DEBUG_WARN("Stream %s not initialized before read\n", | 323 | CX18_DEBUG_WARN("Stream %s not initialized before read\n", |
324 | s->name); | 324 | s->name); |
@@ -361,7 +361,8 @@ static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf, | |||
361 | cx18_enqueue(s, buf, &s->q_free); | 361 | cx18_enqueue(s, buf, &s->q_free); |
362 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, | 362 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, |
363 | s->handle, | 363 | s->handle, |
364 | (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | 364 | (void __iomem *)&cx->scb->cpu_mdl[buf->id] - |
365 | cx->enc_mem, | ||
365 | 1, buf->id, s->buf_size); | 366 | 1, buf->id, s->buf_size); |
366 | } else | 367 | } else |
367 | cx18_enqueue(s, buf, &s->q_io); | 368 | cx18_enqueue(s, buf, &s->q_io); |
@@ -581,7 +582,7 @@ int cx18_v4l2_close(struct inode *inode, struct file *filp) | |||
581 | cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std); | 582 | cx18_call_i2c_clients(cx, VIDIOC_S_STD, &cx->std); |
582 | /* Select correct audio input (i.e. TV tuner or Line in) */ | 583 | /* Select correct audio input (i.e. TV tuner or Line in) */ |
583 | cx18_audio_set_io(cx); | 584 | cx18_audio_set_io(cx); |
584 | if (atomic_read(&cx->capturing) > 0) { | 585 | if (atomic_read(&cx->ana_capturing) > 0) { |
585 | /* Undo video mute */ | 586 | /* Undo video mute */ |
586 | cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle, | 587 | cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle, |
587 | cx->params.video_mute | | 588 | cx->params.video_mute | |
@@ -627,7 +628,7 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp) | |||
627 | } | 628 | } |
628 | 629 | ||
629 | if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) { | 630 | if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) { |
630 | if (atomic_read(&cx->capturing) > 0) { | 631 | if (atomic_read(&cx->ana_capturing) > 0) { |
631 | /* switching to radio while capture is | 632 | /* switching to radio while capture is |
632 | in progress is not polite */ | 633 | in progress is not polite */ |
633 | cx18_release_stream(s); | 634 | cx18_release_stream(s); |
@@ -662,6 +663,8 @@ int cx18_v4l2_open(struct inode *inode, struct file *filp) | |||
662 | for (x = 0; cx == NULL && x < cx18_cards_active; x++) { | 663 | for (x = 0; cx == NULL && x < cx18_cards_active; x++) { |
663 | /* find out which stream this open was on */ | 664 | /* find out which stream this open was on */ |
664 | for (y = 0; y < CX18_MAX_STREAMS; y++) { | 665 | for (y = 0; y < CX18_MAX_STREAMS; y++) { |
666 | if (cx18_cards[x] == NULL) | ||
667 | continue; | ||
665 | s = &cx18_cards[x]->streams[y]; | 668 | s = &cx18_cards[x]->streams[y]; |
666 | if (s->v4l2dev && s->v4l2dev->minor == minor) { | 669 | if (s->v4l2dev && s->v4l2dev->minor == minor) { |
667 | cx = cx18_cards[x]; | 670 | cx = cx18_cards[x]; |
@@ -692,7 +695,7 @@ int cx18_v4l2_open(struct inode *inode, struct file *filp) | |||
692 | 695 | ||
693 | void cx18_mute(struct cx18 *cx) | 696 | void cx18_mute(struct cx18 *cx) |
694 | { | 697 | { |
695 | if (atomic_read(&cx->capturing)) | 698 | if (atomic_read(&cx->ana_capturing)) |
696 | cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, | 699 | cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, |
697 | cx18_find_handle(cx), 1); | 700 | cx18_find_handle(cx), 1); |
698 | CX18_DEBUG_INFO("Mute\n"); | 701 | CX18_DEBUG_INFO("Mute\n"); |
@@ -700,7 +703,7 @@ void cx18_mute(struct cx18 *cx) | |||
700 | 703 | ||
701 | void cx18_unmute(struct cx18 *cx) | 704 | void cx18_unmute(struct cx18 *cx) |
702 | { | 705 | { |
703 | if (atomic_read(&cx->capturing)) { | 706 | if (atomic_read(&cx->ana_capturing)) { |
704 | cx18_msleep_timeout(100, 0); | 707 | cx18_msleep_timeout(100, 0); |
705 | cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, | 708 | cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, |
706 | cx18_find_handle(cx), 12); | 709 | cx18_find_handle(cx), 12); |
diff --git a/drivers/media/video/cx18/cx18-fileops.h b/drivers/media/video/cx18/cx18-fileops.h index 16cdafbd24c5..46da0282fc7d 100644 --- a/drivers/media/video/cx18/cx18-fileops.h +++ b/drivers/media/video/cx18/cx18-fileops.h | |||
@@ -34,12 +34,3 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end); | |||
34 | void cx18_mute(struct cx18 *cx); | 34 | void cx18_mute(struct cx18 *cx); |
35 | void cx18_unmute(struct cx18 *cx); | 35 | void cx18_unmute(struct cx18 *cx); |
36 | 36 | ||
37 | /* Utilities */ | ||
38 | |||
39 | /* Try to claim a stream for the filehandle. Return 0 on success, | ||
40 | -EBUSY if stream already claimed. Once a stream is claimed, it | ||
41 | remains claimed until the associated filehandle is closed. */ | ||
42 | int cx18_claim_stream(struct cx18_open_id *id, int type); | ||
43 | |||
44 | /* Release a previously claimed stream. */ | ||
45 | void cx18_release_stream(struct cx18_stream *s); | ||
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c index 19253e6b8673..b302833f6f9d 100644 --- a/drivers/media/video/cx18/cx18-gpio.c +++ b/drivers/media/video/cx18/cx18-gpio.c | |||
@@ -44,31 +44,81 @@ | |||
44 | * gpio13: cs5345 reset pin | 44 | * gpio13: cs5345 reset pin |
45 | */ | 45 | */ |
46 | 46 | ||
47 | static void gpio_write(struct cx18 *cx) | ||
48 | { | ||
49 | u32 dir = cx->gpio_dir; | ||
50 | u32 val = cx->gpio_val; | ||
51 | |||
52 | write_reg((dir & 0xffff) << 16, CX18_REG_GPIO_DIR1); | ||
53 | write_reg(((dir & 0xffff) << 16) | (val & 0xffff), | ||
54 | CX18_REG_GPIO_OUT1); | ||
55 | write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2); | ||
56 | write_reg_sync((dir & 0xffff0000) | ((val & 0xffff0000) >> 16), | ||
57 | CX18_REG_GPIO_OUT2); | ||
58 | } | ||
59 | |||
60 | void cx18_reset_i2c_slaves_gpio(struct cx18 *cx) | ||
61 | { | ||
62 | const struct cx18_gpio_i2c_slave_reset *p; | ||
63 | |||
64 | p = &cx->card->gpio_i2c_slave_reset; | ||
65 | |||
66 | if ((p->active_lo_mask | p->active_hi_mask) == 0) | ||
67 | return; | ||
68 | |||
69 | /* Assuming that the masks are a subset of the bits in gpio_dir */ | ||
70 | |||
71 | /* Assert */ | ||
72 | cx->gpio_val = | ||
73 | (cx->gpio_val | p->active_hi_mask) & ~(p->active_lo_mask); | ||
74 | gpio_write(cx); | ||
75 | schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted)); | ||
76 | |||
77 | /* Deassert */ | ||
78 | cx->gpio_val = | ||
79 | (cx->gpio_val | p->active_lo_mask) & ~(p->active_hi_mask); | ||
80 | gpio_write(cx); | ||
81 | schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery)); | ||
82 | } | ||
83 | |||
47 | void cx18_gpio_init(struct cx18 *cx) | 84 | void cx18_gpio_init(struct cx18 *cx) |
48 | { | 85 | { |
49 | if (cx->card->gpio_init.direction == 0) | 86 | cx->gpio_dir = cx->card->gpio_init.direction; |
87 | cx->gpio_val = cx->card->gpio_init.initial_value; | ||
88 | |||
89 | if (cx->card->tuners[0].tuner == TUNER_XC2028) { | ||
90 | cx->gpio_dir |= 1 << cx->card->xceive_pin; | ||
91 | cx->gpio_val |= 1 << cx->card->xceive_pin; | ||
92 | } | ||
93 | |||
94 | if (cx->gpio_dir == 0) | ||
50 | return; | 95 | return; |
51 | 96 | ||
52 | CX18_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n", | 97 | CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n", |
53 | read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_OUT1)); | 98 | read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2), |
99 | read_reg(CX18_REG_GPIO_OUT1), read_reg(CX18_REG_GPIO_OUT2)); | ||
54 | 100 | ||
55 | /* init output data then direction */ | 101 | gpio_write(cx); |
56 | write_reg(cx->card->gpio_init.direction << 16, CX18_REG_GPIO_DIR1); | ||
57 | write_reg(0, CX18_REG_GPIO_DIR2); | ||
58 | write_reg((cx->card->gpio_init.direction << 16) | | ||
59 | cx->card->gpio_init.initial_value, CX18_REG_GPIO_OUT1); | ||
60 | write_reg(0, CX18_REG_GPIO_OUT2); | ||
61 | } | 102 | } |
62 | 103 | ||
63 | /* Xceive tuner reset function */ | 104 | /* Xceive tuner reset function */ |
64 | int cx18_reset_tuner_gpio(void *dev, int cmd, int value) | 105 | int cx18_reset_tuner_gpio(void *dev, int cmd, int value) |
65 | { | 106 | { |
66 | struct i2c_algo_bit_data *algo = dev; | 107 | struct i2c_algo_bit_data *algo = dev; |
67 | struct cx18 *cx = algo->data; | 108 | struct cx18_i2c_algo_callback_data *cb_data = algo->data; |
68 | /* int curdir, curout;*/ | 109 | struct cx18 *cx = cb_data->cx; |
69 | 110 | ||
70 | if (cmd != XC2028_TUNER_RESET) | 111 | if (cmd != XC2028_TUNER_RESET) |
71 | return 0; | 112 | return 0; |
72 | CX18_DEBUG_INFO("Resetting tuner\n"); | 113 | CX18_DEBUG_INFO("Resetting tuner\n"); |
114 | |||
115 | cx->gpio_val &= ~(1 << cx->card->xceive_pin); | ||
116 | |||
117 | gpio_write(cx); | ||
118 | schedule_timeout_interruptible(msecs_to_jiffies(1)); | ||
119 | |||
120 | cx->gpio_val |= 1 << cx->card->xceive_pin; | ||
121 | gpio_write(cx); | ||
122 | schedule_timeout_interruptible(msecs_to_jiffies(1)); | ||
73 | return 0; | 123 | return 0; |
74 | } | 124 | } |
diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h index 41bac8856b50..525c328f748a 100644 --- a/drivers/media/video/cx18/cx18-gpio.h +++ b/drivers/media/video/cx18/cx18-gpio.h | |||
@@ -21,4 +21,5 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | void cx18_gpio_init(struct cx18 *cx); | 23 | void cx18_gpio_init(struct cx18 *cx); |
24 | void cx18_reset_i2c_slaves_gpio(struct cx18 *cx); | ||
24 | int cx18_reset_tuner_gpio(void *dev, int cmd, int value); | 25 | int cx18_reset_tuner_gpio(void *dev, int cmd, int value); |
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 18c88d1e4833..680bc4e35b79 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "cx18-cards.h" | 25 | #include "cx18-cards.h" |
26 | #include "cx18-gpio.h" | 26 | #include "cx18-gpio.h" |
27 | #include "cx18-av-core.h" | 27 | #include "cx18-av-core.h" |
28 | #include "cx18-i2c.h" | ||
28 | 29 | ||
29 | #include <media/ir-kbd-i2c.h> | 30 | #include <media/ir-kbd-i2c.h> |
30 | 31 | ||
@@ -73,7 +74,7 @@ static const u8 hw_bus[] = { | |||
73 | }; | 74 | }; |
74 | 75 | ||
75 | /* This array should match the CX18_HW_ defines */ | 76 | /* This array should match the CX18_HW_ defines */ |
76 | static const char * const hw_drivernames[] = { | 77 | static const char * const hw_devicenames[] = { |
77 | "tuner", | 78 | "tuner", |
78 | "tveeprom", | 79 | "tveeprom", |
79 | "cs5345", | 80 | "cs5345", |
@@ -94,8 +95,7 @@ int cx18_i2c_register(struct cx18 *cx, unsigned idx) | |||
94 | id = hw_driverids[idx]; | 95 | id = hw_driverids[idx]; |
95 | bus = hw_bus[idx]; | 96 | bus = hw_bus[idx]; |
96 | memset(&info, 0, sizeof(info)); | 97 | memset(&info, 0, sizeof(info)); |
97 | strlcpy(info.driver_name, hw_drivernames[idx], | 98 | strlcpy(info.type, hw_devicenames[idx], sizeof(info.type)); |
98 | sizeof(info.driver_name)); | ||
99 | info.addr = hw_addrs[idx]; | 99 | info.addr = hw_addrs[idx]; |
100 | for (i = 0; i < I2C_CLIENTS_MAX; i++) | 100 | for (i = 0; i < I2C_CLIENTS_MAX; i++) |
101 | if (cx->i2c_clients[i] == NULL) | 101 | if (cx->i2c_clients[i] == NULL) |
@@ -278,7 +278,7 @@ static const char *cx18_i2c_id_name(u32 id) | |||
278 | 278 | ||
279 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) | 279 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) |
280 | if (hw_driverids[i] == id) | 280 | if (hw_driverids[i] == id) |
281 | return hw_drivernames[i]; | 281 | return hw_devicenames[i]; |
282 | return "unknown device"; | 282 | return "unknown device"; |
283 | } | 283 | } |
284 | 284 | ||
@@ -289,7 +289,7 @@ static const char *cx18_i2c_hw_name(u32 hw) | |||
289 | 289 | ||
290 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) | 290 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) |
291 | if (1 << i == hw) | 291 | if (1 << i == hw) |
292 | return hw_drivernames[i]; | 292 | return hw_devicenames[i]; |
293 | return "unknown device"; | 293 | return "unknown device"; |
294 | } | 294 | } |
295 | 295 | ||
@@ -405,6 +405,8 @@ int init_cx18_i2c(struct cx18 *cx) | |||
405 | cx18_setscl(&cx->i2c_algo_cb_data[1], 1); | 405 | cx18_setscl(&cx->i2c_algo_cb_data[1], 1); |
406 | cx18_setsda(&cx->i2c_algo_cb_data[1], 1); | 406 | cx18_setsda(&cx->i2c_algo_cb_data[1], 1); |
407 | 407 | ||
408 | cx18_reset_i2c_slaves_gpio(cx); | ||
409 | |||
408 | return i2c_bit_add_bus(&cx->i2c_adap[0]) || | 410 | return i2c_bit_add_bus(&cx->i2c_adap[0]) || |
409 | i2c_bit_add_bus(&cx->i2c_adap[1]); | 411 | i2c_bit_add_bus(&cx->i2c_adap[1]); |
410 | } | 412 | } |
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c index dbdcb86ec5aa..4151f1e5493f 100644 --- a/drivers/media/video/cx18/cx18-ioctl.c +++ b/drivers/media/video/cx18/cx18-ioctl.c | |||
@@ -247,7 +247,7 @@ static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype, | |||
247 | 247 | ||
248 | if (!set_fmt || (cx->params.width == w && cx->params.height == h)) | 248 | if (!set_fmt || (cx->params.width == w && cx->params.height == h)) |
249 | return 0; | 249 | return 0; |
250 | if (atomic_read(&cx->capturing) > 0) | 250 | if (atomic_read(&cx->ana_capturing) > 0) |
251 | return -EBUSY; | 251 | return -EBUSY; |
252 | 252 | ||
253 | cx->params.width = w; | 253 | cx->params.width = w; |
@@ -264,7 +264,7 @@ static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype, | |||
264 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { | 264 | if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) { |
265 | if (set_fmt && streamtype == CX18_ENC_STREAM_TYPE_VBI && | 265 | if (set_fmt && streamtype == CX18_ENC_STREAM_TYPE_VBI && |
266 | cx->vbi.sliced_in->service_set && | 266 | cx->vbi.sliced_in->service_set && |
267 | atomic_read(&cx->capturing) > 0) | 267 | atomic_read(&cx->ana_capturing) > 0) |
268 | return -EBUSY; | 268 | return -EBUSY; |
269 | if (set_fmt) { | 269 | if (set_fmt) { |
270 | cx->vbi.sliced_in->service_set = 0; | 270 | cx->vbi.sliced_in->service_set = 0; |
@@ -293,7 +293,7 @@ static int cx18_try_or_set_fmt(struct cx18 *cx, int streamtype, | |||
293 | return 0; | 293 | return 0; |
294 | if (set == 0) | 294 | if (set == 0) |
295 | return -EINVAL; | 295 | return -EINVAL; |
296 | if (atomic_read(&cx->capturing) > 0 && cx->vbi.sliced_in->service_set == 0) | 296 | if (atomic_read(&cx->ana_capturing) > 0 && cx->vbi.sliced_in->service_set == 0) |
297 | return -EBUSY; | 297 | return -EBUSY; |
298 | cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); | 298 | cx18_av_cmd(cx, VIDIOC_S_FMT, fmt); |
299 | memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in)); | 299 | memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in)); |
@@ -581,7 +581,7 @@ int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg | |||
581 | break; | 581 | break; |
582 | 582 | ||
583 | if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) || | 583 | if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) || |
584 | atomic_read(&cx->capturing) > 0) { | 584 | atomic_read(&cx->ana_capturing) > 0) { |
585 | /* Switching standard would turn off the radio or mess | 585 | /* Switching standard would turn off the radio or mess |
586 | with already running streams, prevent that by | 586 | with already running streams, prevent that by |
587 | returning EBUSY. */ | 587 | returning EBUSY. */ |
@@ -677,7 +677,7 @@ int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg | |||
677 | enc->flags = 0; | 677 | enc->flags = 0; |
678 | if (try) | 678 | if (try) |
679 | return 0; | 679 | return 0; |
680 | if (!atomic_read(&cx->capturing)) | 680 | if (!atomic_read(&cx->ana_capturing)) |
681 | return -EPERM; | 681 | return -EPERM; |
682 | if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) | 682 | if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) |
683 | return 0; | 683 | return 0; |
@@ -689,7 +689,7 @@ int cx18_v4l2_ioctls(struct cx18 *cx, struct file *filp, unsigned cmd, void *arg | |||
689 | enc->flags = 0; | 689 | enc->flags = 0; |
690 | if (try) | 690 | if (try) |
691 | return 0; | 691 | return 0; |
692 | if (!atomic_read(&cx->capturing)) | 692 | if (!atomic_read(&cx->ana_capturing)) |
693 | return -EPERM; | 693 | return -EPERM; |
694 | if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) | 694 | if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags)) |
695 | return 0; | 695 | return 0; |
diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index 6e14f8bda559..25114a5cbd57 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c | |||
@@ -75,7 +75,7 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) | |||
75 | 75 | ||
76 | cx18_buf_sync_for_device(s, buf); | 76 | cx18_buf_sync_for_device(s, buf); |
77 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, | 77 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, |
78 | (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, | 78 | (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, |
79 | 1, buf->id, s->buf_size); | 79 | 1, buf->id, s->buf_size); |
80 | } else | 80 | } else |
81 | set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); | 81 | set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); |
@@ -161,13 +161,15 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) | |||
161 | */ | 161 | */ |
162 | 162 | ||
163 | if (sw2) { | 163 | if (sw2) { |
164 | if (sw2 & (cx->scb->cpu2hpu_irq_ack | cx->scb->cpu2epu_irq_ack)) | 164 | if (sw2 & (readl(&cx->scb->cpu2hpu_irq_ack) | |
165 | readl(&cx->scb->cpu2epu_irq_ack))) | ||
165 | wake_up(&cx->mb_cpu_waitq); | 166 | wake_up(&cx->mb_cpu_waitq); |
166 | if (sw2 & (cx->scb->apu2hpu_irq_ack | cx->scb->apu2epu_irq_ack)) | 167 | if (sw2 & (readl(&cx->scb->apu2hpu_irq_ack) | |
168 | readl(&cx->scb->apu2epu_irq_ack))) | ||
167 | wake_up(&cx->mb_apu_waitq); | 169 | wake_up(&cx->mb_apu_waitq); |
168 | if (sw2 & cx->scb->epu2hpu_irq_ack) | 170 | if (sw2 & readl(&cx->scb->epu2hpu_irq_ack)) |
169 | wake_up(&cx->mb_epu_waitq); | 171 | wake_up(&cx->mb_epu_waitq); |
170 | if (sw2 & cx->scb->hpu2epu_irq_ack) | 172 | if (sw2 & readl(&cx->scb->hpu2epu_irq_ack)) |
171 | wake_up(&cx->mb_hpu_waitq); | 173 | wake_up(&cx->mb_hpu_waitq); |
172 | } | 174 | } |
173 | 175 | ||
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 0c5f328bca54..2a5ccef9185b 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c | |||
@@ -94,10 +94,10 @@ static const struct cx18_api_info *find_api_info(u32 cmd) | |||
94 | return NULL; | 94 | return NULL; |
95 | } | 95 | } |
96 | 96 | ||
97 | static struct cx18_mailbox *cx18_mb_is_complete(struct cx18 *cx, int rpu, | 97 | static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu, |
98 | u32 *state, u32 *irq, u32 *req) | 98 | u32 *state, u32 *irq, u32 *req) |
99 | { | 99 | { |
100 | struct cx18_mailbox *mb = NULL; | 100 | struct cx18_mailbox __iomem *mb = NULL; |
101 | int wait_count = 0; | 101 | int wait_count = 0; |
102 | u32 ack; | 102 | u32 ack; |
103 | 103 | ||
@@ -142,7 +142,7 @@ static struct cx18_mailbox *cx18_mb_is_complete(struct cx18 *cx, int rpu, | |||
142 | long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) | 142 | long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) |
143 | { | 143 | { |
144 | const struct cx18_api_info *info = find_api_info(mb->cmd); | 144 | const struct cx18_api_info *info = find_api_info(mb->cmd); |
145 | struct cx18_mailbox *ack_mb; | 145 | struct cx18_mailbox __iomem *ack_mb; |
146 | u32 ack_irq; | 146 | u32 ack_irq; |
147 | u8 rpu = CPU; | 147 | u8 rpu = CPU; |
148 | 148 | ||
@@ -182,7 +182,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) | |||
182 | { | 182 | { |
183 | const struct cx18_api_info *info = find_api_info(cmd); | 183 | const struct cx18_api_info *info = find_api_info(cmd); |
184 | u32 state = 0, irq = 0, req, oldreq, err; | 184 | u32 state = 0, irq = 0, req, oldreq, err; |
185 | struct cx18_mailbox *mb; | 185 | struct cx18_mailbox __iomem *mb; |
186 | wait_queue_head_t *waitq; | 186 | wait_queue_head_t *waitq; |
187 | int timeout = 100; | 187 | int timeout = 100; |
188 | int cnt = 0; | 188 | int cnt = 0; |
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index 65af1bb507ca..6990b77c6200 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c | |||
@@ -26,17 +26,6 @@ | |||
26 | #include "cx18-queue.h" | 26 | #include "cx18-queue.h" |
27 | #include "cx18-scb.h" | 27 | #include "cx18-scb.h" |
28 | 28 | ||
29 | int cx18_buf_copy_from_user(struct cx18_stream *s, struct cx18_buffer *buf, | ||
30 | const char __user *src, int copybytes) | ||
31 | { | ||
32 | if (s->buf_size - buf->bytesused < copybytes) | ||
33 | copybytes = s->buf_size - buf->bytesused; | ||
34 | if (copy_from_user(buf->buf + buf->bytesused, src, copybytes)) | ||
35 | return -EFAULT; | ||
36 | buf->bytesused += copybytes; | ||
37 | return copybytes; | ||
38 | } | ||
39 | |||
40 | void cx18_buf_swap(struct cx18_buffer *buf) | 29 | void cx18_buf_swap(struct cx18_buffer *buf) |
41 | { | 30 | { |
42 | int i; | 31 | int i; |
@@ -159,8 +148,9 @@ static void cx18_queue_move_buf(struct cx18_stream *s, struct cx18_queue *from, | |||
159 | -ENOMEM is returned if the buffers could not be obtained, 0 if all | 148 | -ENOMEM is returned if the buffers could not be obtained, 0 if all |
160 | buffers where obtained from the 'from' list and if non-zero then | 149 | buffers where obtained from the 'from' list and if non-zero then |
161 | the number of stolen buffers is returned. */ | 150 | the number of stolen buffers is returned. */ |
162 | int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from, | 151 | static int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from, |
163 | struct cx18_queue *steal, struct cx18_queue *to, int needed_bytes) | 152 | struct cx18_queue *steal, struct cx18_queue *to, |
153 | int needed_bytes) | ||
164 | { | 154 | { |
165 | unsigned long flags; | 155 | unsigned long flags; |
166 | int rc = 0; | 156 | int rc = 0; |
@@ -239,12 +229,12 @@ int cx18_stream_alloc(struct cx18_stream *s) | |||
239 | 229 | ||
240 | /* allocate stream buffers. Initially all buffers are in q_free. */ | 230 | /* allocate stream buffers. Initially all buffers are in q_free. */ |
241 | for (i = 0; i < s->buffers; i++) { | 231 | for (i = 0; i < s->buffers; i++) { |
242 | struct cx18_buffer *buf = | 232 | struct cx18_buffer *buf = kzalloc(sizeof(struct cx18_buffer), |
243 | kzalloc(sizeof(struct cx18_buffer), GFP_KERNEL); | 233 | GFP_KERNEL|__GFP_NOWARN); |
244 | 234 | ||
245 | if (buf == NULL) | 235 | if (buf == NULL) |
246 | break; | 236 | break; |
247 | buf->buf = kmalloc(s->buf_size, GFP_KERNEL); | 237 | buf->buf = kmalloc(s->buf_size, GFP_KERNEL|__GFP_NOWARN); |
248 | if (buf->buf == NULL) { | 238 | if (buf->buf == NULL) { |
249 | kfree(buf); | 239 | kfree(buf); |
250 | break; | 240 | break; |
diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h index f86c8a6fa6e7..91423b9863a4 100644 --- a/drivers/media/video/cx18/cx18-queue.h +++ b/drivers/media/video/cx18/cx18-queue.h | |||
@@ -39,8 +39,6 @@ static inline void cx18_buf_sync_for_device(struct cx18_stream *s, | |||
39 | s->buf_size, s->dma); | 39 | s->buf_size, s->dma); |
40 | } | 40 | } |
41 | 41 | ||
42 | int cx18_buf_copy_from_user(struct cx18_stream *s, struct cx18_buffer *buf, | ||
43 | const char __user *src, int copybytes); | ||
44 | void cx18_buf_swap(struct cx18_buffer *buf); | 42 | void cx18_buf_swap(struct cx18_buffer *buf); |
45 | 43 | ||
46 | /* cx18_queue utility functions */ | 44 | /* cx18_queue utility functions */ |
@@ -48,8 +46,6 @@ void cx18_queue_init(struct cx18_queue *q); | |||
48 | void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, | 46 | void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, |
49 | struct cx18_queue *q); | 47 | struct cx18_queue *q); |
50 | struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q); | 48 | struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q); |
51 | int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from, | ||
52 | struct cx18_queue *steal, struct cx18_queue *to, int needed_bytes); | ||
53 | struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id, | 49 | struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id, |
54 | u32 bytesused); | 50 | u32 bytesused); |
55 | void cx18_flush_queues(struct cx18_stream *s); | 51 | void cx18_flush_queues(struct cx18_stream *s); |
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index afb141b2027a..1b921a336092 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c | |||
@@ -36,12 +36,13 @@ | |||
36 | #define CX18_DSP0_INTERRUPT_MASK 0xd0004C | 36 | #define CX18_DSP0_INTERRUPT_MASK 0xd0004C |
37 | 37 | ||
38 | static struct file_operations cx18_v4l2_enc_fops = { | 38 | static struct file_operations cx18_v4l2_enc_fops = { |
39 | .owner = THIS_MODULE, | 39 | .owner = THIS_MODULE, |
40 | .read = cx18_v4l2_read, | 40 | .read = cx18_v4l2_read, |
41 | .open = cx18_v4l2_open, | 41 | .open = cx18_v4l2_open, |
42 | .ioctl = cx18_v4l2_ioctl, | 42 | .ioctl = cx18_v4l2_ioctl, |
43 | .release = cx18_v4l2_close, | 43 | .compat_ioctl = v4l_compat_ioctl32, |
44 | .poll = cx18_v4l2_enc_poll, | 44 | .release = cx18_v4l2_close, |
45 | .poll = cx18_v4l2_enc_poll, | ||
45 | }; | 46 | }; |
46 | 47 | ||
47 | /* offset from 0 to register ts v4l2 minors on */ | 48 | /* offset from 0 to register ts v4l2 minors on */ |
@@ -218,7 +219,7 @@ int cx18_streams_setup(struct cx18 *cx) | |||
218 | return 0; | 219 | return 0; |
219 | 220 | ||
220 | /* One or more streams could not be initialized. Clean 'em all up. */ | 221 | /* One or more streams could not be initialized. Clean 'em all up. */ |
221 | cx18_streams_cleanup(cx); | 222 | cx18_streams_cleanup(cx, 0); |
222 | return -ENOMEM; | 223 | return -ENOMEM; |
223 | } | 224 | } |
224 | 225 | ||
@@ -296,12 +297,12 @@ int cx18_streams_register(struct cx18 *cx) | |||
296 | return 0; | 297 | return 0; |
297 | 298 | ||
298 | /* One or more streams could not be initialized. Clean 'em all up. */ | 299 | /* One or more streams could not be initialized. Clean 'em all up. */ |
299 | cx18_streams_cleanup(cx); | 300 | cx18_streams_cleanup(cx, 1); |
300 | return -ENOMEM; | 301 | return -ENOMEM; |
301 | } | 302 | } |
302 | 303 | ||
303 | /* Unregister v4l2 devices */ | 304 | /* Unregister v4l2 devices */ |
304 | void cx18_streams_cleanup(struct cx18 *cx) | 305 | void cx18_streams_cleanup(struct cx18 *cx, int unregister) |
305 | { | 306 | { |
306 | struct video_device *vdev; | 307 | struct video_device *vdev; |
307 | int type; | 308 | int type; |
@@ -319,8 +320,11 @@ void cx18_streams_cleanup(struct cx18 *cx) | |||
319 | 320 | ||
320 | cx18_stream_free(&cx->streams[type]); | 321 | cx18_stream_free(&cx->streams[type]); |
321 | 322 | ||
322 | /* Unregister device */ | 323 | /* Unregister or release device */ |
323 | video_unregister_device(vdev); | 324 | if (unregister) |
325 | video_unregister_device(vdev); | ||
326 | else | ||
327 | video_device_release(vdev); | ||
324 | } | 328 | } |
325 | } | 329 | } |
326 | 330 | ||
@@ -440,7 +444,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
440 | s->handle = data[0]; | 444 | s->handle = data[0]; |
441 | cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype); | 445 | cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype); |
442 | 446 | ||
443 | if (atomic_read(&cx->capturing) == 0 && !ts) { | 447 | if (atomic_read(&cx->ana_capturing) == 0 && !ts) { |
444 | /* Stuff from Windows, we don't know what it is */ | 448 | /* Stuff from Windows, we don't know what it is */ |
445 | cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0); | 449 | cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0); |
446 | cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1); | 450 | cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1); |
@@ -463,14 +467,14 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
463 | cx2341x_update(cx, cx18_api_func, NULL, &cx->params); | 467 | cx2341x_update(cx, cx18_api_func, NULL, &cx->params); |
464 | } | 468 | } |
465 | 469 | ||
466 | if (atomic_read(&cx->capturing) == 0) { | 470 | if (atomic_read(&cx->tot_capturing) == 0) { |
467 | clear_bit(CX18_F_I_EOS, &cx->i_flags); | 471 | clear_bit(CX18_F_I_EOS, &cx->i_flags); |
468 | write_reg(7, CX18_DSP0_INTERRUPT_MASK); | 472 | write_reg(7, CX18_DSP0_INTERRUPT_MASK); |
469 | } | 473 | } |
470 | 474 | ||
471 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle, | 475 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle, |
472 | (void *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem, | 476 | (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem, |
473 | (void *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem); | 477 | (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem); |
474 | 478 | ||
475 | list_for_each(p, &s->q_free.list) { | 479 | list_for_each(p, &s->q_free.list) { |
476 | struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list); | 480 | struct cx18_buffer *buf = list_entry(p, struct cx18_buffer, list); |
@@ -478,8 +482,8 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
478 | writel(buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr); | 482 | writel(buf->dma_handle, &cx->scb->cpu_mdl[buf->id].paddr); |
479 | writel(s->buf_size, &cx->scb->cpu_mdl[buf->id].length); | 483 | writel(s->buf_size, &cx->scb->cpu_mdl[buf->id].length); |
480 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, | 484 | cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, |
481 | (void *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, 1, | 485 | (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, |
482 | buf->id, s->buf_size); | 486 | 1, buf->id, s->buf_size); |
483 | } | 487 | } |
484 | /* begin_capture */ | 488 | /* begin_capture */ |
485 | if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { | 489 | if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) { |
@@ -489,7 +493,9 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s) | |||
489 | } | 493 | } |
490 | 494 | ||
491 | /* you're live! sit back and await interrupts :) */ | 495 | /* you're live! sit back and await interrupts :) */ |
492 | atomic_inc(&cx->capturing); | 496 | if (!ts) |
497 | atomic_inc(&cx->ana_capturing); | ||
498 | atomic_inc(&cx->tot_capturing); | ||
493 | return 0; | 499 | return 0; |
494 | } | 500 | } |
495 | 501 | ||
@@ -520,7 +526,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
520 | 526 | ||
521 | CX18_DEBUG_INFO("Stop Capture\n"); | 527 | CX18_DEBUG_INFO("Stop Capture\n"); |
522 | 528 | ||
523 | if (atomic_read(&cx->capturing) == 0) | 529 | if (atomic_read(&cx->tot_capturing) == 0) |
524 | return 0; | 530 | return 0; |
525 | 531 | ||
526 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) | 532 | if (s->type == CX18_ENC_STREAM_TYPE_MPG) |
@@ -534,7 +540,9 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
534 | CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n"); | 540 | CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n"); |
535 | } | 541 | } |
536 | 542 | ||
537 | atomic_dec(&cx->capturing); | 543 | if (s->type != CX18_ENC_STREAM_TYPE_TS) |
544 | atomic_dec(&cx->ana_capturing); | ||
545 | atomic_dec(&cx->tot_capturing); | ||
538 | 546 | ||
539 | /* Clear capture and no-read bits */ | 547 | /* Clear capture and no-read bits */ |
540 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); | 548 | clear_bit(CX18_F_S_STREAMING, &s->s_flags); |
@@ -542,7 +550,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end) | |||
542 | cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); | 550 | cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle); |
543 | s->handle = 0xffffffff; | 551 | s->handle = 0xffffffff; |
544 | 552 | ||
545 | if (atomic_read(&cx->capturing) > 0) | 553 | if (atomic_read(&cx->tot_capturing) > 0) |
546 | return 0; | 554 | return 0; |
547 | 555 | ||
548 | write_reg(5, CX18_DSP0_INTERRUPT_MASK); | 556 | write_reg(5, CX18_DSP0_INTERRUPT_MASK); |
diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h index 8c7ba7d2fa79..f327e947b24f 100644 --- a/drivers/media/video/cx18/cx18-streams.h +++ b/drivers/media/video/cx18/cx18-streams.h | |||
@@ -24,7 +24,7 @@ | |||
24 | u32 cx18_find_handle(struct cx18 *cx); | 24 | u32 cx18_find_handle(struct cx18 *cx); |
25 | int cx18_streams_setup(struct cx18 *cx); | 25 | int cx18_streams_setup(struct cx18 *cx); |
26 | int cx18_streams_register(struct cx18 *cx); | 26 | int cx18_streams_register(struct cx18 *cx); |
27 | void cx18_streams_cleanup(struct cx18 *cx); | 27 | void cx18_streams_cleanup(struct cx18 *cx, int unregister); |
28 | 28 | ||
29 | /* Capture related */ | 29 | /* Capture related */ |
30 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s); | 30 | int cx18_start_v4l2_encode_stream(struct cx18_stream *s); |
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index cadf936c3673..7bf14c9a15c7 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig | |||
@@ -1,18 +1,20 @@ | |||
1 | config VIDEO_CX23885 | 1 | config VIDEO_CX23885 |
2 | tristate "Conexant cx23885 (2388x successor) support" | 2 | tristate "Conexant cx23885 (2388x successor) support" |
3 | depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT | 3 | depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT |
4 | depends on HOTPLUG # due to FW_LOADER | ||
4 | select I2C_ALGOBIT | 5 | select I2C_ALGOBIT |
5 | select FW_LOADER | 6 | select FW_LOADER |
6 | select VIDEO_BTCX | 7 | select VIDEO_BTCX |
7 | select MEDIA_TUNER | 8 | select VIDEO_TUNER |
8 | select VIDEO_TVEEPROM | 9 | select VIDEO_TVEEPROM |
9 | select VIDEO_IR | 10 | select VIDEO_IR |
10 | select VIDEOBUF_DVB | 11 | select VIDEOBUF_DVB |
11 | select VIDEO_CX25840 | 12 | select VIDEO_CX25840 |
13 | select VIDEO_CX2341X | ||
14 | select DVB_DIB7000P if !DVB_FE_CUSTOMISE | ||
12 | select MEDIA_TUNER_MT2131 if !DVB_FE_CUSTOMISE | 15 | select MEDIA_TUNER_MT2131 if !DVB_FE_CUSTOMISE |
13 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE | 16 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE |
14 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 17 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
15 | select DVB_PLL if !DVB_FE_CUSTOMISE | ||
16 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE | 18 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE |
17 | select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE | 19 | select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE |
18 | select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE | 20 | select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE |
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 6ebf58724a01..20e05f230546 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c | |||
@@ -200,6 +200,10 @@ struct cx23885_subid cx23885_subids[] = { | |||
200 | .card = CX23885_BOARD_HAUPPAUGE_HVR1200, | 200 | .card = CX23885_BOARD_HAUPPAUGE_HVR1200, |
201 | }, { | 201 | }, { |
202 | .subvendor = 0x0070, | 202 | .subvendor = 0x0070, |
203 | .subdevice = 0x71d3, | ||
204 | .card = CX23885_BOARD_HAUPPAUGE_HVR1200, | ||
205 | }, { | ||
206 | .subvendor = 0x0070, | ||
203 | .subdevice = 0x8101, | 207 | .subdevice = 0x8101, |
204 | .card = CX23885_BOARD_HAUPPAUGE_HVR1700, | 208 | .card = CX23885_BOARD_HAUPPAUGE_HVR1700, |
205 | }, { | 209 | }, { |
@@ -245,6 +249,33 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) | |||
245 | /* Make sure we support the board model */ | 249 | /* Make sure we support the board model */ |
246 | switch (tv.model) | 250 | switch (tv.model) |
247 | { | 251 | { |
252 | case 71009: | ||
253 | /* WinTV-HVR1200 (PCIe, Retail, full height) | ||
254 | * DVB-T and basic analog */ | ||
255 | case 71359: | ||
256 | /* WinTV-HVR1200 (PCIe, OEM, half height) | ||
257 | * DVB-T and basic analog */ | ||
258 | case 71439: | ||
259 | /* WinTV-HVR1200 (PCIe, OEM, half height) | ||
260 | * DVB-T and basic analog */ | ||
261 | case 71449: | ||
262 | /* WinTV-HVR1200 (PCIe, OEM, full height) | ||
263 | * DVB-T and basic analog */ | ||
264 | case 71939: | ||
265 | /* WinTV-HVR1200 (PCIe, OEM, half height) | ||
266 | * DVB-T and basic analog */ | ||
267 | case 71949: | ||
268 | /* WinTV-HVR1200 (PCIe, OEM, full height) | ||
269 | * DVB-T and basic analog */ | ||
270 | case 71959: | ||
271 | /* WinTV-HVR1200 (PCIe, OEM, full height) | ||
272 | * DVB-T and basic analog */ | ||
273 | case 71979: | ||
274 | /* WinTV-HVR1200 (PCIe, OEM, half height) | ||
275 | * DVB-T and basic analog */ | ||
276 | case 71999: | ||
277 | /* WinTV-HVR1200 (PCIe, OEM, full height) | ||
278 | * DVB-T and basic analog */ | ||
248 | case 76601: /* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual channel ATSC and MPEG2 HW Encoder */ | 279 | case 76601: /* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual channel ATSC and MPEG2 HW Encoder */ |
249 | case 77001: /* WinTV-HVR1500 (Express Card, OEM, No IR, ATSC and Basic analog */ | 280 | case 77001: /* WinTV-HVR1500 (Express Card, OEM, No IR, ATSC and Basic analog */ |
250 | case 77011: /* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC and Basic analog */ | 281 | case 77011: /* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC and Basic analog */ |
@@ -263,8 +294,11 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) | |||
263 | case 80019: | 294 | case 80019: |
264 | /* WinTV-HVR1400 (Express Card, Retail, IR, | 295 | /* WinTV-HVR1400 (Express Card, Retail, IR, |
265 | * DVB-T and Basic analog */ | 296 | * DVB-T and Basic analog */ |
297 | case 81509: | ||
298 | /* WinTV-HVR1700 (PCIe, OEM, No IR, half height) | ||
299 | * DVB-T and MPEG2 HW Encoder */ | ||
266 | case 81519: | 300 | case 81519: |
267 | /* WinTV-HVR1700 (PCIe, Retail, No IR, half height, | 301 | /* WinTV-HVR1700 (PCIe, OEM, No IR, full height) |
268 | * DVB-T and MPEG2 HW Encoder */ | 302 | * DVB-T and MPEG2 HW Encoder */ |
269 | break; | 303 | break; |
270 | default: | 304 | default: |
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index f24abcd06dea..c4cc2f3b8876 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c | |||
@@ -823,7 +823,7 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev) | |||
823 | iounmap(dev->lmmio); | 823 | iounmap(dev->lmmio); |
824 | } | 824 | } |
825 | 825 | ||
826 | static u32* cx23885_risc_field(u32 *rp, struct scatterlist *sglist, | 826 | static __le32* cx23885_risc_field(__le32 *rp, struct scatterlist *sglist, |
827 | unsigned int offset, u32 sync_line, | 827 | unsigned int offset, u32 sync_line, |
828 | unsigned int bpl, unsigned int padding, | 828 | unsigned int bpl, unsigned int padding, |
829 | unsigned int lines) | 829 | unsigned int lines) |
@@ -883,7 +883,7 @@ int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | |||
883 | unsigned int padding, unsigned int lines) | 883 | unsigned int padding, unsigned int lines) |
884 | { | 884 | { |
885 | u32 instructions, fields; | 885 | u32 instructions, fields; |
886 | u32 *rp; | 886 | __le32 *rp; |
887 | int rc; | 887 | int rc; |
888 | 888 | ||
889 | fields = 0; | 889 | fields = 0; |
@@ -924,7 +924,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci, | |||
924 | unsigned int lines) | 924 | unsigned int lines) |
925 | { | 925 | { |
926 | u32 instructions; | 926 | u32 instructions; |
927 | u32 *rp; | 927 | __le32 *rp; |
928 | int rc; | 928 | int rc; |
929 | 929 | ||
930 | /* estimate risc mem: worst case is one write per page border + | 930 | /* estimate risc mem: worst case is one write per page border + |
@@ -951,7 +951,7 @@ static int cx23885_risc_databuffer(struct pci_dev *pci, | |||
951 | int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | 951 | int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, |
952 | u32 reg, u32 mask, u32 value) | 952 | u32 reg, u32 mask, u32 value) |
953 | { | 953 | { |
954 | u32 *rp; | 954 | __le32 *rp; |
955 | int rc; | 955 | int rc; |
956 | 956 | ||
957 | if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0) | 957 | if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0) |
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index f05649727b60..022aa391937a 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include "lgdt330x.h" | 37 | #include "lgdt330x.h" |
38 | #include "xc5000.h" | 38 | #include "xc5000.h" |
39 | #include "tda10048.h" | 39 | #include "tda10048.h" |
40 | #include "dvb-pll.h" | ||
41 | #include "tuner-xc2028.h" | 40 | #include "tuner-xc2028.h" |
42 | #include "tuner-simple.h" | 41 | #include "tuner-simple.h" |
43 | #include "dib7000p.h" | 42 | #include "dib7000p.h" |
@@ -385,12 +384,10 @@ static int dvb_register(struct cx23885_tsport *port) | |||
385 | port->dvb.frontend = dvb_attach(s5h1409_attach, | 384 | port->dvb.frontend = dvb_attach(s5h1409_attach, |
386 | &hauppauge_hvr1500q_config, | 385 | &hauppauge_hvr1500q_config, |
387 | &dev->i2c_bus[0].i2c_adap); | 386 | &dev->i2c_bus[0].i2c_adap); |
388 | if (port->dvb.frontend != NULL) { | 387 | if (port->dvb.frontend != NULL) |
389 | hauppauge_hvr1500q_tunerconfig.priv = i2c_bus; | ||
390 | dvb_attach(xc5000_attach, port->dvb.frontend, | 388 | dvb_attach(xc5000_attach, port->dvb.frontend, |
391 | &i2c_bus->i2c_adap, | 389 | &i2c_bus->i2c_adap, |
392 | &hauppauge_hvr1500q_tunerconfig); | 390 | &hauppauge_hvr1500q_tunerconfig, i2c_bus); |
393 | } | ||
394 | break; | 391 | break; |
395 | case CX23885_BOARD_HAUPPAUGE_HVR1500: | 392 | case CX23885_BOARD_HAUPPAUGE_HVR1500: |
396 | i2c_bus = &dev->i2c_bus[1]; | 393 | i2c_bus = &dev->i2c_bus[1]; |
diff --git a/drivers/media/video/cx25840/Kconfig b/drivers/media/video/cx25840/Kconfig index 7cf29a03ed63..448f4cd0ce34 100644 --- a/drivers/media/video/cx25840/Kconfig +++ b/drivers/media/video/cx25840/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config VIDEO_CX25840 | 1 | config VIDEO_CX25840 |
2 | tristate "Conexant CX2584x audio/video decoders" | 2 | tristate "Conexant CX2584x audio/video decoders" |
3 | depends on VIDEO_V4L2 && I2C && EXPERIMENTAL | 3 | depends on VIDEO_V4L2 && I2C && EXPERIMENTAL |
4 | depends on HOTPLUG # due to FW_LOADER | ||
4 | select FW_LOADER | 5 | select FW_LOADER |
5 | ---help--- | 6 | ---help--- |
6 | Support for the Conexant CX2584x audio/video decoders. | 7 | Support for the Conexant CX2584x audio/video decoders. |
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 88823810497c..1da6f134888d 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -433,7 +433,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
433 | int chroma = vid_input & 0xf00; | 433 | int chroma = vid_input & 0xf00; |
434 | 434 | ||
435 | if ((vid_input & ~0xff0) || | 435 | if ((vid_input & ~0xff0) || |
436 | luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA4 || | 436 | luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA8 || |
437 | chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) { | 437 | chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) { |
438 | v4l_err(client, "0x%04x is not a valid video input!\n", | 438 | v4l_err(client, "0x%04x is not a valid video input!\n", |
439 | vid_input); | 439 | vid_input); |
@@ -1284,10 +1284,17 @@ static int cx25840_remove(struct i2c_client *client) | |||
1284 | return 0; | 1284 | return 0; |
1285 | } | 1285 | } |
1286 | 1286 | ||
1287 | static const struct i2c_device_id cx25840_id[] = { | ||
1288 | { "cx25840", 0 }, | ||
1289 | { } | ||
1290 | }; | ||
1291 | MODULE_DEVICE_TABLE(i2c, cx25840_id); | ||
1292 | |||
1287 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 1293 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
1288 | .name = "cx25840", | 1294 | .name = "cx25840", |
1289 | .driverid = I2C_DRIVERID_CX25840, | 1295 | .driverid = I2C_DRIVERID_CX25840, |
1290 | .command = cx25840_command, | 1296 | .command = cx25840_command, |
1291 | .probe = cx25840_probe, | 1297 | .probe = cx25840_probe, |
1292 | .remove = cx25840_remove, | 1298 | .remove = cx25840_remove, |
1299 | .id_table = cx25840_id, | ||
1293 | }; | 1300 | }; |
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index b0d7d6a7a4cc..10e20d8196dc 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig | |||
@@ -2,10 +2,9 @@ config VIDEO_CX88 | |||
2 | tristate "Conexant 2388x (bt878 successor) support" | 2 | tristate "Conexant 2388x (bt878 successor) support" |
3 | depends on VIDEO_DEV && PCI && I2C && INPUT | 3 | depends on VIDEO_DEV && PCI && I2C && INPUT |
4 | select I2C_ALGOBIT | 4 | select I2C_ALGOBIT |
5 | select FW_LOADER | ||
6 | select VIDEO_BTCX | 5 | select VIDEO_BTCX |
7 | select VIDEOBUF_DMA_SG | 6 | select VIDEOBUF_DMA_SG |
8 | select MEDIA_TUNER | 7 | select VIDEO_TUNER |
9 | select VIDEO_TVEEPROM | 8 | select VIDEO_TVEEPROM |
10 | select VIDEO_IR | 9 | select VIDEO_IR |
11 | select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO | 10 | select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO |
@@ -34,8 +33,9 @@ config VIDEO_CX88_ALSA | |||
34 | 33 | ||
35 | config VIDEO_CX88_BLACKBIRD | 34 | config VIDEO_CX88_BLACKBIRD |
36 | tristate "Blackbird MPEG encoder support (cx2388x + cx23416)" | 35 | tristate "Blackbird MPEG encoder support (cx2388x + cx23416)" |
37 | depends on VIDEO_CX88 | 36 | depends on VIDEO_CX88 && HOTPLUG |
38 | select VIDEO_CX2341X | 37 | select VIDEO_CX2341X |
38 | select FW_LOADER | ||
39 | ---help--- | 39 | ---help--- |
40 | This adds support for MPEG encoder cards based on the | 40 | This adds support for MPEG encoder cards based on the |
41 | Blackbird reference design, using the Conexant 2388x | 41 | Blackbird reference design, using the Conexant 2388x |
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index e976fc6bef7c..80c8883e54b5 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c | |||
@@ -332,6 +332,12 @@ static int snd_cx88_pcm_open(struct snd_pcm_substream *substream) | |||
332 | struct snd_pcm_runtime *runtime = substream->runtime; | 332 | struct snd_pcm_runtime *runtime = substream->runtime; |
333 | int err; | 333 | int err; |
334 | 334 | ||
335 | if (!chip) { | ||
336 | printk(KERN_ERR "BUG: cx88 can't find device struct." | ||
337 | " Can't proceed with open\n"); | ||
338 | return -ENODEV; | ||
339 | } | ||
340 | |||
335 | err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS); | 341 | err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS); |
336 | if (err < 0) | 342 | if (err < 0) |
337 | goto _error; | 343 | goto _error; |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index aeba26dc0a37..fa6d398e97b9 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -1493,10 +1493,16 @@ static const struct cx88_board cx88_boards[] = { | |||
1493 | }, | 1493 | }, |
1494 | }, | 1494 | }, |
1495 | [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { | 1495 | [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { |
1496 | .name = "PowerColor Real Angel 330", | 1496 | .name = "PowerColor RA330", /* Long names may confuse LIRC. */ |
1497 | .tuner_type = TUNER_XC2028, | 1497 | .tuner_type = TUNER_XC2028, |
1498 | .tuner_addr = 0x61, | 1498 | .tuner_addr = 0x61, |
1499 | .input = { { | 1499 | .input = { { |
1500 | .type = CX88_VMUX_DEBUG, | ||
1501 | .vmux = 3, /* Due to the way the cx88 driver is written, */ | ||
1502 | .gpio0 = 0x00ff, /* there is no way to deactivate audio pass- */ | ||
1503 | .gpio1 = 0xf39d, /* through without this entry. Furthermore, if */ | ||
1504 | .gpio3 = 0x0000, /* the TV mux entry is first, you get audio */ | ||
1505 | }, { /* from the tuner on boot for a little while. */ | ||
1500 | .type = CX88_VMUX_TELEVISION, | 1506 | .type = CX88_VMUX_TELEVISION, |
1501 | .vmux = 0, | 1507 | .vmux = 0, |
1502 | .gpio0 = 0x00ff, | 1508 | .gpio0 = 0x00ff, |
@@ -2424,8 +2430,9 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) | |||
2424 | 2430 | ||
2425 | switch (core->boardnr) { | 2431 | switch (core->boardnr) { |
2426 | case CX88_BOARD_POWERCOLOR_REAL_ANGEL: | 2432 | case CX88_BOARD_POWERCOLOR_REAL_ANGEL: |
2427 | /* Doesn't work with firmware version 2.7 */ | 2433 | /* Now works with firmware version 2.7 */ |
2428 | ctl->fname = "xc3028-v25.fw"; | 2434 | if (core->i2c_algo.udelay < 16) |
2435 | core->i2c_algo.udelay = 16; | ||
2429 | break; | 2436 | break; |
2430 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: | 2437 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: |
2431 | ctl->scode_table = XC3028_FE_ZARLINK456; | 2438 | ctl->scode_table = XC3028_FE_ZARLINK456; |
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index c4d1aff1fdb4..60eeda3057e9 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c | |||
@@ -70,7 +70,7 @@ static DEFINE_MUTEX(devlist); | |||
70 | 70 | ||
71 | /* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be | 71 | /* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be |
72 | generated _after_ lpi lines are transferred. */ | 72 | generated _after_ lpi lines are transferred. */ |
73 | static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, | 73 | static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist, |
74 | unsigned int offset, u32 sync_line, | 74 | unsigned int offset, u32 sync_line, |
75 | unsigned int bpl, unsigned int padding, | 75 | unsigned int bpl, unsigned int padding, |
76 | unsigned int lines, unsigned int lpi) | 76 | unsigned int lines, unsigned int lpi) |
@@ -130,7 +130,7 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | |||
130 | unsigned int bpl, unsigned int padding, unsigned int lines) | 130 | unsigned int bpl, unsigned int padding, unsigned int lines) |
131 | { | 131 | { |
132 | u32 instructions,fields; | 132 | u32 instructions,fields; |
133 | u32 *rp; | 133 | __le32 *rp; |
134 | int rc; | 134 | int rc; |
135 | 135 | ||
136 | fields = 0; | 136 | fields = 0; |
@@ -168,7 +168,7 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, | |||
168 | unsigned int lines, unsigned int lpi) | 168 | unsigned int lines, unsigned int lpi) |
169 | { | 169 | { |
170 | u32 instructions; | 170 | u32 instructions; |
171 | u32 *rp; | 171 | __le32 *rp; |
172 | int rc; | 172 | int rc; |
173 | 173 | ||
174 | /* estimate risc mem: worst case is one write per page border + | 174 | /* estimate risc mem: worst case is one write per page border + |
@@ -193,7 +193,7 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, | |||
193 | int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | 193 | int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, |
194 | u32 reg, u32 mask, u32 value) | 194 | u32 reg, u32 mask, u32 value) |
195 | { | 195 | { |
196 | u32 *rp; | 196 | __le32 *rp; |
197 | int rc; | 197 | int rc; |
198 | 198 | ||
199 | if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0) | 199 | if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0) |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 1c7fe6862a60..d96173ff1dba 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -509,9 +509,6 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) | |||
509 | if (!fe) { | 509 | if (!fe) { |
510 | printk(KERN_ERR "%s/2: xc3028 attach failed\n", | 510 | printk(KERN_ERR "%s/2: xc3028 attach failed\n", |
511 | dev->core->name); | 511 | dev->core->name); |
512 | dvb_frontend_detach(dev->dvb.frontend); | ||
513 | dvb_unregister_frontend(dev->dvb.frontend); | ||
514 | dev->dvb.frontend = NULL; | ||
515 | return -EINVAL; | 512 | return -EINVAL; |
516 | } | 513 | } |
517 | 514 | ||
@@ -523,20 +520,23 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) | |||
523 | 520 | ||
524 | static int dvb_register(struct cx8802_dev *dev) | 521 | static int dvb_register(struct cx8802_dev *dev) |
525 | { | 522 | { |
523 | struct cx88_core *core = dev->core; | ||
524 | |||
526 | /* init struct videobuf_dvb */ | 525 | /* init struct videobuf_dvb */ |
527 | dev->dvb.name = dev->core->name; | 526 | dev->dvb.name = core->name; |
528 | dev->ts_gen_cntrl = 0x0c; | 527 | dev->ts_gen_cntrl = 0x0c; |
529 | 528 | ||
530 | /* init frontend */ | 529 | /* init frontend */ |
531 | switch (dev->core->boardnr) { | 530 | switch (core->boardnr) { |
532 | case CX88_BOARD_HAUPPAUGE_DVB_T1: | 531 | case CX88_BOARD_HAUPPAUGE_DVB_T1: |
533 | dev->dvb.frontend = dvb_attach(cx22702_attach, | 532 | dev->dvb.frontend = dvb_attach(cx22702_attach, |
534 | &connexant_refboard_config, | 533 | &connexant_refboard_config, |
535 | &dev->core->i2c_adap); | 534 | &core->i2c_adap); |
536 | if (dev->dvb.frontend != NULL) { | 535 | if (dev->dvb.frontend != NULL) { |
537 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 536 | if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, |
538 | &dev->core->i2c_adap, | 537 | 0x61, &core->i2c_adap, |
539 | DVB_PLL_THOMSON_DTT759X); | 538 | DVB_PLL_THOMSON_DTT759X)) |
539 | goto frontend_detach; | ||
540 | } | 540 | } |
541 | break; | 541 | break; |
542 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: | 542 | case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: |
@@ -545,11 +545,12 @@ static int dvb_register(struct cx8802_dev *dev) | |||
545 | case CX88_BOARD_WINFAST_DTV1000: | 545 | case CX88_BOARD_WINFAST_DTV1000: |
546 | dev->dvb.frontend = dvb_attach(cx22702_attach, | 546 | dev->dvb.frontend = dvb_attach(cx22702_attach, |
547 | &connexant_refboard_config, | 547 | &connexant_refboard_config, |
548 | &dev->core->i2c_adap); | 548 | &core->i2c_adap); |
549 | if (dev->dvb.frontend != NULL) { | 549 | if (dev->dvb.frontend != NULL) { |
550 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, | 550 | if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, |
551 | &dev->core->i2c_adap, | 551 | 0x60, &core->i2c_adap, |
552 | DVB_PLL_THOMSON_DTT7579); | 552 | DVB_PLL_THOMSON_DTT7579)) |
553 | goto frontend_detach; | ||
553 | } | 554 | } |
554 | break; | 555 | break; |
555 | case CX88_BOARD_WINFAST_DTV2000H: | 556 | case CX88_BOARD_WINFAST_DTV2000H: |
@@ -559,29 +560,32 @@ static int dvb_register(struct cx8802_dev *dev) | |||
559 | case CX88_BOARD_HAUPPAUGE_HVR3000: | 560 | case CX88_BOARD_HAUPPAUGE_HVR3000: |
560 | dev->dvb.frontend = dvb_attach(cx22702_attach, | 561 | dev->dvb.frontend = dvb_attach(cx22702_attach, |
561 | &hauppauge_hvr_config, | 562 | &hauppauge_hvr_config, |
562 | &dev->core->i2c_adap); | 563 | &core->i2c_adap); |
563 | if (dev->dvb.frontend != NULL) { | 564 | if (dev->dvb.frontend != NULL) { |
564 | dvb_attach(simple_tuner_attach, dev->dvb.frontend, | 565 | if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, |
565 | &dev->core->i2c_adap, 0x61, | 566 | &core->i2c_adap, 0x61, |
566 | TUNER_PHILIPS_FMD1216ME_MK3); | 567 | TUNER_PHILIPS_FMD1216ME_MK3)) |
568 | goto frontend_detach; | ||
567 | } | 569 | } |
568 | break; | 570 | break; |
569 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: | 571 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: |
570 | dev->dvb.frontend = dvb_attach(mt352_attach, | 572 | dev->dvb.frontend = dvb_attach(mt352_attach, |
571 | &dvico_fusionhdtv, | 573 | &dvico_fusionhdtv, |
572 | &dev->core->i2c_adap); | 574 | &core->i2c_adap); |
573 | if (dev->dvb.frontend != NULL) { | 575 | if (dev->dvb.frontend != NULL) { |
574 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, | 576 | if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, |
575 | NULL, DVB_PLL_THOMSON_DTT7579); | 577 | 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) |
578 | goto frontend_detach; | ||
576 | break; | 579 | break; |
577 | } | 580 | } |
578 | /* ZL10353 replaces MT352 on later cards */ | 581 | /* ZL10353 replaces MT352 on later cards */ |
579 | dev->dvb.frontend = dvb_attach(zl10353_attach, | 582 | dev->dvb.frontend = dvb_attach(zl10353_attach, |
580 | &dvico_fusionhdtv_plus_v1_1, | 583 | &dvico_fusionhdtv_plus_v1_1, |
581 | &dev->core->i2c_adap); | 584 | &core->i2c_adap); |
582 | if (dev->dvb.frontend != NULL) { | 585 | if (dev->dvb.frontend != NULL) { |
583 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, | 586 | if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, |
584 | NULL, DVB_PLL_THOMSON_DTT7579); | 587 | 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) |
588 | goto frontend_detach; | ||
585 | } | 589 | } |
586 | break; | 590 | break; |
587 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: | 591 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: |
@@ -589,28 +593,31 @@ static int dvb_register(struct cx8802_dev *dev) | |||
589 | * compatible, with a slightly different MT352 AGC gain. */ | 593 | * compatible, with a slightly different MT352 AGC gain. */ |
590 | dev->dvb.frontend = dvb_attach(mt352_attach, | 594 | dev->dvb.frontend = dvb_attach(mt352_attach, |
591 | &dvico_fusionhdtv_dual, | 595 | &dvico_fusionhdtv_dual, |
592 | &dev->core->i2c_adap); | 596 | &core->i2c_adap); |
593 | if (dev->dvb.frontend != NULL) { | 597 | if (dev->dvb.frontend != NULL) { |
594 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 598 | if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, |
595 | NULL, DVB_PLL_THOMSON_DTT7579); | 599 | 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) |
600 | goto frontend_detach; | ||
596 | break; | 601 | break; |
597 | } | 602 | } |
598 | /* ZL10353 replaces MT352 on later cards */ | 603 | /* ZL10353 replaces MT352 on later cards */ |
599 | dev->dvb.frontend = dvb_attach(zl10353_attach, | 604 | dev->dvb.frontend = dvb_attach(zl10353_attach, |
600 | &dvico_fusionhdtv_plus_v1_1, | 605 | &dvico_fusionhdtv_plus_v1_1, |
601 | &dev->core->i2c_adap); | 606 | &core->i2c_adap); |
602 | if (dev->dvb.frontend != NULL) { | 607 | if (dev->dvb.frontend != NULL) { |
603 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 608 | if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, |
604 | NULL, DVB_PLL_THOMSON_DTT7579); | 609 | 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) |
610 | goto frontend_detach; | ||
605 | } | 611 | } |
606 | break; | 612 | break; |
607 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: | 613 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: |
608 | dev->dvb.frontend = dvb_attach(mt352_attach, | 614 | dev->dvb.frontend = dvb_attach(mt352_attach, |
609 | &dvico_fusionhdtv, | 615 | &dvico_fusionhdtv, |
610 | &dev->core->i2c_adap); | 616 | &core->i2c_adap); |
611 | if (dev->dvb.frontend != NULL) { | 617 | if (dev->dvb.frontend != NULL) { |
612 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 618 | if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, |
613 | NULL, DVB_PLL_LG_Z201); | 619 | 0x61, NULL, DVB_PLL_LG_Z201)) |
620 | goto frontend_detach; | ||
614 | } | 621 | } |
615 | break; | 622 | break; |
616 | case CX88_BOARD_KWORLD_DVB_T: | 623 | case CX88_BOARD_KWORLD_DVB_T: |
@@ -618,10 +625,11 @@ static int dvb_register(struct cx8802_dev *dev) | |||
618 | case CX88_BOARD_ADSTECH_DVB_T_PCI: | 625 | case CX88_BOARD_ADSTECH_DVB_T_PCI: |
619 | dev->dvb.frontend = dvb_attach(mt352_attach, | 626 | dev->dvb.frontend = dvb_attach(mt352_attach, |
620 | &dntv_live_dvbt_config, | 627 | &dntv_live_dvbt_config, |
621 | &dev->core->i2c_adap); | 628 | &core->i2c_adap); |
622 | if (dev->dvb.frontend != NULL) { | 629 | if (dev->dvb.frontend != NULL) { |
623 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 630 | if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, |
624 | NULL, DVB_PLL_UNKNOWN_1); | 631 | 0x61, NULL, DVB_PLL_UNKNOWN_1)) |
632 | goto frontend_detach; | ||
625 | } | 633 | } |
626 | break; | 634 | break; |
627 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: | 635 | case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: |
@@ -630,32 +638,35 @@ static int dvb_register(struct cx8802_dev *dev) | |||
630 | dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, | 638 | dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, |
631 | &dev->vp3054->adap); | 639 | &dev->vp3054->adap); |
632 | if (dev->dvb.frontend != NULL) { | 640 | if (dev->dvb.frontend != NULL) { |
633 | dvb_attach(simple_tuner_attach, dev->dvb.frontend, | 641 | if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, |
634 | &dev->core->i2c_adap, 0x61, | 642 | &core->i2c_adap, 0x61, |
635 | TUNER_PHILIPS_FMD1216ME_MK3); | 643 | TUNER_PHILIPS_FMD1216ME_MK3)) |
644 | goto frontend_detach; | ||
636 | } | 645 | } |
637 | #else | 646 | #else |
638 | printk(KERN_ERR "%s/2: built without vp3054 support\n", dev->core->name); | 647 | printk(KERN_ERR "%s/2: built without vp3054 support\n", |
648 | core->name); | ||
639 | #endif | 649 | #endif |
640 | break; | 650 | break; |
641 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: | 651 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: |
642 | dev->dvb.frontend = dvb_attach(zl10353_attach, | 652 | dev->dvb.frontend = dvb_attach(zl10353_attach, |
643 | &dvico_fusionhdtv_hybrid, | 653 | &dvico_fusionhdtv_hybrid, |
644 | &dev->core->i2c_adap); | 654 | &core->i2c_adap); |
645 | if (dev->dvb.frontend != NULL) { | 655 | if (dev->dvb.frontend != NULL) { |
646 | dvb_attach(simple_tuner_attach, dev->dvb.frontend, | 656 | if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, |
647 | &dev->core->i2c_adap, 0x61, | 657 | &core->i2c_adap, 0x61, |
648 | TUNER_THOMSON_FE6600); | 658 | TUNER_THOMSON_FE6600)) |
659 | goto frontend_detach; | ||
649 | } | 660 | } |
650 | break; | 661 | break; |
651 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: | 662 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: |
652 | dev->dvb.frontend = dvb_attach(zl10353_attach, | 663 | dev->dvb.frontend = dvb_attach(zl10353_attach, |
653 | &dvico_fusionhdtv_xc3028, | 664 | &dvico_fusionhdtv_xc3028, |
654 | &dev->core->i2c_adap); | 665 | &core->i2c_adap); |
655 | if (dev->dvb.frontend == NULL) | 666 | if (dev->dvb.frontend == NULL) |
656 | dev->dvb.frontend = dvb_attach(mt352_attach, | 667 | dev->dvb.frontend = dvb_attach(mt352_attach, |
657 | &dvico_fusionhdtv_mt352_xc3028, | 668 | &dvico_fusionhdtv_mt352_xc3028, |
658 | &dev->core->i2c_adap); | 669 | &core->i2c_adap); |
659 | /* | 670 | /* |
660 | * On this board, the demod provides the I2C bus pullup. | 671 | * On this board, the demod provides the I2C bus pullup. |
661 | * We must not permit gate_ctrl to be performed, or | 672 | * We must not permit gate_ctrl to be performed, or |
@@ -668,19 +679,18 @@ static int dvb_register(struct cx8802_dev *dev) | |||
668 | break; | 679 | break; |
669 | case CX88_BOARD_PCHDTV_HD3000: | 680 | case CX88_BOARD_PCHDTV_HD3000: |
670 | dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, | 681 | dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, |
671 | &dev->core->i2c_adap); | 682 | &core->i2c_adap); |
672 | if (dev->dvb.frontend != NULL) { | 683 | if (dev->dvb.frontend != NULL) { |
673 | dvb_attach(simple_tuner_attach, dev->dvb.frontend, | 684 | if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, |
674 | &dev->core->i2c_adap, 0x61, | 685 | &core->i2c_adap, 0x61, |
675 | TUNER_THOMSON_DTT761X); | 686 | TUNER_THOMSON_DTT761X)) |
687 | goto frontend_detach; | ||
676 | } | 688 | } |
677 | break; | 689 | break; |
678 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: | 690 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: |
679 | dev->ts_gen_cntrl = 0x08; | 691 | dev->ts_gen_cntrl = 0x08; |
680 | { | ||
681 | /* Do a hardware reset of chip before using it. */ | ||
682 | struct cx88_core *core = dev->core; | ||
683 | 692 | ||
693 | /* Do a hardware reset of chip before using it. */ | ||
684 | cx_clear(MO_GP0_IO, 1); | 694 | cx_clear(MO_GP0_IO, 1); |
685 | mdelay(100); | 695 | mdelay(100); |
686 | cx_set(MO_GP0_IO, 1); | 696 | cx_set(MO_GP0_IO, 1); |
@@ -690,139 +700,137 @@ static int dvb_register(struct cx8802_dev *dev) | |||
690 | fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; | 700 | fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; |
691 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, | 701 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, |
692 | &fusionhdtv_3_gold, | 702 | &fusionhdtv_3_gold, |
693 | &dev->core->i2c_adap); | 703 | &core->i2c_adap); |
694 | if (dev->dvb.frontend != NULL) { | 704 | if (dev->dvb.frontend != NULL) { |
695 | dvb_attach(simple_tuner_attach, dev->dvb.frontend, | 705 | if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, |
696 | &dev->core->i2c_adap, 0x61, | 706 | &core->i2c_adap, 0x61, |
697 | TUNER_MICROTUNE_4042FI5); | 707 | TUNER_MICROTUNE_4042FI5)) |
698 | } | 708 | goto frontend_detach; |
699 | } | 709 | } |
700 | break; | 710 | break; |
701 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: | 711 | case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: |
702 | dev->ts_gen_cntrl = 0x08; | 712 | dev->ts_gen_cntrl = 0x08; |
703 | { | ||
704 | /* Do a hardware reset of chip before using it. */ | ||
705 | struct cx88_core *core = dev->core; | ||
706 | 713 | ||
714 | /* Do a hardware reset of chip before using it. */ | ||
707 | cx_clear(MO_GP0_IO, 1); | 715 | cx_clear(MO_GP0_IO, 1); |
708 | mdelay(100); | 716 | mdelay(100); |
709 | cx_set(MO_GP0_IO, 9); | 717 | cx_set(MO_GP0_IO, 9); |
710 | mdelay(200); | 718 | mdelay(200); |
711 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, | 719 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, |
712 | &fusionhdtv_3_gold, | 720 | &fusionhdtv_3_gold, |
713 | &dev->core->i2c_adap); | 721 | &core->i2c_adap); |
714 | if (dev->dvb.frontend != NULL) { | 722 | if (dev->dvb.frontend != NULL) { |
715 | dvb_attach(simple_tuner_attach, dev->dvb.frontend, | 723 | if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, |
716 | &dev->core->i2c_adap, 0x61, | 724 | &core->i2c_adap, 0x61, |
717 | TUNER_THOMSON_DTT761X); | 725 | TUNER_THOMSON_DTT761X)) |
718 | } | 726 | goto frontend_detach; |
719 | } | 727 | } |
720 | break; | 728 | break; |
721 | case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: | 729 | case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: |
722 | dev->ts_gen_cntrl = 0x08; | 730 | dev->ts_gen_cntrl = 0x08; |
723 | { | ||
724 | /* Do a hardware reset of chip before using it. */ | ||
725 | struct cx88_core *core = dev->core; | ||
726 | 731 | ||
732 | /* Do a hardware reset of chip before using it. */ | ||
727 | cx_clear(MO_GP0_IO, 1); | 733 | cx_clear(MO_GP0_IO, 1); |
728 | mdelay(100); | 734 | mdelay(100); |
729 | cx_set(MO_GP0_IO, 1); | 735 | cx_set(MO_GP0_IO, 1); |
730 | mdelay(200); | 736 | mdelay(200); |
731 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, | 737 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, |
732 | &fusionhdtv_5_gold, | 738 | &fusionhdtv_5_gold, |
733 | &dev->core->i2c_adap); | 739 | &core->i2c_adap); |
734 | if (dev->dvb.frontend != NULL) { | 740 | if (dev->dvb.frontend != NULL) { |
735 | dvb_attach(simple_tuner_attach, dev->dvb.frontend, | 741 | if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, |
736 | &dev->core->i2c_adap, 0x61, | 742 | &core->i2c_adap, 0x61, |
737 | TUNER_LG_TDVS_H06XF); | 743 | TUNER_LG_TDVS_H06XF)) |
738 | dvb_attach(tda9887_attach, dev->dvb.frontend, | 744 | goto frontend_detach; |
739 | &dev->core->i2c_adap, 0x43); | 745 | if (!dvb_attach(tda9887_attach, dev->dvb.frontend, |
740 | } | 746 | &core->i2c_adap, 0x43)) |
747 | goto frontend_detach; | ||
741 | } | 748 | } |
742 | break; | 749 | break; |
743 | case CX88_BOARD_PCHDTV_HD5500: | 750 | case CX88_BOARD_PCHDTV_HD5500: |
744 | dev->ts_gen_cntrl = 0x08; | 751 | dev->ts_gen_cntrl = 0x08; |
745 | { | ||
746 | /* Do a hardware reset of chip before using it. */ | ||
747 | struct cx88_core *core = dev->core; | ||
748 | 752 | ||
753 | /* Do a hardware reset of chip before using it. */ | ||
749 | cx_clear(MO_GP0_IO, 1); | 754 | cx_clear(MO_GP0_IO, 1); |
750 | mdelay(100); | 755 | mdelay(100); |
751 | cx_set(MO_GP0_IO, 1); | 756 | cx_set(MO_GP0_IO, 1); |
752 | mdelay(200); | 757 | mdelay(200); |
753 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, | 758 | dev->dvb.frontend = dvb_attach(lgdt330x_attach, |
754 | &pchdtv_hd5500, | 759 | &pchdtv_hd5500, |
755 | &dev->core->i2c_adap); | 760 | &core->i2c_adap); |
756 | if (dev->dvb.frontend != NULL) { | 761 | if (dev->dvb.frontend != NULL) { |
757 | dvb_attach(simple_tuner_attach, dev->dvb.frontend, | 762 | if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, |
758 | &dev->core->i2c_adap, 0x61, | 763 | &core->i2c_adap, 0x61, |
759 | TUNER_LG_TDVS_H06XF); | 764 | TUNER_LG_TDVS_H06XF)) |
760 | dvb_attach(tda9887_attach, dev->dvb.frontend, | 765 | goto frontend_detach; |
761 | &dev->core->i2c_adap, 0x43); | 766 | if (!dvb_attach(tda9887_attach, dev->dvb.frontend, |
762 | } | 767 | &core->i2c_adap, 0x43)) |
768 | goto frontend_detach; | ||
763 | } | 769 | } |
764 | break; | 770 | break; |
765 | case CX88_BOARD_ATI_HDTVWONDER: | 771 | case CX88_BOARD_ATI_HDTVWONDER: |
766 | dev->dvb.frontend = dvb_attach(nxt200x_attach, | 772 | dev->dvb.frontend = dvb_attach(nxt200x_attach, |
767 | &ati_hdtvwonder, | 773 | &ati_hdtvwonder, |
768 | &dev->core->i2c_adap); | 774 | &core->i2c_adap); |
769 | if (dev->dvb.frontend != NULL) { | 775 | if (dev->dvb.frontend != NULL) { |
770 | dvb_attach(simple_tuner_attach, dev->dvb.frontend, | 776 | if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, |
771 | &dev->core->i2c_adap, 0x61, | 777 | &core->i2c_adap, 0x61, |
772 | TUNER_PHILIPS_TUV1236D); | 778 | TUNER_PHILIPS_TUV1236D)) |
779 | goto frontend_detach; | ||
773 | } | 780 | } |
774 | break; | 781 | break; |
775 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: | 782 | case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: |
776 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: | 783 | case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: |
777 | dev->dvb.frontend = dvb_attach(cx24123_attach, | 784 | dev->dvb.frontend = dvb_attach(cx24123_attach, |
778 | &hauppauge_novas_config, | 785 | &hauppauge_novas_config, |
779 | &dev->core->i2c_adap); | 786 | &core->i2c_adap); |
780 | if (dev->dvb.frontend) { | 787 | if (dev->dvb.frontend) { |
781 | dvb_attach(isl6421_attach, dev->dvb.frontend, | 788 | if (!dvb_attach(isl6421_attach, dev->dvb.frontend, |
782 | &dev->core->i2c_adap, 0x08, 0x00, 0x00); | 789 | &core->i2c_adap, 0x08, 0x00, 0x00)) |
790 | goto frontend_detach; | ||
783 | } | 791 | } |
784 | break; | 792 | break; |
785 | case CX88_BOARD_KWORLD_DVBS_100: | 793 | case CX88_BOARD_KWORLD_DVBS_100: |
786 | dev->dvb.frontend = dvb_attach(cx24123_attach, | 794 | dev->dvb.frontend = dvb_attach(cx24123_attach, |
787 | &kworld_dvbs_100_config, | 795 | &kworld_dvbs_100_config, |
788 | &dev->core->i2c_adap); | 796 | &core->i2c_adap); |
789 | if (dev->dvb.frontend) { | 797 | if (dev->dvb.frontend) { |
790 | dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; | 798 | core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; |
791 | dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; | 799 | dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; |
792 | } | 800 | } |
793 | break; | 801 | break; |
794 | case CX88_BOARD_GENIATECH_DVBS: | 802 | case CX88_BOARD_GENIATECH_DVBS: |
795 | dev->dvb.frontend = dvb_attach(cx24123_attach, | 803 | dev->dvb.frontend = dvb_attach(cx24123_attach, |
796 | &geniatech_dvbs_config, | 804 | &geniatech_dvbs_config, |
797 | &dev->core->i2c_adap); | 805 | &core->i2c_adap); |
798 | if (dev->dvb.frontend) { | 806 | if (dev->dvb.frontend) { |
799 | dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; | 807 | core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; |
800 | dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; | 808 | dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; |
801 | } | 809 | } |
802 | break; | 810 | break; |
803 | case CX88_BOARD_PINNACLE_PCTV_HD_800i: | 811 | case CX88_BOARD_PINNACLE_PCTV_HD_800i: |
804 | dev->dvb.frontend = dvb_attach(s5h1409_attach, | 812 | dev->dvb.frontend = dvb_attach(s5h1409_attach, |
805 | &pinnacle_pctv_hd_800i_config, | 813 | &pinnacle_pctv_hd_800i_config, |
806 | &dev->core->i2c_adap); | 814 | &core->i2c_adap); |
807 | if (dev->dvb.frontend != NULL) { | 815 | if (dev->dvb.frontend != NULL) { |
808 | /* tuner_config.video_dev must point to | 816 | /* tuner_config.video_dev must point to |
809 | * i2c_adap.algo_data | 817 | * i2c_adap.algo_data |
810 | */ | 818 | */ |
811 | pinnacle_pctv_hd_800i_tuner_config.priv = | 819 | if (!dvb_attach(xc5000_attach, dev->dvb.frontend, |
812 | dev->core->i2c_adap.algo_data; | 820 | &core->i2c_adap, |
813 | dvb_attach(xc5000_attach, dev->dvb.frontend, | 821 | &pinnacle_pctv_hd_800i_tuner_config, |
814 | &dev->core->i2c_adap, | 822 | core->i2c_adap.algo_data)) |
815 | &pinnacle_pctv_hd_800i_tuner_config); | 823 | goto frontend_detach; |
816 | } | 824 | } |
817 | break; | 825 | break; |
818 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: | 826 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: |
819 | dev->dvb.frontend = dvb_attach(s5h1409_attach, | 827 | dev->dvb.frontend = dvb_attach(s5h1409_attach, |
820 | &dvico_hdtv5_pci_nano_config, | 828 | &dvico_hdtv5_pci_nano_config, |
821 | &dev->core->i2c_adap); | 829 | &core->i2c_adap); |
822 | if (dev->dvb.frontend != NULL) { | 830 | if (dev->dvb.frontend != NULL) { |
823 | struct dvb_frontend *fe; | 831 | struct dvb_frontend *fe; |
824 | struct xc2028_config cfg = { | 832 | struct xc2028_config cfg = { |
825 | .i2c_adap = &dev->core->i2c_adap, | 833 | .i2c_adap = &core->i2c_adap, |
826 | .i2c_addr = 0x61, | 834 | .i2c_addr = 0x61, |
827 | .callback = cx88_pci_nano_callback, | 835 | .callback = cx88_pci_nano_callback, |
828 | }; | 836 | }; |
@@ -841,50 +849,50 @@ static int dvb_register(struct cx8802_dev *dev) | |||
841 | case CX88_BOARD_PINNACLE_HYBRID_PCTV: | 849 | case CX88_BOARD_PINNACLE_HYBRID_PCTV: |
842 | dev->dvb.frontend = dvb_attach(zl10353_attach, | 850 | dev->dvb.frontend = dvb_attach(zl10353_attach, |
843 | &cx88_geniatech_x8000_mt, | 851 | &cx88_geniatech_x8000_mt, |
844 | &dev->core->i2c_adap); | 852 | &core->i2c_adap); |
845 | if (attach_xc3028(0x61, dev) < 0) | 853 | if (attach_xc3028(0x61, dev) < 0) |
846 | return -EINVAL; | 854 | goto frontend_detach; |
847 | break; | 855 | break; |
848 | case CX88_BOARD_GENIATECH_X8000_MT: | 856 | case CX88_BOARD_GENIATECH_X8000_MT: |
849 | dev->ts_gen_cntrl = 0x00; | 857 | dev->ts_gen_cntrl = 0x00; |
850 | 858 | ||
851 | dev->dvb.frontend = dvb_attach(zl10353_attach, | 859 | dev->dvb.frontend = dvb_attach(zl10353_attach, |
852 | &cx88_geniatech_x8000_mt, | 860 | &cx88_geniatech_x8000_mt, |
853 | &dev->core->i2c_adap); | 861 | &core->i2c_adap); |
854 | if (attach_xc3028(0x61, dev) < 0) | 862 | if (attach_xc3028(0x61, dev) < 0) |
855 | return -EINVAL; | 863 | goto frontend_detach; |
856 | break; | 864 | break; |
857 | case CX88_BOARD_KWORLD_ATSC_120: | 865 | case CX88_BOARD_KWORLD_ATSC_120: |
858 | dev->dvb.frontend = dvb_attach(s5h1409_attach, | 866 | dev->dvb.frontend = dvb_attach(s5h1409_attach, |
859 | &kworld_atsc_120_config, | 867 | &kworld_atsc_120_config, |
860 | &dev->core->i2c_adap); | 868 | &core->i2c_adap); |
861 | if (attach_xc3028(0x61, dev) < 0) | 869 | if (attach_xc3028(0x61, dev) < 0) |
862 | return -EINVAL; | 870 | goto frontend_detach; |
863 | break; | 871 | break; |
864 | case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: | 872 | case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: |
865 | dev->dvb.frontend = dvb_attach(s5h1411_attach, | 873 | dev->dvb.frontend = dvb_attach(s5h1411_attach, |
866 | &dvico_fusionhdtv7_config, | 874 | &dvico_fusionhdtv7_config, |
867 | &dev->core->i2c_adap); | 875 | &core->i2c_adap); |
868 | if (dev->dvb.frontend != NULL) { | 876 | if (dev->dvb.frontend != NULL) { |
869 | /* tuner_config.video_dev must point to | 877 | /* tuner_config.video_dev must point to |
870 | * i2c_adap.algo_data | 878 | * i2c_adap.algo_data |
871 | */ | 879 | */ |
872 | dvico_fusionhdtv7_tuner_config.priv = | 880 | if (!dvb_attach(xc5000_attach, dev->dvb.frontend, |
873 | dev->core->i2c_adap.algo_data; | 881 | &core->i2c_adap, |
874 | dvb_attach(xc5000_attach, dev->dvb.frontend, | 882 | &dvico_fusionhdtv7_tuner_config, |
875 | &dev->core->i2c_adap, | 883 | core->i2c_adap.algo_data)) |
876 | &dvico_fusionhdtv7_tuner_config); | 884 | goto frontend_detach; |
877 | } | 885 | } |
878 | break; | 886 | break; |
879 | default: | 887 | default: |
880 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", | 888 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", |
881 | dev->core->name); | 889 | core->name); |
882 | break; | 890 | break; |
883 | } | 891 | } |
884 | if (NULL == dev->dvb.frontend) { | 892 | if (NULL == dev->dvb.frontend) { |
885 | printk(KERN_ERR | 893 | printk(KERN_ERR |
886 | "%s/2: frontend initialization failed\n", | 894 | "%s/2: frontend initialization failed\n", |
887 | dev->core->name); | 895 | core->name); |
888 | return -EINVAL; | 896 | return -EINVAL; |
889 | } | 897 | } |
890 | 898 | ||
@@ -892,11 +900,18 @@ static int dvb_register(struct cx8802_dev *dev) | |||
892 | dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; | 900 | dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; |
893 | 901 | ||
894 | /* Put the analog decoder in standby to keep it quiet */ | 902 | /* Put the analog decoder in standby to keep it quiet */ |
895 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | 903 | cx88_call_i2c_clients(core, TUNER_SET_STANDBY, NULL); |
896 | 904 | ||
897 | /* register everything */ | 905 | /* register everything */ |
898 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, | 906 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, |
899 | &dev->pci->dev, adapter_nr); | 907 | &dev->pci->dev, adapter_nr); |
908 | |||
909 | frontend_detach: | ||
910 | if (dev->dvb.frontend) { | ||
911 | dvb_frontend_detach(dev->dvb.frontend); | ||
912 | dev->dvb.frontend = NULL; | ||
913 | } | ||
914 | return -EINVAL; | ||
900 | } | 915 | } |
901 | 916 | ||
902 | /* ----------------------------------------------------------- */ | 917 | /* ----------------------------------------------------------- */ |
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index c7c2896bbd8b..16a5af30e9d1 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | config VIDEO_EM28XX | 1 | config VIDEO_EM28XX |
2 | tristate "Empia EM28xx USB video capture support" | 2 | tristate "Empia EM28xx USB video capture support" |
3 | depends on VIDEO_DEV && I2C && INPUT | 3 | depends on VIDEO_DEV && I2C && INPUT |
4 | select MEDIA_TUNER | 4 | select VIDEO_TUNER |
5 | select VIDEO_TVEEPROM | 5 | select VIDEO_TVEEPROM |
6 | select VIDEO_IR | 6 | select VIDEO_IR |
7 | select VIDEOBUF_VMALLOC | 7 | select VIDEOBUF_VMALLOC |
@@ -35,7 +35,6 @@ config VIDEO_EM28XX_DVB | |||
35 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 35 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
36 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | 36 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
37 | select VIDEOBUF_DVB | 37 | select VIDEOBUF_DVB |
38 | select FW_LOADER | ||
39 | ---help--- | 38 | ---help--- |
40 | This adds support for DVB cards based on the | 39 | This adds support for DVB cards based on the |
41 | Empiatech em28xx chips. | 40 | Empiatech em28xx chips. |
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 92b2a6db4fdc..3c006103c1eb 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c | |||
@@ -268,6 +268,12 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) | |||
268 | 268 | ||
269 | dprintk("opening device and trying to acquire exclusive lock\n"); | 269 | dprintk("opening device and trying to acquire exclusive lock\n"); |
270 | 270 | ||
271 | if (!dev) { | ||
272 | printk(KERN_ERR "BUG: em28xx can't find device struct." | ||
273 | " Can't proceed with open\n"); | ||
274 | return -ENODEV; | ||
275 | } | ||
276 | |||
271 | /* Sets volume, mute, etc */ | 277 | /* Sets volume, mute, etc */ |
272 | 278 | ||
273 | dev->mute = 0; | 279 | dev->mute = 0; |
@@ -415,6 +421,12 @@ static int em28xx_audio_init(struct em28xx *dev) | |||
415 | static int devnr; | 421 | static int devnr; |
416 | int ret, err; | 422 | int ret, err; |
417 | 423 | ||
424 | if (dev->has_audio_class) { | ||
425 | /* This device does not support the extension (in this case | ||
426 | the device is expecting the snd-usb-audio module */ | ||
427 | return 0; | ||
428 | } | ||
429 | |||
418 | printk(KERN_INFO "em28xx-audio.c: probing for em28x1 " | 430 | printk(KERN_INFO "em28xx-audio.c: probing for em28x1 " |
419 | "non standard usbaudio\n"); | 431 | "non standard usbaudio\n"); |
420 | printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " | 432 | printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " |
@@ -458,6 +470,12 @@ static int em28xx_audio_fini(struct em28xx *dev) | |||
458 | if (dev == NULL) | 470 | if (dev == NULL) |
459 | return 0; | 471 | return 0; |
460 | 472 | ||
473 | if (dev->has_audio_class) { | ||
474 | /* This device does not support the extension (in this case | ||
475 | the device is expecting the snd-usb-audio module */ | ||
476 | return 0; | ||
477 | } | ||
478 | |||
461 | if (dev->adev) { | 479 | if (dev->adev) { |
462 | snd_card_free(dev->adev->sndcard); | 480 | snd_card_free(dev->adev->sndcard); |
463 | kfree(dev->adev); | 481 | kfree(dev->adev); |
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 50ccf3771204..8cbda43727c3 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -157,6 +157,7 @@ struct em28xx_board em28xx_boards[] = { | |||
157 | .tda9887_conf = TDA9887_PRESENT, | 157 | .tda9887_conf = TDA9887_PRESENT, |
158 | .tuner_type = TUNER_XC2028, | 158 | .tuner_type = TUNER_XC2028, |
159 | .mts_firmware = 1, | 159 | .mts_firmware = 1, |
160 | .has_dvb = 1, | ||
160 | .decoder = EM28XX_TVP5150, | 161 | .decoder = EM28XX_TVP5150, |
161 | .input = { { | 162 | .input = { { |
162 | .type = EM28XX_VMUX_TELEVISION, | 163 | .type = EM28XX_VMUX_TELEVISION, |
@@ -420,7 +421,13 @@ struct usb_device_id em28xx_id_table [] = { | |||
420 | .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, | 421 | .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, |
421 | { USB_DEVICE(0x2040, 0x6502), | 422 | { USB_DEVICE(0x2040, 0x6502), |
422 | .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, | 423 | .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, |
423 | { USB_DEVICE(0x2040, 0x6513), | 424 | { USB_DEVICE(0x2040, 0x6513), /* HCW HVR-980 */ |
425 | .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 }, | ||
426 | { USB_DEVICE(0x2040, 0x6517), /* HP HVR-950 */ | ||
427 | .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 }, | ||
428 | { USB_DEVICE(0x2040, 0x651b), /* RP HVR-950 */ | ||
429 | .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 }, | ||
430 | { USB_DEVICE(0x2040, 0x651f), /* HCW HVR-850 */ | ||
424 | .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 }, | 431 | .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 }, |
425 | { USB_DEVICE(0x0ccd, 0x0042), | 432 | { USB_DEVICE(0x0ccd, 0x0042), |
426 | .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS }, | 433 | .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS }, |
@@ -518,6 +525,9 @@ void em28xx_pre_card_setup(struct em28xx *dev) | |||
518 | rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); | 525 | rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); |
519 | if (rc > 0) { | 526 | if (rc > 0) { |
520 | switch (rc) { | 527 | switch (rc) { |
528 | case CHIP_ID_EM2860: | ||
529 | em28xx_info("chip ID is em2860\n"); | ||
530 | break; | ||
521 | case CHIP_ID_EM2883: | 531 | case CHIP_ID_EM2883: |
522 | em28xx_info("chip ID is em2882/em2883\n"); | 532 | em28xx_info("chip ID is em2882/em2883\n"); |
523 | dev->wait_after_write = 0; | 533 | dev->wait_after_write = 0; |
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 7df81575b7f2..0b2333ee07f8 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
@@ -251,7 +251,6 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) | |||
251 | printk(KERN_ERR "%s/2: xc3028 attach failed\n", | 251 | printk(KERN_ERR "%s/2: xc3028 attach failed\n", |
252 | dev->name); | 252 | dev->name); |
253 | dvb_frontend_detach(dev->dvb->frontend); | 253 | dvb_frontend_detach(dev->dvb->frontend); |
254 | dvb_unregister_frontend(dev->dvb->frontend); | ||
255 | dev->dvb->frontend = NULL; | 254 | dev->dvb->frontend = NULL; |
256 | return -EINVAL; | 255 | return -EINVAL; |
257 | } | 256 | } |
@@ -383,6 +382,11 @@ static int dvb_init(struct em28xx *dev) | |||
383 | int result = 0; | 382 | int result = 0; |
384 | struct em28xx_dvb *dvb; | 383 | struct em28xx_dvb *dvb; |
385 | 384 | ||
385 | if (!dev->has_dvb) { | ||
386 | /* This device does not support the extension */ | ||
387 | return 0; | ||
388 | } | ||
389 | |||
386 | dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); | 390 | dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); |
387 | 391 | ||
388 | if (dvb == NULL) { | 392 | if (dvb == NULL) { |
@@ -445,6 +449,11 @@ out_free: | |||
445 | 449 | ||
446 | static int dvb_fini(struct em28xx *dev) | 450 | static int dvb_fini(struct em28xx *dev) |
447 | { | 451 | { |
452 | if (!dev->has_dvb) { | ||
453 | /* This device does not support the extension */ | ||
454 | return 0; | ||
455 | } | ||
456 | |||
448 | if (dev->dvb) { | 457 | if (dev->dvb) { |
449 | unregister_dvb(dev->dvb); | 458 | unregister_dvb(dev->dvb); |
450 | dev->dvb = NULL; | 459 | dev->dvb = NULL; |
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h index 9058bed07953..fac1ab23f621 100644 --- a/drivers/media/video/em28xx/em28xx-reg.h +++ b/drivers/media/video/em28xx/em28xx-reg.h | |||
@@ -84,5 +84,6 @@ | |||
84 | 84 | ||
85 | /* FIXME: Need to be populated with the other chip ID's */ | 85 | /* FIXME: Need to be populated with the other chip ID's */ |
86 | enum em28xx_chip_id { | 86 | enum em28xx_chip_id { |
87 | CHIP_ID_EM2860 = 34, | ||
87 | CHIP_ID_EM2883 = 36, | 88 | CHIP_ID_EM2883 = 36, |
88 | }; | 89 | }; |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 8996175cc950..285bc62bbe46 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -1166,13 +1166,13 @@ static int vidioc_g_register(struct file *file, void *priv, | |||
1166 | 1166 | ||
1167 | reg->val = ret; | 1167 | reg->val = ret; |
1168 | } else { | 1168 | } else { |
1169 | u64 val = 0; | 1169 | __le64 val = 0; |
1170 | ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS, | 1170 | ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS, |
1171 | reg->reg, (char *)&val, 2); | 1171 | reg->reg, (char *)&val, 2); |
1172 | if (ret < 0) | 1172 | if (ret < 0) |
1173 | return ret; | 1173 | return ret; |
1174 | 1174 | ||
1175 | reg->val = cpu_to_le64((__u64)val); | 1175 | reg->val = le64_to_cpu(val); |
1176 | } | 1176 | } |
1177 | 1177 | ||
1178 | return 0; | 1178 | return 0; |
@@ -1183,9 +1183,9 @@ static int vidioc_s_register(struct file *file, void *priv, | |||
1183 | { | 1183 | { |
1184 | struct em28xx_fh *fh = priv; | 1184 | struct em28xx_fh *fh = priv; |
1185 | struct em28xx *dev = fh->dev; | 1185 | struct em28xx *dev = fh->dev; |
1186 | u64 buf; | 1186 | __le64 buf; |
1187 | 1187 | ||
1188 | buf = le64_to_cpu((__u64)reg->val); | 1188 | buf = cpu_to_le64(reg->val); |
1189 | 1189 | ||
1190 | return em28xx_write_regs(dev, reg->reg, (char *)&buf, | 1190 | return em28xx_write_regs(dev, reg->reg, (char *)&buf, |
1191 | em28xx_reg_len(reg->reg)); | 1191 | em28xx_reg_len(reg->reg)); |
@@ -1848,32 +1848,28 @@ static DEFINE_MUTEX(em28xx_extension_devlist_lock); | |||
1848 | 1848 | ||
1849 | int em28xx_register_extension(struct em28xx_ops *ops) | 1849 | int em28xx_register_extension(struct em28xx_ops *ops) |
1850 | { | 1850 | { |
1851 | struct em28xx *h, *dev = NULL; | 1851 | struct em28xx *dev = NULL; |
1852 | |||
1853 | list_for_each_entry(h, &em28xx_devlist, devlist) | ||
1854 | dev = h; | ||
1855 | 1852 | ||
1856 | mutex_lock(&em28xx_extension_devlist_lock); | 1853 | mutex_lock(&em28xx_extension_devlist_lock); |
1857 | list_add_tail(&ops->next, &em28xx_extension_devlist); | 1854 | list_add_tail(&ops->next, &em28xx_extension_devlist); |
1858 | if (dev) | 1855 | list_for_each_entry(dev, &em28xx_devlist, devlist) { |
1859 | ops->init(dev); | 1856 | if (dev) |
1860 | 1857 | ops->init(dev); | |
1858 | } | ||
1861 | printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); | 1859 | printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); |
1862 | mutex_unlock(&em28xx_extension_devlist_lock); | 1860 | mutex_unlock(&em28xx_extension_devlist_lock); |
1863 | |||
1864 | return 0; | 1861 | return 0; |
1865 | } | 1862 | } |
1866 | EXPORT_SYMBOL(em28xx_register_extension); | 1863 | EXPORT_SYMBOL(em28xx_register_extension); |
1867 | 1864 | ||
1868 | void em28xx_unregister_extension(struct em28xx_ops *ops) | 1865 | void em28xx_unregister_extension(struct em28xx_ops *ops) |
1869 | { | 1866 | { |
1870 | struct em28xx *h, *dev = NULL; | 1867 | struct em28xx *dev = NULL; |
1871 | |||
1872 | list_for_each_entry(h, &em28xx_devlist, devlist) | ||
1873 | dev = h; | ||
1874 | 1868 | ||
1875 | if (dev) | 1869 | list_for_each_entry(dev, &em28xx_devlist, devlist) { |
1876 | ops->fini(dev); | 1870 | if (dev) |
1871 | ops->fini(dev); | ||
1872 | } | ||
1877 | 1873 | ||
1878 | mutex_lock(&em28xx_extension_devlist_lock); | 1874 | mutex_lock(&em28xx_extension_devlist_lock); |
1879 | printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); | 1875 | printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); |
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 5e749c528a62..15d037ae25c5 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include <linux/mm.h> | 34 | #include <linux/mm.h> |
35 | #include <linux/vmalloc.h> | 35 | #include <linux/vmalloc.h> |
36 | #include <linux/page-flags.h> | 36 | #include <linux/page-flags.h> |
37 | #include <linux/byteorder/generic.h> | 37 | #include <asm/byteorder.h> |
38 | #include <asm/page.h> | 38 | #include <asm/page.h> |
39 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
40 | 40 | ||
diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig index eec115bf9517..5d7ee8fcdd50 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/video/ivtv/Kconfig | |||
@@ -1,10 +1,12 @@ | |||
1 | config VIDEO_IVTV | 1 | config VIDEO_IVTV |
2 | tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" | 2 | tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" |
3 | depends on VIDEO_V4L1 && VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL | 3 | depends on VIDEO_V4L1 && VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL |
4 | depends on INPUT # due to VIDEO_IR | ||
5 | depends on HOTPLUG # due to FW_LOADER | ||
4 | select I2C_ALGOBIT | 6 | select I2C_ALGOBIT |
5 | select FW_LOADER | 7 | select FW_LOADER |
6 | select VIDEO_IR | 8 | select VIDEO_IR |
7 | select MEDIA_TUNER | 9 | select VIDEO_TUNER |
8 | select VIDEO_TVEEPROM | 10 | select VIDEO_TVEEPROM |
9 | select VIDEO_CX2341X | 11 | select VIDEO_CX2341X |
10 | select VIDEO_CX25840 | 12 | select VIDEO_CX25840 |
diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c index 8c02fa661591..c7e449f6397b 100644 --- a/drivers/media/video/ivtv/ivtv-controls.c +++ b/drivers/media/video/ivtv/ivtv-controls.c | |||
@@ -181,12 +181,12 @@ static int ivtv_setup_vbi_fmt(struct ivtv *itv, enum v4l2_mpeg_stream_vbi_fmt fm | |||
181 | return 0; | 181 | return 0; |
182 | } | 182 | } |
183 | /* Need sliced data for mpeg insertion */ | 183 | /* Need sliced data for mpeg insertion */ |
184 | if (get_service_set(itv->vbi.sliced_in) == 0) { | 184 | if (ivtv_get_service_set(itv->vbi.sliced_in) == 0) { |
185 | if (itv->is_60hz) | 185 | if (itv->is_60hz) |
186 | itv->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525; | 186 | itv->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525; |
187 | else | 187 | else |
188 | itv->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625; | 188 | itv->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625; |
189 | expand_service_set(itv->vbi.sliced_in, itv->is_50hz); | 189 | ivtv_expand_service_set(itv->vbi.sliced_in, itv->is_50hz); |
190 | } | 190 | } |
191 | return 0; | 191 | return 0; |
192 | } | 192 | } |
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index ed020f722b05..797e636771da 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c | |||
@@ -853,6 +853,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, | |||
853 | return 0; | 853 | return 0; |
854 | } | 854 | } |
855 | 855 | ||
856 | #ifdef MODULE | ||
856 | static u32 ivtv_request_module(struct ivtv *itv, u32 hw, | 857 | static u32 ivtv_request_module(struct ivtv *itv, u32 hw, |
857 | const char *name, u32 id) | 858 | const char *name, u32 id) |
858 | { | 859 | { |
@@ -865,12 +866,14 @@ static u32 ivtv_request_module(struct ivtv *itv, u32 hw, | |||
865 | IVTV_DEBUG_INFO("Loaded module %s\n", name); | 866 | IVTV_DEBUG_INFO("Loaded module %s\n", name); |
866 | return hw; | 867 | return hw; |
867 | } | 868 | } |
869 | #endif | ||
868 | 870 | ||
869 | static void ivtv_load_and_init_modules(struct ivtv *itv) | 871 | static void ivtv_load_and_init_modules(struct ivtv *itv) |
870 | { | 872 | { |
871 | u32 hw = itv->card->hw_all; | 873 | u32 hw = itv->card->hw_all; |
872 | unsigned i; | 874 | unsigned i; |
873 | 875 | ||
876 | #ifdef MODULE | ||
874 | /* load modules */ | 877 | /* load modules */ |
875 | #ifndef CONFIG_MEDIA_TUNER | 878 | #ifndef CONFIG_MEDIA_TUNER |
876 | hw = ivtv_request_module(itv, hw, "tuner", IVTV_HW_TUNER); | 879 | hw = ivtv_request_module(itv, hw, "tuner", IVTV_HW_TUNER); |
@@ -911,6 +914,7 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) | |||
911 | #ifndef CONFIG_VIDEO_M52790 | 914 | #ifndef CONFIG_VIDEO_M52790 |
912 | hw = ivtv_request_module(itv, hw, "m52790", IVTV_HW_M52790); | 915 | hw = ivtv_request_module(itv, hw, "m52790", IVTV_HW_M52790); |
913 | #endif | 916 | #endif |
917 | #endif | ||
914 | 918 | ||
915 | /* check which i2c devices are actually found */ | 919 | /* check which i2c devices are actually found */ |
916 | for (i = 0; i < 32; i++) { | 920 | for (i = 0; i < 32; i++) { |
@@ -1228,7 +1232,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev, | |||
1228 | return 0; | 1232 | return 0; |
1229 | 1233 | ||
1230 | free_streams: | 1234 | free_streams: |
1231 | ivtv_streams_cleanup(itv); | 1235 | ivtv_streams_cleanup(itv, 1); |
1232 | free_irq: | 1236 | free_irq: |
1233 | free_irq(itv->dev->irq, (void *)itv); | 1237 | free_irq(itv->dev->irq, (void *)itv); |
1234 | free_i2c: | 1238 | free_i2c: |
@@ -1373,7 +1377,7 @@ static void ivtv_remove(struct pci_dev *pci_dev) | |||
1373 | flush_workqueue(itv->irq_work_queues); | 1377 | flush_workqueue(itv->irq_work_queues); |
1374 | destroy_workqueue(itv->irq_work_queues); | 1378 | destroy_workqueue(itv->irq_work_queues); |
1375 | 1379 | ||
1376 | ivtv_streams_cleanup(itv); | 1380 | ivtv_streams_cleanup(itv, 1); |
1377 | ivtv_udma_free(itv); | 1381 | ivtv_udma_free(itv); |
1378 | 1382 | ||
1379 | exit_ivtv_i2c(itv); | 1383 | exit_ivtv_i2c(itv); |
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index ba06e813c58c..9d23b1efd36d 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h | |||
@@ -259,6 +259,12 @@ struct ivtv_mailbox_data { | |||
259 | 259 | ||
260 | /* Scatter-Gather array element, used in DMA transfers */ | 260 | /* Scatter-Gather array element, used in DMA transfers */ |
261 | struct ivtv_sg_element { | 261 | struct ivtv_sg_element { |
262 | __le32 src; | ||
263 | __le32 dst; | ||
264 | __le32 size; | ||
265 | }; | ||
266 | |||
267 | struct ivtv_sg_host_element { | ||
262 | u32 src; | 268 | u32 src; |
263 | u32 dst; | 269 | u32 dst; |
264 | u32 size; | 270 | u32 size; |
@@ -349,8 +355,8 @@ struct ivtv_stream { | |||
349 | u16 dma_xfer_cnt; | 355 | u16 dma_xfer_cnt; |
350 | 356 | ||
351 | /* Base Dev SG Array for cx23415/6 */ | 357 | /* Base Dev SG Array for cx23415/6 */ |
352 | struct ivtv_sg_element *sg_pending; | 358 | struct ivtv_sg_host_element *sg_pending; |
353 | struct ivtv_sg_element *sg_processing; | 359 | struct ivtv_sg_host_element *sg_processing; |
354 | struct ivtv_sg_element *sg_dma; | 360 | struct ivtv_sg_element *sg_dma; |
355 | dma_addr_t sg_handle; | 361 | dma_addr_t sg_handle; |
356 | int sg_pending_size; | 362 | int sg_pending_size; |
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 2b74b0ab1477..db813e071ce6 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c | |||
@@ -587,7 +587,7 @@ retry: | |||
587 | since we may get here before the stream has been fully set-up */ | 587 | since we may get here before the stream has been fully set-up */ |
588 | if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) { | 588 | if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) { |
589 | while (count >= itv->dma_data_req_size) { | 589 | while (count >= itv->dma_data_req_size) { |
590 | if (!ivtv_yuv_udma_stream_frame (itv, (void *)user_buf)) { | 590 | if (!ivtv_yuv_udma_stream_frame (itv, (void __user *)user_buf)) { |
591 | bytes_written += itv->dma_data_req_size; | 591 | bytes_written += itv->dma_data_req_size; |
592 | user_buf += itv->dma_data_req_size; | 592 | user_buf += itv->dma_data_req_size; |
593 | count -= itv->dma_data_req_size; | 593 | count -= itv->dma_data_req_size; |
@@ -987,6 +987,8 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) | |||
987 | /* Find which card this open was on */ | 987 | /* Find which card this open was on */ |
988 | spin_lock(&ivtv_cards_lock); | 988 | spin_lock(&ivtv_cards_lock); |
989 | for (x = 0; itv == NULL && x < ivtv_cards_active; x++) { | 989 | for (x = 0; itv == NULL && x < ivtv_cards_active; x++) { |
990 | if (ivtv_cards[x] == NULL) | ||
991 | continue; | ||
990 | /* find out which stream this open was on */ | 992 | /* find out which stream this open was on */ |
991 | for (y = 0; y < IVTV_MAX_STREAMS; y++) { | 993 | for (y = 0; y < IVTV_MAX_STREAMS; y++) { |
992 | s = &ivtv_cards[x]->streams[y]; | 994 | s = &ivtv_cards[x]->streams[y]; |
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c index 771adf47e944..32129f3ea836 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ b/drivers/media/video/ivtv/ivtv-i2c.c | |||
@@ -136,7 +136,7 @@ static const u8 hw_addrs[] = { | |||
136 | }; | 136 | }; |
137 | 137 | ||
138 | /* This array should match the IVTV_HW_ defines */ | 138 | /* This array should match the IVTV_HW_ defines */ |
139 | static const char * const hw_drivernames[] = { | 139 | static const char * const hw_devicenames[] = { |
140 | "cx25840", | 140 | "cx25840", |
141 | "saa7115", | 141 | "saa7115", |
142 | "saa7127", | 142 | "saa7127", |
@@ -145,7 +145,7 @@ static const char * const hw_drivernames[] = { | |||
145 | "wm8775", | 145 | "wm8775", |
146 | "cs53l32a", | 146 | "cs53l32a", |
147 | "tveeprom", | 147 | "tveeprom", |
148 | "saa7115", | 148 | "saa7114", |
149 | "upd64031a", | 149 | "upd64031a", |
150 | "upd64083", | 150 | "upd64083", |
151 | "saa717x", | 151 | "saa717x", |
@@ -167,8 +167,7 @@ int ivtv_i2c_register(struct ivtv *itv, unsigned idx) | |||
167 | return -1; | 167 | return -1; |
168 | id = hw_driverids[idx]; | 168 | id = hw_driverids[idx]; |
169 | memset(&info, 0, sizeof(info)); | 169 | memset(&info, 0, sizeof(info)); |
170 | strlcpy(info.driver_name, hw_drivernames[idx], | 170 | strlcpy(info.type, hw_devicenames[idx], sizeof(info.type)); |
171 | sizeof(info.driver_name)); | ||
172 | info.addr = hw_addrs[idx]; | 171 | info.addr = hw_addrs[idx]; |
173 | for (i = 0; itv->i2c_clients[i] && i < I2C_CLIENTS_MAX; i++) {} | 172 | for (i = 0; itv->i2c_clients[i] && i < I2C_CLIENTS_MAX; i++) {} |
174 | 173 | ||
@@ -657,7 +656,7 @@ static const char *ivtv_i2c_id_name(u32 id) | |||
657 | 656 | ||
658 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) | 657 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) |
659 | if (hw_driverids[i] == id) | 658 | if (hw_driverids[i] == id) |
660 | return hw_drivernames[i]; | 659 | return hw_devicenames[i]; |
661 | return "unknown device"; | 660 | return "unknown device"; |
662 | } | 661 | } |
663 | 662 | ||
@@ -668,7 +667,7 @@ static const char *ivtv_i2c_hw_name(u32 hw) | |||
668 | 667 | ||
669 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) | 668 | for (i = 0; i < ARRAY_SIZE(hw_driverids); i++) |
670 | if (1 << i == hw) | 669 | if (1 << i == hw) |
671 | return hw_drivernames[i]; | 670 | return hw_devicenames[i]; |
672 | return "unknown device"; | 671 | return "unknown device"; |
673 | } | 672 | } |
674 | 673 | ||
@@ -770,7 +769,7 @@ int init_ivtv_i2c(struct ivtv *itv) | |||
770 | * same size and GPIO must be the last entry. | 769 | * same size and GPIO must be the last entry. |
771 | */ | 770 | */ |
772 | if (ARRAY_SIZE(hw_driverids) != ARRAY_SIZE(hw_addrs) || | 771 | if (ARRAY_SIZE(hw_driverids) != ARRAY_SIZE(hw_addrs) || |
773 | ARRAY_SIZE(hw_drivernames) != ARRAY_SIZE(hw_addrs) || | 772 | ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs) || |
774 | IVTV_HW_GPIO != (1 << (ARRAY_SIZE(hw_addrs) - 1)) || | 773 | IVTV_HW_GPIO != (1 << (ARRAY_SIZE(hw_addrs) - 1)) || |
775 | hw_driverids[ARRAY_SIZE(hw_addrs) - 1]) { | 774 | hw_driverids[ARRAY_SIZE(hw_addrs) - 1]) { |
776 | IVTV_ERR("Mismatched I2C hardware arrays\n"); | 775 | IVTV_ERR("Mismatched I2C hardware arrays\n"); |
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index d508b5d0538c..26cc0f6699fd 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include <linux/dvb/audio.h> | 38 | #include <linux/dvb/audio.h> |
39 | #include <linux/i2c-id.h> | 39 | #include <linux/i2c-id.h> |
40 | 40 | ||
41 | u16 service2vbi(int type) | 41 | u16 ivtv_service2vbi(int type) |
42 | { | 42 | { |
43 | switch (type) { | 43 | switch (type) { |
44 | case V4L2_SLICED_TELETEXT_B: | 44 | case V4L2_SLICED_TELETEXT_B: |
@@ -88,7 +88,7 @@ static u16 select_service_from_set(int field, int line, u16 set, int is_pal) | |||
88 | return 0; | 88 | return 0; |
89 | } | 89 | } |
90 | 90 | ||
91 | void expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) | 91 | void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) |
92 | { | 92 | { |
93 | u16 set = fmt->service_set; | 93 | u16 set = fmt->service_set; |
94 | int f, l; | 94 | int f, l; |
@@ -115,7 +115,7 @@ static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) | |||
115 | return set != 0; | 115 | return set != 0; |
116 | } | 116 | } |
117 | 117 | ||
118 | u16 get_service_set(struct v4l2_sliced_vbi_format *fmt) | 118 | u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt) |
119 | { | 119 | { |
120 | int f, l; | 120 | int f, l; |
121 | u16 set = 0; | 121 | u16 set = 0; |
@@ -466,7 +466,7 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm | |||
466 | vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625; | 466 | vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625; |
467 | vbifmt->service_lines[0][16] = V4L2_SLICED_VPS; | 467 | vbifmt->service_lines[0][16] = V4L2_SLICED_VPS; |
468 | } | 468 | } |
469 | vbifmt->service_set = get_service_set(vbifmt); | 469 | vbifmt->service_set = ivtv_get_service_set(vbifmt); |
470 | break; | 470 | break; |
471 | } | 471 | } |
472 | 472 | ||
@@ -481,12 +481,12 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm | |||
481 | if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) { | 481 | if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) { |
482 | vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 : | 482 | vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 : |
483 | V4L2_SLICED_VBI_525; | 483 | V4L2_SLICED_VBI_525; |
484 | expand_service_set(vbifmt, itv->is_50hz); | 484 | ivtv_expand_service_set(vbifmt, itv->is_50hz); |
485 | break; | 485 | break; |
486 | } | 486 | } |
487 | 487 | ||
488 | itv->video_dec_func(itv, VIDIOC_G_FMT, fmt); | 488 | itv->video_dec_func(itv, VIDIOC_G_FMT, fmt); |
489 | vbifmt->service_set = get_service_set(vbifmt); | 489 | vbifmt->service_set = ivtv_get_service_set(vbifmt); |
490 | break; | 490 | break; |
491 | } | 491 | } |
492 | case V4L2_BUF_TYPE_VBI_OUTPUT: | 492 | case V4L2_BUF_TYPE_VBI_OUTPUT: |
@@ -640,9 +640,9 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, | |||
640 | memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved)); | 640 | memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved)); |
641 | 641 | ||
642 | if (vbifmt->service_set) | 642 | if (vbifmt->service_set) |
643 | expand_service_set(vbifmt, itv->is_50hz); | 643 | ivtv_expand_service_set(vbifmt, itv->is_50hz); |
644 | set = check_service_set(vbifmt, itv->is_50hz); | 644 | set = check_service_set(vbifmt, itv->is_50hz); |
645 | vbifmt->service_set = get_service_set(vbifmt); | 645 | vbifmt->service_set = ivtv_get_service_set(vbifmt); |
646 | 646 | ||
647 | if (!set_fmt) | 647 | if (!set_fmt) |
648 | return 0; | 648 | return 0; |
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.h b/drivers/media/video/ivtv/ivtv-ioctl.h index a03351b6853d..4e67f0ed1fc0 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.h +++ b/drivers/media/video/ivtv/ivtv-ioctl.h | |||
@@ -21,9 +21,9 @@ | |||
21 | #ifndef IVTV_IOCTL_H | 21 | #ifndef IVTV_IOCTL_H |
22 | #define IVTV_IOCTL_H | 22 | #define IVTV_IOCTL_H |
23 | 23 | ||
24 | u16 service2vbi(int type); | 24 | u16 ivtv_service2vbi(int type); |
25 | void expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal); | 25 | void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal); |
26 | u16 get_service_set(struct v4l2_sliced_vbi_format *fmt); | 26 | u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt); |
27 | int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | 27 | int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, |
28 | unsigned long arg); | 28 | unsigned long arg); |
29 | int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg); | 29 | int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg); |
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c index d8ba3a4a8761..fba150a6cd23 100644 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ b/drivers/media/video/ivtv/ivtv-irq.c | |||
@@ -231,14 +231,14 @@ static void dma_post(struct ivtv_stream *s) | |||
231 | struct ivtv_buffer *buf = NULL; | 231 | struct ivtv_buffer *buf = NULL; |
232 | struct list_head *p; | 232 | struct list_head *p; |
233 | u32 offset; | 233 | u32 offset; |
234 | u32 *u32buf; | 234 | __le32 *u32buf; |
235 | int x = 0; | 235 | int x = 0; |
236 | 236 | ||
237 | IVTV_DEBUG_HI_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA", | 237 | IVTV_DEBUG_HI_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA", |
238 | s->name, s->dma_offset); | 238 | s->name, s->dma_offset); |
239 | list_for_each(p, &s->q_dma.list) { | 239 | list_for_each(p, &s->q_dma.list) { |
240 | buf = list_entry(p, struct ivtv_buffer, list); | 240 | buf = list_entry(p, struct ivtv_buffer, list); |
241 | u32buf = (u32 *)buf->buf; | 241 | u32buf = (__le32 *)buf->buf; |
242 | 242 | ||
243 | /* Sync Buffer */ | 243 | /* Sync Buffer */ |
244 | ivtv_buf_sync_for_cpu(s, buf); | 244 | ivtv_buf_sync_for_cpu(s, buf); |
@@ -444,7 +444,7 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) | |||
444 | } | 444 | } |
445 | 445 | ||
446 | s->dma_xfer_cnt++; | 446 | s->dma_xfer_cnt++; |
447 | memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_element) * s->sg_pending_size); | 447 | memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size); |
448 | s->sg_processing_size = s->sg_pending_size; | 448 | s->sg_processing_size = s->sg_pending_size; |
449 | s->sg_pending_size = 0; | 449 | s->sg_pending_size = 0; |
450 | s->sg_processed = 0; | 450 | s->sg_processed = 0; |
@@ -473,7 +473,7 @@ static void ivtv_dma_dec_start(struct ivtv_stream *s) | |||
473 | if (s->q_predma.bytesused) | 473 | if (s->q_predma.bytesused) |
474 | ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); | 474 | ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); |
475 | s->dma_xfer_cnt++; | 475 | s->dma_xfer_cnt++; |
476 | memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_element) * s->sg_pending_size); | 476 | memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size); |
477 | s->sg_processing_size = s->sg_pending_size; | 477 | s->sg_processing_size = s->sg_pending_size; |
478 | s->sg_pending_size = 0; | 478 | s->sg_pending_size = 0; |
479 | s->sg_processed = 0; | 479 | s->sg_processed = 0; |
diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c index 3e1deec67a5e..71bd13e22e2e 100644 --- a/drivers/media/video/ivtv/ivtv-queue.c +++ b/drivers/media/video/ivtv/ivtv-queue.c | |||
@@ -193,7 +193,7 @@ void ivtv_flush_queues(struct ivtv_stream *s) | |||
193 | int ivtv_stream_alloc(struct ivtv_stream *s) | 193 | int ivtv_stream_alloc(struct ivtv_stream *s) |
194 | { | 194 | { |
195 | struct ivtv *itv = s->itv; | 195 | struct ivtv *itv = s->itv; |
196 | int SGsize = sizeof(struct ivtv_sg_element) * s->buffers; | 196 | int SGsize = sizeof(struct ivtv_sg_host_element) * s->buffers; |
197 | int i; | 197 | int i; |
198 | 198 | ||
199 | if (s->buffers == 0) | 199 | if (s->buffers == 0) |
@@ -203,14 +203,14 @@ int ivtv_stream_alloc(struct ivtv_stream *s) | |||
203 | s->dma != PCI_DMA_NONE ? "DMA " : "", | 203 | s->dma != PCI_DMA_NONE ? "DMA " : "", |
204 | s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024); | 204 | s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024); |
205 | 205 | ||
206 | s->sg_pending = kzalloc(SGsize, GFP_KERNEL); | 206 | s->sg_pending = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN); |
207 | if (s->sg_pending == NULL) { | 207 | if (s->sg_pending == NULL) { |
208 | IVTV_ERR("Could not allocate sg_pending for %s stream\n", s->name); | 208 | IVTV_ERR("Could not allocate sg_pending for %s stream\n", s->name); |
209 | return -ENOMEM; | 209 | return -ENOMEM; |
210 | } | 210 | } |
211 | s->sg_pending_size = 0; | 211 | s->sg_pending_size = 0; |
212 | 212 | ||
213 | s->sg_processing = kzalloc(SGsize, GFP_KERNEL); | 213 | s->sg_processing = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN); |
214 | if (s->sg_processing == NULL) { | 214 | if (s->sg_processing == NULL) { |
215 | IVTV_ERR("Could not allocate sg_processing for %s stream\n", s->name); | 215 | IVTV_ERR("Could not allocate sg_processing for %s stream\n", s->name); |
216 | kfree(s->sg_pending); | 216 | kfree(s->sg_pending); |
@@ -219,7 +219,8 @@ int ivtv_stream_alloc(struct ivtv_stream *s) | |||
219 | } | 219 | } |
220 | s->sg_processing_size = 0; | 220 | s->sg_processing_size = 0; |
221 | 221 | ||
222 | s->sg_dma = kzalloc(sizeof(struct ivtv_sg_element), GFP_KERNEL); | 222 | s->sg_dma = kzalloc(sizeof(struct ivtv_sg_element), |
223 | GFP_KERNEL|__GFP_NOWARN); | ||
223 | if (s->sg_dma == NULL) { | 224 | if (s->sg_dma == NULL) { |
224 | IVTV_ERR("Could not allocate sg_dma for %s stream\n", s->name); | 225 | IVTV_ERR("Could not allocate sg_dma for %s stream\n", s->name); |
225 | kfree(s->sg_pending); | 226 | kfree(s->sg_pending); |
@@ -235,11 +236,12 @@ int ivtv_stream_alloc(struct ivtv_stream *s) | |||
235 | 236 | ||
236 | /* allocate stream buffers. Initially all buffers are in q_free. */ | 237 | /* allocate stream buffers. Initially all buffers are in q_free. */ |
237 | for (i = 0; i < s->buffers; i++) { | 238 | for (i = 0; i < s->buffers; i++) { |
238 | struct ivtv_buffer *buf = kzalloc(sizeof(struct ivtv_buffer), GFP_KERNEL); | 239 | struct ivtv_buffer *buf = kzalloc(sizeof(struct ivtv_buffer), |
240 | GFP_KERNEL|__GFP_NOWARN); | ||
239 | 241 | ||
240 | if (buf == NULL) | 242 | if (buf == NULL) |
241 | break; | 243 | break; |
242 | buf->buf = kmalloc(s->buf_size + 256, GFP_KERNEL); | 244 | buf->buf = kmalloc(s->buf_size + 256, GFP_KERNEL|__GFP_NOWARN); |
243 | if (buf->buf == NULL) { | 245 | if (buf->buf == NULL) { |
244 | kfree(buf); | 246 | kfree(buf); |
245 | break; | 247 | break; |
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 4ab8d36831ba..c854285a4371 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c | |||
@@ -44,23 +44,25 @@ | |||
44 | #include "ivtv-streams.h" | 44 | #include "ivtv-streams.h" |
45 | 45 | ||
46 | static const struct file_operations ivtv_v4l2_enc_fops = { | 46 | static const struct file_operations ivtv_v4l2_enc_fops = { |
47 | .owner = THIS_MODULE, | 47 | .owner = THIS_MODULE, |
48 | .read = ivtv_v4l2_read, | 48 | .read = ivtv_v4l2_read, |
49 | .write = ivtv_v4l2_write, | 49 | .write = ivtv_v4l2_write, |
50 | .open = ivtv_v4l2_open, | 50 | .open = ivtv_v4l2_open, |
51 | .ioctl = ivtv_v4l2_ioctl, | 51 | .ioctl = ivtv_v4l2_ioctl, |
52 | .release = ivtv_v4l2_close, | 52 | .compat_ioctl = v4l_compat_ioctl32, |
53 | .poll = ivtv_v4l2_enc_poll, | 53 | .release = ivtv_v4l2_close, |
54 | .poll = ivtv_v4l2_enc_poll, | ||
54 | }; | 55 | }; |
55 | 56 | ||
56 | static const struct file_operations ivtv_v4l2_dec_fops = { | 57 | static const struct file_operations ivtv_v4l2_dec_fops = { |
57 | .owner = THIS_MODULE, | 58 | .owner = THIS_MODULE, |
58 | .read = ivtv_v4l2_read, | 59 | .read = ivtv_v4l2_read, |
59 | .write = ivtv_v4l2_write, | 60 | .write = ivtv_v4l2_write, |
60 | .open = ivtv_v4l2_open, | 61 | .open = ivtv_v4l2_open, |
61 | .ioctl = ivtv_v4l2_ioctl, | 62 | .ioctl = ivtv_v4l2_ioctl, |
62 | .release = ivtv_v4l2_close, | 63 | .compat_ioctl = v4l_compat_ioctl32, |
63 | .poll = ivtv_v4l2_dec_poll, | 64 | .release = ivtv_v4l2_close, |
65 | .poll = ivtv_v4l2_dec_poll, | ||
64 | }; | 66 | }; |
65 | 67 | ||
66 | #define IVTV_V4L2_DEC_MPG_OFFSET 16 /* offset from 0 to register decoder mpg v4l2 minors on */ | 68 | #define IVTV_V4L2_DEC_MPG_OFFSET 16 /* offset from 0 to register decoder mpg v4l2 minors on */ |
@@ -244,7 +246,7 @@ int ivtv_streams_setup(struct ivtv *itv) | |||
244 | return 0; | 246 | return 0; |
245 | 247 | ||
246 | /* One or more streams could not be initialized. Clean 'em all up. */ | 248 | /* One or more streams could not be initialized. Clean 'em all up. */ |
247 | ivtv_streams_cleanup(itv); | 249 | ivtv_streams_cleanup(itv, 0); |
248 | return -ENOMEM; | 250 | return -ENOMEM; |
249 | } | 251 | } |
250 | 252 | ||
@@ -304,12 +306,12 @@ int ivtv_streams_register(struct ivtv *itv) | |||
304 | return 0; | 306 | return 0; |
305 | 307 | ||
306 | /* One or more streams could not be initialized. Clean 'em all up. */ | 308 | /* One or more streams could not be initialized. Clean 'em all up. */ |
307 | ivtv_streams_cleanup(itv); | 309 | ivtv_streams_cleanup(itv, 1); |
308 | return -ENOMEM; | 310 | return -ENOMEM; |
309 | } | 311 | } |
310 | 312 | ||
311 | /* Unregister v4l2 devices */ | 313 | /* Unregister v4l2 devices */ |
312 | void ivtv_streams_cleanup(struct ivtv *itv) | 314 | void ivtv_streams_cleanup(struct ivtv *itv, int unregister) |
313 | { | 315 | { |
314 | int type; | 316 | int type; |
315 | 317 | ||
@@ -322,8 +324,11 @@ void ivtv_streams_cleanup(struct ivtv *itv) | |||
322 | continue; | 324 | continue; |
323 | 325 | ||
324 | ivtv_stream_free(&itv->streams[type]); | 326 | ivtv_stream_free(&itv->streams[type]); |
325 | /* Unregister device */ | 327 | /* Unregister or release device */ |
326 | video_unregister_device(vdev); | 328 | if (unregister) |
329 | video_unregister_device(vdev); | ||
330 | else | ||
331 | video_device_release(vdev); | ||
327 | } | 332 | } |
328 | } | 333 | } |
329 | 334 | ||
diff --git a/drivers/media/video/ivtv/ivtv-streams.h b/drivers/media/video/ivtv/ivtv-streams.h index 3d76a415fbd8..a653a5136417 100644 --- a/drivers/media/video/ivtv/ivtv-streams.h +++ b/drivers/media/video/ivtv/ivtv-streams.h | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | int ivtv_streams_setup(struct ivtv *itv); | 24 | int ivtv_streams_setup(struct ivtv *itv); |
25 | int ivtv_streams_register(struct ivtv *itv); | 25 | int ivtv_streams_register(struct ivtv *itv); |
26 | void ivtv_streams_cleanup(struct ivtv *itv); | 26 | void ivtv_streams_cleanup(struct ivtv *itv, int unregister); |
27 | 27 | ||
28 | /* Capture related */ | 28 | /* Capture related */ |
29 | int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s); | 29 | int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s); |
diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index c151bcf5519a..71798f0da27f 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c | |||
@@ -169,7 +169,8 @@ static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp) | |||
169 | linemask[0] |= (1 << l); | 169 | linemask[0] |= (1 << l); |
170 | else | 170 | else |
171 | linemask[1] |= (1 << (l - 32)); | 171 | linemask[1] |= (1 << (l - 32)); |
172 | dst[sd + 12 + line * 43] = service2vbi(itv->vbi.sliced_data[i].id); | 172 | dst[sd + 12 + line * 43] = |
173 | ivtv_service2vbi(itv->vbi.sliced_data[i].id); | ||
173 | memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42); | 174 | memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42); |
174 | line++; | 175 | line++; |
175 | } | 176 | } |
diff --git a/drivers/media/video/ivtv/ivtv-version.h b/drivers/media/video/ivtv/ivtv-version.h index 02c5ab071d1b..442f43f11b73 100644 --- a/drivers/media/video/ivtv/ivtv-version.h +++ b/drivers/media/video/ivtv/ivtv-version.h | |||
@@ -22,8 +22,8 @@ | |||
22 | 22 | ||
23 | #define IVTV_DRIVER_NAME "ivtv" | 23 | #define IVTV_DRIVER_NAME "ivtv" |
24 | #define IVTV_DRIVER_VERSION_MAJOR 1 | 24 | #define IVTV_DRIVER_VERSION_MAJOR 1 |
25 | #define IVTV_DRIVER_VERSION_MINOR 2 | 25 | #define IVTV_DRIVER_VERSION_MINOR 3 |
26 | #define IVTV_DRIVER_VERSION_PATCHLEVEL 1 | 26 | #define IVTV_DRIVER_VERSION_PATCHLEVEL 0 |
27 | 27 | ||
28 | #define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL) | 28 | #define IVTV_VERSION __stringify(IVTV_DRIVER_VERSION_MAJOR) "." __stringify(IVTV_DRIVER_VERSION_MINOR) "." __stringify(IVTV_DRIVER_VERSION_PATCHLEVEL) |
29 | #define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL) | 29 | #define IVTV_DRIVER_VERSION KERNEL_VERSION(IVTV_DRIVER_VERSION_MAJOR,IVTV_DRIVER_VERSION_MINOR,IVTV_DRIVER_VERSION_PATCHLEVEL) |
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index 62f70bd5e3cb..3092ff1d00a0 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c | |||
@@ -908,7 +908,7 @@ static void ivtv_yuv_init(struct ivtv *itv) | |||
908 | } | 908 | } |
909 | 909 | ||
910 | /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */ | 910 | /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */ |
911 | yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL); | 911 | yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN); |
912 | if (yi->blanking_ptr) { | 912 | if (yi->blanking_ptr) { |
913 | yi->blanking_dmaptr = pci_map_single(itv->dev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE); | 913 | yi->blanking_dmaptr = pci_map_single(itv->dev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE); |
914 | } else { | 914 | } else { |
@@ -1116,7 +1116,7 @@ void ivtv_yuv_setup_stream_frame(struct ivtv *itv) | |||
1116 | } | 1116 | } |
1117 | 1117 | ||
1118 | /* Attempt to dma a frame from a user buffer */ | 1118 | /* Attempt to dma a frame from a user buffer */ |
1119 | int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void *src) | 1119 | int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src) |
1120 | { | 1120 | { |
1121 | struct yuv_playback_info *yi = &itv->yuv_info; | 1121 | struct yuv_playback_info *yi = &itv->yuv_info; |
1122 | struct ivtv_dma_frame dma_args; | 1122 | struct ivtv_dma_frame dma_args; |
diff --git a/drivers/media/video/ivtv/ivtv-yuv.h b/drivers/media/video/ivtv/ivtv-yuv.h index 2fe5f1250762..ca5173fbf006 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.h +++ b/drivers/media/video/ivtv/ivtv-yuv.h | |||
@@ -35,7 +35,7 @@ extern const u32 yuv_offset[IVTV_YUV_BUFFERS]; | |||
35 | 35 | ||
36 | int ivtv_yuv_filter_check(struct ivtv *itv); | 36 | int ivtv_yuv_filter_check(struct ivtv *itv); |
37 | void ivtv_yuv_setup_stream_frame(struct ivtv *itv); | 37 | void ivtv_yuv_setup_stream_frame(struct ivtv *itv); |
38 | int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void *src); | 38 | int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src); |
39 | void ivtv_yuv_frame_complete(struct ivtv *itv); | 39 | void ivtv_yuv_frame_complete(struct ivtv *itv); |
40 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args); | 40 | int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args); |
41 | void ivtv_yuv_close(struct ivtv *itv); | 41 | void ivtv_yuv_close(struct ivtv *itv); |
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index df789f683e63..73be154f7f05 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c | |||
@@ -948,7 +948,8 @@ static int ivtvfb_init_vidmode(struct ivtv *itv) | |||
948 | } | 948 | } |
949 | 949 | ||
950 | /* Allocate the pseudo palette */ | 950 | /* Allocate the pseudo palette */ |
951 | oi->ivtvfb_info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); | 951 | oi->ivtvfb_info.pseudo_palette = |
952 | kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN); | ||
952 | 953 | ||
953 | if (!oi->ivtvfb_info.pseudo_palette) { | 954 | if (!oi->ivtvfb_info.pseudo_palette) { |
954 | IVTVFB_ERR("abort, unable to alloc pseudo pallete\n"); | 955 | IVTVFB_ERR("abort, unable to alloc pseudo pallete\n"); |
@@ -1056,7 +1057,8 @@ static int ivtvfb_init_card(struct ivtv *itv) | |||
1056 | return -EBUSY; | 1057 | return -EBUSY; |
1057 | } | 1058 | } |
1058 | 1059 | ||
1059 | itv->osd_info = kzalloc(sizeof(struct osd_info), GFP_ATOMIC); | 1060 | itv->osd_info = kzalloc(sizeof(struct osd_info), |
1061 | GFP_ATOMIC|__GFP_NOWARN); | ||
1060 | if (itv->osd_info == NULL) { | 1062 | if (itv->osd_info == NULL) { |
1061 | IVTVFB_ERR("Failed to allocate memory for osd_info\n"); | 1063 | IVTVFB_ERR("Failed to allocate memory for osd_info\n"); |
1062 | return -ENOMEM; | 1064 | return -ENOMEM; |
diff --git a/drivers/media/video/m52790.c b/drivers/media/video/m52790.c index 5b9dfa2c51b4..8e0160d275ca 100644 --- a/drivers/media/video/m52790.c +++ b/drivers/media/video/m52790.c | |||
@@ -135,8 +135,6 @@ static int m52790_probe(struct i2c_client *client, | |||
135 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 135 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
136 | return -EIO; | 136 | return -EIO; |
137 | 137 | ||
138 | snprintf(client->name, sizeof(client->name) - 1, "m52790"); | ||
139 | |||
140 | v4l_info(client, "chip found @ 0x%x (%s)\n", | 138 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
141 | client->addr << 1, client->adapter->name); | 139 | client->addr << 1, client->adapter->name); |
142 | 140 | ||
@@ -159,11 +157,18 @@ static int m52790_remove(struct i2c_client *client) | |||
159 | 157 | ||
160 | /* ----------------------------------------------------------------------- */ | 158 | /* ----------------------------------------------------------------------- */ |
161 | 159 | ||
160 | static const struct i2c_device_id m52790_id[] = { | ||
161 | { "m52790", 0 }, | ||
162 | { } | ||
163 | }; | ||
164 | MODULE_DEVICE_TABLE(i2c, m52790_id); | ||
165 | |||
162 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 166 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
163 | .name = "m52790", | 167 | .name = "m52790", |
164 | .driverid = I2C_DRIVERID_M52790, | 168 | .driverid = I2C_DRIVERID_M52790, |
165 | .command = m52790_command, | 169 | .command = m52790_command, |
166 | .probe = m52790_probe, | 170 | .probe = m52790_probe, |
167 | .remove = m52790_remove, | 171 | .remove = m52790_remove, |
172 | .id_table = m52790_id, | ||
168 | }; | 173 | }; |
169 | 174 | ||
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c index e6273162e123..310dbaba55ff 100644 --- a/drivers/media/video/msp3400-driver.c +++ b/drivers/media/video/msp3400-driver.c | |||
@@ -815,7 +815,8 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
815 | int msp_product, msp_prod_hi, msp_prod_lo; | 815 | int msp_product, msp_prod_hi, msp_prod_lo; |
816 | int msp_rom; | 816 | int msp_rom; |
817 | 817 | ||
818 | snprintf(client->name, sizeof(client->name) - 1, "msp3400"); | 818 | if (!id) |
819 | strlcpy(client->name, "msp3400", sizeof(client->name)); | ||
819 | 820 | ||
820 | if (msp_reset(client) == -1) { | 821 | if (msp_reset(client) == -1) { |
821 | v4l_dbg(1, msp_debug, client, "msp3400 not found\n"); | 822 | v4l_dbg(1, msp_debug, client, "msp3400 not found\n"); |
@@ -864,9 +865,6 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
864 | msp_revision = (state->rev1 & 0x0f) + '@'; | 865 | msp_revision = (state->rev1 & 0x0f) + '@'; |
865 | msp_hard = ((state->rev1 >> 8) & 0xff) + '@'; | 866 | msp_hard = ((state->rev1 >> 8) & 0xff) + '@'; |
866 | msp_rom = state->rev2 & 0x1f; | 867 | msp_rom = state->rev2 & 0x1f; |
867 | snprintf(client->name, sizeof(client->name), "MSP%d4%02d%c-%c%d", | ||
868 | msp_family, msp_product, | ||
869 | msp_revision, msp_hard, msp_rom); | ||
870 | /* Rev B=2, C=3, D=4, G=7 */ | 868 | /* Rev B=2, C=3, D=4, G=7 */ |
871 | state->ident = msp_family * 10000 + 4000 + msp_product * 10 + | 869 | state->ident = msp_family * 10000 + 4000 + msp_product * 10 + |
872 | msp_revision - '@'; | 870 | msp_revision - '@'; |
@@ -931,7 +929,9 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
931 | } | 929 | } |
932 | 930 | ||
933 | /* hello world :-) */ | 931 | /* hello world :-) */ |
934 | v4l_info(client, "%s found @ 0x%x (%s)\n", client->name, | 932 | v4l_info(client, "MSP%d4%02d%c-%c%d found @ 0x%x (%s)\n", |
933 | msp_family, msp_product, | ||
934 | msp_revision, msp_hard, msp_rom, | ||
935 | client->addr << 1, client->adapter->name); | 935 | client->addr << 1, client->adapter->name); |
936 | v4l_info(client, "%s ", client->name); | 936 | v4l_info(client, "%s ", client->name); |
937 | if (state->has_nicam && state->has_radio) | 937 | if (state->has_nicam && state->has_radio) |
@@ -987,6 +987,12 @@ static int msp_remove(struct i2c_client *client) | |||
987 | 987 | ||
988 | /* ----------------------------------------------------------------------- */ | 988 | /* ----------------------------------------------------------------------- */ |
989 | 989 | ||
990 | static const struct i2c_device_id msp_id[] = { | ||
991 | { "msp3400", 0 }, | ||
992 | { } | ||
993 | }; | ||
994 | MODULE_DEVICE_TABLE(i2c, msp_id); | ||
995 | |||
990 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 996 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
991 | .name = "msp3400", | 997 | .name = "msp3400", |
992 | .driverid = I2C_DRIVERID_MSP3400, | 998 | .driverid = I2C_DRIVERID_MSP3400, |
@@ -995,6 +1001,7 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { | |||
995 | .remove = msp_remove, | 1001 | .remove = msp_remove, |
996 | .suspend = msp_suspend, | 1002 | .suspend = msp_suspend, |
997 | .resume = msp_resume, | 1003 | .resume = msp_resume, |
1004 | .id_table = msp_id, | ||
998 | }; | 1005 | }; |
999 | 1006 | ||
1000 | 1007 | ||
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 179e47049a45..ee43499544c1 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c | |||
@@ -12,15 +12,12 @@ | |||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/i2c.h> | 13 | #include <linux/i2c.h> |
14 | #include <linux/log2.h> | 14 | #include <linux/log2.h> |
15 | #include <linux/gpio.h> | ||
15 | 16 | ||
16 | #include <media/v4l2-common.h> | 17 | #include <media/v4l2-common.h> |
17 | #include <media/v4l2-chip-ident.h> | 18 | #include <media/v4l2-chip-ident.h> |
18 | #include <media/soc_camera.h> | 19 | #include <media/soc_camera.h> |
19 | 20 | ||
20 | #ifdef CONFIG_MT9M001_PCA9536_SWITCH | ||
21 | #include <asm/gpio.h> | ||
22 | #endif | ||
23 | |||
24 | /* mt9m001 i2c address 0x5d | 21 | /* mt9m001 i2c address 0x5d |
25 | * The platform has to define i2c_board_info | 22 | * The platform has to define i2c_board_info |
26 | * and call i2c_register_board_info() */ | 23 | * and call i2c_register_board_info() */ |
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index d1391ac55096..1658fe590392 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c | |||
@@ -13,15 +13,12 @@ | |||
13 | #include <linux/i2c.h> | 13 | #include <linux/i2c.h> |
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/log2.h> | 15 | #include <linux/log2.h> |
16 | #include <linux/gpio.h> | ||
16 | 17 | ||
17 | #include <media/v4l2-common.h> | 18 | #include <media/v4l2-common.h> |
18 | #include <media/v4l2-chip-ident.h> | 19 | #include <media/v4l2-chip-ident.h> |
19 | #include <media/soc_camera.h> | 20 | #include <media/soc_camera.h> |
20 | 21 | ||
21 | #ifdef CONFIG_MT9M001_PCA9536_SWITCH | ||
22 | #include <asm/gpio.h> | ||
23 | #endif | ||
24 | |||
25 | /* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c | 22 | /* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c |
26 | * The platform has to define i2c_board_info | 23 | * The platform has to define i2c_board_info |
27 | * and call i2c_register_board_info() */ | 24 | * and call i2c_register_board_info() */ |
@@ -91,7 +88,7 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { | |||
91 | struct mt9v022 { | 88 | struct mt9v022 { |
92 | struct i2c_client *client; | 89 | struct i2c_client *client; |
93 | struct soc_camera_device icd; | 90 | struct soc_camera_device icd; |
94 | int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ | 91 | int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ |
95 | int switch_gpio; | 92 | int switch_gpio; |
96 | u16 chip_control; | 93 | u16 chip_control; |
97 | unsigned char datawidth; | 94 | unsigned char datawidth; |
diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index 9620c67fae77..4482b2c72ced 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig | |||
@@ -1,8 +1,10 @@ | |||
1 | config VIDEO_PVRUSB2 | 1 | config VIDEO_PVRUSB2 |
2 | tristate "Hauppauge WinTV-PVR USB2 support" | 2 | tristate "Hauppauge WinTV-PVR USB2 support" |
3 | depends on VIDEO_V4L2 && I2C | 3 | depends on VIDEO_V4L2 && I2C |
4 | depends on VIDEO_MEDIA # Avoids pvrusb = Y / DVB = M | ||
5 | depends on HOTPLUG # due to FW_LOADER | ||
4 | select FW_LOADER | 6 | select FW_LOADER |
5 | select MEDIA_TUNER | 7 | select VIDEO_TUNER |
6 | select VIDEO_TVEEPROM | 8 | select VIDEO_TVEEPROM |
7 | select VIDEO_CX2341X | 9 | select VIDEO_CX2341X |
8 | select VIDEO_SAA711X | 10 | select VIDEO_SAA711X |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 7cc8e9b19fb7..5ec5bb9a94d2 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -1019,12 +1019,12 @@ static int pxa_camera_probe(struct platform_device *pdev) | |||
1019 | struct pxa_camera_dev *pcdev; | 1019 | struct pxa_camera_dev *pcdev; |
1020 | struct resource *res; | 1020 | struct resource *res; |
1021 | void __iomem *base; | 1021 | void __iomem *base; |
1022 | unsigned int irq; | 1022 | int irq; |
1023 | int err = 0; | 1023 | int err = 0; |
1024 | 1024 | ||
1025 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1025 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1026 | irq = platform_get_irq(pdev, 0); | 1026 | irq = platform_get_irq(pdev, 0); |
1027 | if (!res || !irq) { | 1027 | if (!res || irq < 0) { |
1028 | err = -ENODEV; | 1028 | err = -ENODEV; |
1029 | goto exit; | 1029 | goto exit; |
1030 | } | 1030 | } |
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index e684108637ad..435c083cc542 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c | |||
@@ -1456,14 +1456,13 @@ static int saa7115_probe(struct i2c_client *client, | |||
1456 | struct saa711x_state *state; | 1456 | struct saa711x_state *state; |
1457 | int i; | 1457 | int i; |
1458 | char name[17]; | 1458 | char name[17]; |
1459 | u8 chip_id; | 1459 | char chip_id; |
1460 | int autodetect = !id || id->driver_data == 1; | ||
1460 | 1461 | ||
1461 | /* Check if the adapter supports the needed features */ | 1462 | /* Check if the adapter supports the needed features */ |
1462 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 1463 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
1463 | return -EIO; | 1464 | return -EIO; |
1464 | 1465 | ||
1465 | snprintf(client->name, sizeof(client->name) - 1, "saa7115"); | ||
1466 | |||
1467 | for (i = 0; i < 0x0f; i++) { | 1466 | for (i = 0; i < 0x0f; i++) { |
1468 | saa711x_write(client, 0, i); | 1467 | saa711x_write(client, 0, i); |
1469 | name[i] = (saa711x_read(client, 0) & 0x0f) + '0'; | 1468 | name[i] = (saa711x_read(client, 0) & 0x0f) + '0'; |
@@ -1472,8 +1471,7 @@ static int saa7115_probe(struct i2c_client *client, | |||
1472 | } | 1471 | } |
1473 | name[i] = '\0'; | 1472 | name[i] = '\0'; |
1474 | 1473 | ||
1475 | saa711x_write(client, 0, 5); | 1474 | chip_id = name[5]; |
1476 | chip_id = saa711x_read(client, 0) & 0x0f; | ||
1477 | 1475 | ||
1478 | /* Check whether this chip is part of the saa711x series */ | 1476 | /* Check whether this chip is part of the saa711x series */ |
1479 | if (memcmp(name, "1f711", 5)) { | 1477 | if (memcmp(name, "1f711", 5)) { |
@@ -1482,8 +1480,14 @@ static int saa7115_probe(struct i2c_client *client, | |||
1482 | return -ENODEV; | 1480 | return -ENODEV; |
1483 | } | 1481 | } |
1484 | 1482 | ||
1485 | snprintf(client->name, sizeof(client->name) - 1, "saa711%d",chip_id); | 1483 | /* Safety check */ |
1486 | v4l_info(client, "saa711%d found (%s) @ 0x%x (%s)\n", chip_id, name, client->addr << 1, client->adapter->name); | 1484 | if (!autodetect && id->name[6] != chip_id) { |
1485 | v4l_warn(client, "found saa711%c while %s was expected\n", | ||
1486 | chip_id, id->name); | ||
1487 | } | ||
1488 | snprintf(client->name, sizeof(client->name), "saa711%c", chip_id); | ||
1489 | v4l_info(client, "saa711%c found (%s) @ 0x%x (%s)\n", chip_id, name, | ||
1490 | client->addr << 1, client->adapter->name); | ||
1487 | 1491 | ||
1488 | state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL); | 1492 | state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL); |
1489 | i2c_set_clientdata(client, state); | 1493 | i2c_set_clientdata(client, state); |
@@ -1499,19 +1503,19 @@ static int saa7115_probe(struct i2c_client *client, | |||
1499 | state->hue = 0; | 1503 | state->hue = 0; |
1500 | state->sat = 64; | 1504 | state->sat = 64; |
1501 | switch (chip_id) { | 1505 | switch (chip_id) { |
1502 | case 1: | 1506 | case '1': |
1503 | state->ident = V4L2_IDENT_SAA7111; | 1507 | state->ident = V4L2_IDENT_SAA7111; |
1504 | break; | 1508 | break; |
1505 | case 3: | 1509 | case '3': |
1506 | state->ident = V4L2_IDENT_SAA7113; | 1510 | state->ident = V4L2_IDENT_SAA7113; |
1507 | break; | 1511 | break; |
1508 | case 4: | 1512 | case '4': |
1509 | state->ident = V4L2_IDENT_SAA7114; | 1513 | state->ident = V4L2_IDENT_SAA7114; |
1510 | break; | 1514 | break; |
1511 | case 5: | 1515 | case '5': |
1512 | state->ident = V4L2_IDENT_SAA7115; | 1516 | state->ident = V4L2_IDENT_SAA7115; |
1513 | break; | 1517 | break; |
1514 | case 8: | 1518 | case '8': |
1515 | state->ident = V4L2_IDENT_SAA7118; | 1519 | state->ident = V4L2_IDENT_SAA7118; |
1516 | break; | 1520 | break; |
1517 | default: | 1521 | default: |
@@ -1553,6 +1557,17 @@ static int saa7115_remove(struct i2c_client *client) | |||
1553 | return 0; | 1557 | return 0; |
1554 | } | 1558 | } |
1555 | 1559 | ||
1560 | static const struct i2c_device_id saa7115_id[] = { | ||
1561 | { "saa711x", 1 }, /* autodetect */ | ||
1562 | { "saa7111", 0 }, | ||
1563 | { "saa7113", 0 }, | ||
1564 | { "saa7114", 0 }, | ||
1565 | { "saa7115", 0 }, | ||
1566 | { "saa7118", 0 }, | ||
1567 | { } | ||
1568 | }; | ||
1569 | MODULE_DEVICE_TABLE(i2c, saa7115_id); | ||
1570 | |||
1556 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 1571 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
1557 | .name = "saa7115", | 1572 | .name = "saa7115", |
1558 | .driverid = I2C_DRIVERID_SAA711X, | 1573 | .driverid = I2C_DRIVERID_SAA711X, |
@@ -1560,5 +1575,6 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { | |||
1560 | .probe = saa7115_probe, | 1575 | .probe = saa7115_probe, |
1561 | .remove = saa7115_remove, | 1576 | .remove = saa7115_remove, |
1562 | .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, | 1577 | .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, |
1578 | .id_table = saa7115_id, | ||
1563 | }; | 1579 | }; |
1564 | 1580 | ||
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index e750cd65c1c3..79d11a658bdf 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c | |||
@@ -672,8 +672,6 @@ static int saa7127_probe(struct i2c_client *client, | |||
672 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 672 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
673 | return -EIO; | 673 | return -EIO; |
674 | 674 | ||
675 | snprintf(client->name, sizeof(client->name) - 1, "saa7127"); | ||
676 | |||
677 | v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n", | 675 | v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n", |
678 | client->addr << 1); | 676 | client->addr << 1); |
679 | 677 | ||
@@ -741,11 +739,18 @@ static int saa7127_remove(struct i2c_client *client) | |||
741 | 739 | ||
742 | /* ----------------------------------------------------------------------- */ | 740 | /* ----------------------------------------------------------------------- */ |
743 | 741 | ||
742 | static struct i2c_device_id saa7127_id[] = { | ||
743 | { "saa7127", 0 }, | ||
744 | { } | ||
745 | }; | ||
746 | MODULE_DEVICE_TABLE(i2c, saa7127_id); | ||
747 | |||
744 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 748 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
745 | .name = "saa7127", | 749 | .name = "saa7127", |
746 | .driverid = I2C_DRIVERID_SAA7127, | 750 | .driverid = I2C_DRIVERID_SAA7127, |
747 | .command = saa7127_command, | 751 | .command = saa7127_command, |
748 | .probe = saa7127_probe, | 752 | .probe = saa7127_probe, |
749 | .remove = saa7127_remove, | 753 | .remove = saa7127_remove, |
754 | .id_table = saa7127_id, | ||
750 | }; | 755 | }; |
751 | 756 | ||
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 40e4c3bd2cb9..83f076abce35 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig | |||
@@ -3,7 +3,7 @@ config VIDEO_SAA7134 | |||
3 | depends on VIDEO_DEV && PCI && I2C && INPUT | 3 | depends on VIDEO_DEV && PCI && I2C && INPUT |
4 | select VIDEOBUF_DMA_SG | 4 | select VIDEOBUF_DMA_SG |
5 | select VIDEO_IR | 5 | select VIDEO_IR |
6 | select MEDIA_TUNER | 6 | select VIDEO_TUNER |
7 | select VIDEO_TVEEPROM | 7 | select VIDEO_TVEEPROM |
8 | select CRC32 | 8 | select CRC32 |
9 | ---help--- | 9 | ---help--- |
@@ -27,6 +27,7 @@ config VIDEO_SAA7134_ALSA | |||
27 | config VIDEO_SAA7134_DVB | 27 | config VIDEO_SAA7134_DVB |
28 | tristate "DVB/ATSC Support for saa7134 based TV cards" | 28 | tristate "DVB/ATSC Support for saa7134 based TV cards" |
29 | depends on VIDEO_SAA7134 && DVB_CORE | 29 | depends on VIDEO_SAA7134 && DVB_CORE |
30 | depends on HOTPLUG # due to FW_LOADER | ||
30 | select VIDEOBUF_DVB | 31 | select VIDEOBUF_DVB |
31 | select FW_LOADER | 32 | select FW_LOADER |
32 | select DVB_PLL if !DVB_FE_CUSTOMISE | 33 | select DVB_PLL if !DVB_FE_CUSTOMISE |
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index ba3082422a01..f118de6e3672 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c | |||
@@ -613,9 +613,15 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream) | |||
613 | struct snd_pcm_runtime *runtime = substream->runtime; | 613 | struct snd_pcm_runtime *runtime = substream->runtime; |
614 | snd_card_saa7134_pcm_t *pcm; | 614 | snd_card_saa7134_pcm_t *pcm; |
615 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | 615 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); |
616 | struct saa7134_dev *dev = saa7134->dev; | 616 | struct saa7134_dev *dev; |
617 | int amux, err; | 617 | int amux, err; |
618 | 618 | ||
619 | if (!saa7134) { | ||
620 | printk(KERN_ERR "BUG: saa7134 can't find device struct." | ||
621 | " Can't proceed with open\n"); | ||
622 | return -ENODEV; | ||
623 | } | ||
624 | dev = saa7134->dev; | ||
619 | mutex_lock(&dev->dmasound.lock); | 625 | mutex_lock(&dev->dmasound.lock); |
620 | 626 | ||
621 | dev->dmasound.read_count = 0; | 627 | dev->dmasound.read_count = 0; |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index b111903aa322..2618cfa592e7 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -4114,11 +4114,7 @@ struct saa7134_board saa7134_boards[] = { | |||
4114 | .radio_type = UNSET, | 4114 | .radio_type = UNSET, |
4115 | .tuner_addr = ADDR_UNSET, | 4115 | .tuner_addr = ADDR_UNSET, |
4116 | .radio_addr = ADDR_UNSET, | 4116 | .radio_addr = ADDR_UNSET, |
4117 | /* | ||
4118 | TODO: | ||
4119 | .mpeg = SAA7134_MPEG_DVB, | 4117 | .mpeg = SAA7134_MPEG_DVB, |
4120 | */ | ||
4121 | |||
4122 | .inputs = {{ | 4118 | .inputs = {{ |
4123 | .name = name_tv, | 4119 | .name = name_tv, |
4124 | .vmux = 1, | 4120 | .vmux = 1, |
@@ -4157,7 +4153,7 @@ struct saa7134_board saa7134_boards[] = { | |||
4157 | } }, | 4153 | } }, |
4158 | .radio = { | 4154 | .radio = { |
4159 | .name = name_radio, | 4155 | .name = name_radio, |
4160 | .amux = LINE1, | 4156 | .amux = TV, |
4161 | }, | 4157 | }, |
4162 | }, | 4158 | }, |
4163 | [SAA7134_BOARD_AVERMEDIA_M115] = { | 4159 | [SAA7134_BOARD_AVERMEDIA_M115] = { |
@@ -4167,6 +4163,7 @@ struct saa7134_board saa7134_boards[] = { | |||
4167 | .radio_type = UNSET, | 4163 | .radio_type = UNSET, |
4168 | .tuner_addr = ADDR_UNSET, | 4164 | .tuner_addr = ADDR_UNSET, |
4169 | .radio_addr = ADDR_UNSET, | 4165 | .radio_addr = ADDR_UNSET, |
4166 | .mpeg = SAA7134_MPEG_DVB, | ||
4170 | .inputs = {{ | 4167 | .inputs = {{ |
4171 | .name = name_tv, | 4168 | .name = name_tv, |
4172 | .vmux = 1, | 4169 | .vmux = 1, |
@@ -5351,22 +5348,21 @@ static int saa7134_xc2028_callback(struct saa7134_dev *dev, | |||
5351 | { | 5348 | { |
5352 | switch (command) { | 5349 | switch (command) { |
5353 | case XC2028_TUNER_RESET: | 5350 | case XC2028_TUNER_RESET: |
5354 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000); | 5351 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00000000); |
5355 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000); | 5352 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000); |
5356 | mdelay(250); | 5353 | switch (dev->board) { |
5357 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0); | 5354 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: |
5358 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0); | 5355 | saa7134_set_gpio(dev, 23, 0); |
5359 | mdelay(250); | 5356 | msleep(10); |
5360 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000); | 5357 | saa7134_set_gpio(dev, 23, 1); |
5361 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000); | 5358 | break; |
5362 | mdelay(250); | 5359 | case SAA7134_BOARD_AVERMEDIA_A16D: |
5363 | saa_andorl(SAA7133_ANALOG_IO_SELECT >> 2, 0x02, 0x02); | 5360 | saa7134_set_gpio(dev, 21, 0); |
5364 | saa_andorl(SAA7134_ANALOG_IN_CTRL1 >> 2, 0x81, 0x81); | 5361 | msleep(10); |
5365 | saa_andorl(SAA7134_AUDIO_CLOCK0 >> 2, 0x03187de7, 0x03187de7); | 5362 | saa7134_set_gpio(dev, 21, 1); |
5366 | saa_andorl(SAA7134_AUDIO_PLL_CTRL >> 2, 0x03, 0x03); | 5363 | break; |
5367 | saa_andorl(SAA7134_AUDIO_CLOCKS_PER_FIELD0 >> 2, | 5364 | } |
5368 | 0x0001e000, 0x0001e000); | 5365 | return 0; |
5369 | return 0; | ||
5370 | } | 5366 | } |
5371 | return -EINVAL; | 5367 | return -EINVAL; |
5372 | } | 5368 | } |
@@ -5553,9 +5549,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
5553 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000); | 5549 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000); |
5554 | break; | 5550 | break; |
5555 | case SAA7134_BOARD_AVERMEDIA_CARDBUS: | 5551 | case SAA7134_BOARD_AVERMEDIA_CARDBUS: |
5556 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: | ||
5557 | case SAA7134_BOARD_AVERMEDIA_M115: | 5552 | case SAA7134_BOARD_AVERMEDIA_M115: |
5558 | case SAA7134_BOARD_AVERMEDIA_A16D: | ||
5559 | /* power-down tuner chip */ | 5553 | /* power-down tuner chip */ |
5560 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0); | 5554 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0); |
5561 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0); | 5555 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0); |
@@ -5565,6 +5559,18 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
5565 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff); | 5559 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff); |
5566 | msleep(10); | 5560 | msleep(10); |
5567 | break; | 5561 | break; |
5562 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: | ||
5563 | saa7134_set_gpio(dev, 23, 0); | ||
5564 | msleep(10); | ||
5565 | saa7134_set_gpio(dev, 23, 1); | ||
5566 | break; | ||
5567 | case SAA7134_BOARD_AVERMEDIA_A16D: | ||
5568 | saa7134_set_gpio(dev, 21, 0); | ||
5569 | msleep(10); | ||
5570 | saa7134_set_gpio(dev, 21, 1); | ||
5571 | msleep(1); | ||
5572 | dev->has_remote = SAA7134_REMOTE_GPIO; | ||
5573 | break; | ||
5568 | case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: | 5574 | case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: |
5569 | /* power-down tuner chip */ | 5575 | /* power-down tuner chip */ |
5570 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x000A8004, 0x000A8004); | 5576 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x000A8004, 0x000A8004); |
@@ -5615,7 +5621,8 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
5615 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x80040100, 0x80040100); | 5621 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x80040100, 0x80040100); |
5616 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100); | 5622 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100); |
5617 | printk("%s: %s: hybrid analog/dvb card\n" | 5623 | printk("%s: %s: hybrid analog/dvb card\n" |
5618 | "%s: Sorry, only the analog inputs are supported for now.\n", | 5624 | "%s: Sorry, only analog s-video and composite input " |
5625 | "are supported for now.\n", | ||
5619 | dev->name, card(dev).name, dev->name); | 5626 | dev->name, card(dev).name, dev->name); |
5620 | break; | 5627 | break; |
5621 | } | 5628 | } |
@@ -5675,6 +5682,7 @@ static void saa7134_tuner_setup(struct saa7134_dev *dev) | |||
5675 | 5682 | ||
5676 | switch (dev->board) { | 5683 | switch (dev->board) { |
5677 | case SAA7134_BOARD_AVERMEDIA_A16D: | 5684 | case SAA7134_BOARD_AVERMEDIA_A16D: |
5685 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: | ||
5678 | ctl.demod = XC3028_FE_ZARLINK456; | 5686 | ctl.demod = XC3028_FE_ZARLINK456; |
5679 | break; | 5687 | break; |
5680 | default: | 5688 | default: |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index eec127864fe3..2c19cd0113c8 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -864,7 +864,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
864 | struct saa7134_dev *dev; | 864 | struct saa7134_dev *dev; |
865 | struct saa7134_mpeg_ops *mops; | 865 | struct saa7134_mpeg_ops *mops; |
866 | int err; | 866 | int err; |
867 | int mask; | ||
868 | 867 | ||
869 | if (saa7134_devcount == SAA7134_MAXBOARDS) | 868 | if (saa7134_devcount == SAA7134_MAXBOARDS) |
870 | return -ENOMEM; | 869 | return -ENOMEM; |
@@ -1065,11 +1064,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, | |||
1065 | if (TUNER_ABSENT != dev->tuner_type) | 1064 | if (TUNER_ABSENT != dev->tuner_type) |
1066 | saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); | 1065 | saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); |
1067 | 1066 | ||
1068 | if (card(dev).gpiomask != 0) { | ||
1069 | mask = card(dev).gpiomask; | ||
1070 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); | ||
1071 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, 0); | ||
1072 | } | ||
1073 | return 0; | 1067 | return 0; |
1074 | 1068 | ||
1075 | fail4: | 1069 | fail4: |
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 2d16be2259db..341b101b0357 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
@@ -153,12 +153,12 @@ static int mt352_aver777_init(struct dvb_frontend* fe) | |||
153 | return 0; | 153 | return 0; |
154 | } | 154 | } |
155 | 155 | ||
156 | static int mt352_aver_a16d_init(struct dvb_frontend *fe) | 156 | static int mt352_avermedia_xc3028_init(struct dvb_frontend *fe) |
157 | { | 157 | { |
158 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x2d }; | 158 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x2d }; |
159 | static u8 reset [] = { RESET, 0x80 }; | 159 | static u8 reset [] = { RESET, 0x80 }; |
160 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; | 160 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; |
161 | static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0xa0 }; | 161 | static u8 agc_cfg [] = { AGC_TARGET, 0xe }; |
162 | static u8 capt_range_cfg[] = { CAPT_RANGE, 0x33 }; | 162 | static u8 capt_range_cfg[] = { CAPT_RANGE, 0x33 }; |
163 | 163 | ||
164 | mt352_write(fe, clock_config, sizeof(clock_config)); | 164 | mt352_write(fe, clock_config, sizeof(clock_config)); |
@@ -167,12 +167,9 @@ static int mt352_aver_a16d_init(struct dvb_frontend *fe) | |||
167 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | 167 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); |
168 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | 168 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); |
169 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | 169 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); |
170 | |||
171 | return 0; | 170 | return 0; |
172 | } | 171 | } |
173 | 172 | ||
174 | |||
175 | |||
176 | static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe, | 173 | static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe, |
177 | struct dvb_frontend_parameters* params) | 174 | struct dvb_frontend_parameters* params) |
178 | { | 175 | { |
@@ -215,14 +212,10 @@ static struct mt352_config avermedia_777 = { | |||
215 | .demod_init = mt352_aver777_init, | 212 | .demod_init = mt352_aver777_init, |
216 | }; | 213 | }; |
217 | 214 | ||
218 | static struct mt352_config avermedia_16d = { | 215 | static struct mt352_config avermedia_xc3028_mt352_dev = { |
219 | .demod_address = 0xf, | ||
220 | .demod_init = mt352_aver_a16d_init, | ||
221 | }; | ||
222 | |||
223 | static struct mt352_config avermedia_e506r_mt352_dev = { | ||
224 | .demod_address = (0x1e >> 1), | 216 | .demod_address = (0x1e >> 1), |
225 | .no_tuner = 1, | 217 | .no_tuner = 1, |
218 | .demod_init = mt352_avermedia_xc3028_init, | ||
226 | }; | 219 | }; |
227 | 220 | ||
228 | /* ================================================================== | 221 | /* ================================================================== |
@@ -538,19 +531,23 @@ static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe) | |||
538 | return 0; | 531 | return 0; |
539 | } | 532 | } |
540 | 533 | ||
541 | static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *cdec_conf, | 534 | static int configure_tda827x_fe(struct saa7134_dev *dev, |
542 | struct tda827x_config *tuner_conf) | 535 | struct tda1004x_config *cdec_conf, |
536 | struct tda827x_config *tuner_conf) | ||
543 | { | 537 | { |
544 | dev->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap); | 538 | dev->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap); |
545 | if (dev->dvb.frontend) { | 539 | if (dev->dvb.frontend) { |
546 | if (cdec_conf->i2c_gate) | 540 | if (cdec_conf->i2c_gate) |
547 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; | 541 | dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; |
548 | if (dvb_attach(tda827x_attach, dev->dvb.frontend, cdec_conf->tuner_address, | 542 | if (dvb_attach(tda827x_attach, dev->dvb.frontend, |
549 | &dev->i2c_adap, tuner_conf) == NULL) { | 543 | cdec_conf->tuner_address, |
550 | wprintk("no tda827x tuner found at addr: %02x\n", | 544 | &dev->i2c_adap, tuner_conf)) |
545 | return 0; | ||
546 | |||
547 | wprintk("no tda827x tuner found at addr: %02x\n", | ||
551 | cdec_conf->tuner_address); | 548 | cdec_conf->tuner_address); |
552 | } | ||
553 | } | 549 | } |
550 | return -EINVAL; | ||
554 | } | 551 | } |
555 | 552 | ||
556 | /* ------------------------------------------------------------------ */ | 553 | /* ------------------------------------------------------------------ */ |
@@ -971,9 +968,10 @@ static int dvb_init(struct saa7134_dev *dev) | |||
971 | } | 968 | } |
972 | break; | 969 | break; |
973 | case SAA7134_BOARD_AVERMEDIA_A16D: | 970 | case SAA7134_BOARD_AVERMEDIA_A16D: |
974 | dprintk("avertv A16D dvb setup\n"); | 971 | dprintk("AverMedia A16D dvb setup\n"); |
975 | dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_16d, | 972 | dev->dvb.frontend = dvb_attach(mt352_attach, |
976 | &dev->i2c_adap); | 973 | &avermedia_xc3028_mt352_dev, |
974 | &dev->i2c_adap); | ||
977 | attach_xc3028 = 1; | 975 | attach_xc3028 = 1; |
978 | break; | 976 | break; |
979 | case SAA7134_BOARD_MD7134: | 977 | case SAA7134_BOARD_MD7134: |
@@ -997,7 +995,9 @@ static int dvb_init(struct saa7134_dev *dev) | |||
997 | break; | 995 | break; |
998 | case SAA7134_BOARD_FLYDVBTDUO: | 996 | case SAA7134_BOARD_FLYDVBTDUO: |
999 | case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS: | 997 | case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS: |
1000 | configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0); | 998 | if (configure_tda827x_fe(dev, &tda827x_lifeview_config, |
999 | &tda827x_cfg_0) < 0) | ||
1000 | goto dettach_frontend; | ||
1001 | break; | 1001 | break; |
1002 | case SAA7134_BOARD_PHILIPS_EUROPA: | 1002 | case SAA7134_BOARD_PHILIPS_EUROPA: |
1003 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: | 1003 | case SAA7134_BOARD_VIDEOMATE_DVBT_300: |
@@ -1022,36 +1022,52 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1022 | } | 1022 | } |
1023 | break; | 1023 | break; |
1024 | case SAA7134_BOARD_KWORLD_DVBT_210: | 1024 | case SAA7134_BOARD_KWORLD_DVBT_210: |
1025 | configure_tda827x_fe(dev, &kworld_dvb_t_210_config, &tda827x_cfg_2); | 1025 | if (configure_tda827x_fe(dev, &kworld_dvb_t_210_config, |
1026 | &tda827x_cfg_2) < 0) | ||
1027 | goto dettach_frontend; | ||
1026 | break; | 1028 | break; |
1027 | case SAA7134_BOARD_PHILIPS_TIGER: | 1029 | case SAA7134_BOARD_PHILIPS_TIGER: |
1028 | configure_tda827x_fe(dev, &philips_tiger_config, &tda827x_cfg_0); | 1030 | if (configure_tda827x_fe(dev, &philips_tiger_config, |
1031 | &tda827x_cfg_0) < 0) | ||
1032 | goto dettach_frontend; | ||
1029 | break; | 1033 | break; |
1030 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | 1034 | case SAA7134_BOARD_PINNACLE_PCTV_310i: |
1031 | configure_tda827x_fe(dev, &pinnacle_pctv_310i_config, &tda827x_cfg_1); | 1035 | if (configure_tda827x_fe(dev, &pinnacle_pctv_310i_config, |
1036 | &tda827x_cfg_1) < 0) | ||
1037 | goto dettach_frontend; | ||
1032 | break; | 1038 | break; |
1033 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | 1039 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: |
1034 | configure_tda827x_fe(dev, &hauppauge_hvr_1110_config, &tda827x_cfg_1); | 1040 | if (configure_tda827x_fe(dev, &hauppauge_hvr_1110_config, |
1041 | &tda827x_cfg_1) < 0) | ||
1042 | goto dettach_frontend; | ||
1035 | break; | 1043 | break; |
1036 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: | 1044 | case SAA7134_BOARD_ASUSTeK_P7131_DUAL: |
1037 | configure_tda827x_fe(dev, &asus_p7131_dual_config, &tda827x_cfg_0); | 1045 | if (configure_tda827x_fe(dev, &asus_p7131_dual_config, |
1046 | &tda827x_cfg_0) < 0) | ||
1047 | goto dettach_frontend; | ||
1038 | break; | 1048 | break; |
1039 | case SAA7134_BOARD_FLYDVBT_LR301: | 1049 | case SAA7134_BOARD_FLYDVBT_LR301: |
1040 | configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0); | 1050 | if (configure_tda827x_fe(dev, &tda827x_lifeview_config, |
1051 | &tda827x_cfg_0) < 0) | ||
1052 | goto dettach_frontend; | ||
1041 | break; | 1053 | break; |
1042 | case SAA7134_BOARD_FLYDVB_TRIO: | 1054 | case SAA7134_BOARD_FLYDVB_TRIO: |
1043 | if(! use_frontend) { /* terrestrial */ | 1055 | if (!use_frontend) { /* terrestrial */ |
1044 | configure_tda827x_fe(dev, &lifeview_trio_config, &tda827x_cfg_0); | 1056 | if (configure_tda827x_fe(dev, &lifeview_trio_config, |
1057 | &tda827x_cfg_0) < 0) | ||
1058 | goto dettach_frontend; | ||
1045 | } else { /* satellite */ | 1059 | } else { /* satellite */ |
1046 | dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); | 1060 | dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); |
1047 | if (dev->dvb.frontend) { | 1061 | if (dev->dvb.frontend) { |
1048 | if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63, | 1062 | if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63, |
1049 | &dev->i2c_adap, 0) == NULL) { | 1063 | &dev->i2c_adap, 0) == NULL) { |
1050 | wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__); | 1064 | wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__); |
1065 | goto dettach_frontend; | ||
1051 | } | 1066 | } |
1052 | if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap, | 1067 | if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap, |
1053 | 0x08, 0, 0) == NULL) { | 1068 | 0x08, 0, 0) == NULL) { |
1054 | wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__); | 1069 | wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__); |
1070 | goto dettach_frontend; | ||
1055 | } | 1071 | } |
1056 | } | 1072 | } |
1057 | } | 1073 | } |
@@ -1067,15 +1083,21 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1067 | &ads_duo_cfg) == NULL) { | 1083 | &ads_duo_cfg) == NULL) { |
1068 | wprintk("no tda827x tuner found at addr: %02x\n", | 1084 | wprintk("no tda827x tuner found at addr: %02x\n", |
1069 | ads_tech_duo_config.tuner_address); | 1085 | ads_tech_duo_config.tuner_address); |
1086 | goto dettach_frontend; | ||
1070 | } | 1087 | } |
1071 | } | 1088 | } else |
1089 | wprintk("failed to attach tda10046\n"); | ||
1072 | break; | 1090 | break; |
1073 | case SAA7134_BOARD_TEVION_DVBT_220RF: | 1091 | case SAA7134_BOARD_TEVION_DVBT_220RF: |
1074 | configure_tda827x_fe(dev, &tevion_dvbt220rf_config, &tda827x_cfg_0); | 1092 | if (configure_tda827x_fe(dev, &tevion_dvbt220rf_config, |
1093 | &tda827x_cfg_0) < 0) | ||
1094 | goto dettach_frontend; | ||
1075 | break; | 1095 | break; |
1076 | case SAA7134_BOARD_MEDION_MD8800_QUADRO: | 1096 | case SAA7134_BOARD_MEDION_MD8800_QUADRO: |
1077 | if (!use_frontend) { /* terrestrial */ | 1097 | if (!use_frontend) { /* terrestrial */ |
1078 | configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0); | 1098 | if (configure_tda827x_fe(dev, &md8800_dvbt_config, |
1099 | &tda827x_cfg_0) < 0) | ||
1100 | goto dettach_frontend; | ||
1079 | } else { /* satellite */ | 1101 | } else { /* satellite */ |
1080 | dev->dvb.frontend = dvb_attach(tda10086_attach, | 1102 | dev->dvb.frontend = dvb_attach(tda10086_attach, |
1081 | &flydvbs, &dev->i2c_adap); | 1103 | &flydvbs, &dev->i2c_adap); |
@@ -1086,16 +1108,20 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1086 | struct i2c_msg msg = {.addr = 0x08, .flags = 0, .len = 1}; | 1108 | struct i2c_msg msg = {.addr = 0x08, .flags = 0, .len = 1}; |
1087 | 1109 | ||
1088 | if (dvb_attach(tda826x_attach, dev->dvb.frontend, | 1110 | if (dvb_attach(tda826x_attach, dev->dvb.frontend, |
1089 | 0x60, &dev->i2c_adap, 0) == NULL) | 1111 | 0x60, &dev->i2c_adap, 0) == NULL) { |
1090 | wprintk("%s: Medion Quadro, no tda826x " | 1112 | wprintk("%s: Medion Quadro, no tda826x " |
1091 | "found !\n", __func__); | 1113 | "found !\n", __func__); |
1114 | goto dettach_frontend; | ||
1115 | } | ||
1092 | if (dev_id != 0x08) { | 1116 | if (dev_id != 0x08) { |
1093 | /* we need to open the i2c gate (we know it exists) */ | 1117 | /* we need to open the i2c gate (we know it exists) */ |
1094 | fe->ops.i2c_gate_ctrl(fe, 1); | 1118 | fe->ops.i2c_gate_ctrl(fe, 1); |
1095 | if (dvb_attach(isl6405_attach, fe, | 1119 | if (dvb_attach(isl6405_attach, fe, |
1096 | &dev->i2c_adap, 0x08, 0, 0) == NULL) | 1120 | &dev->i2c_adap, 0x08, 0, 0) == NULL) { |
1097 | wprintk("%s: Medion Quadro, no ISL6405 " | 1121 | wprintk("%s: Medion Quadro, no ISL6405 " |
1098 | "found !\n", __func__); | 1122 | "found !\n", __func__); |
1123 | goto dettach_frontend; | ||
1124 | } | ||
1099 | if (dev_id == 0x07) { | 1125 | if (dev_id == 0x07) { |
1100 | /* fire up the 2nd section of the LNB supply since | 1126 | /* fire up the 2nd section of the LNB supply since |
1101 | we can't do this from the other section */ | 1127 | we can't do this from the other section */ |
@@ -1117,19 +1143,17 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1117 | case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: | 1143 | case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: |
1118 | dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180, | 1144 | dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180, |
1119 | &dev->i2c_adap); | 1145 | &dev->i2c_adap); |
1120 | if (dev->dvb.frontend) { | 1146 | if (dev->dvb.frontend) |
1121 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | 1147 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, |
1122 | NULL, DVB_PLL_TDHU2); | 1148 | NULL, DVB_PLL_TDHU2); |
1123 | } | ||
1124 | break; | 1149 | break; |
1125 | case SAA7134_BOARD_KWORLD_ATSC110: | 1150 | case SAA7134_BOARD_KWORLD_ATSC110: |
1126 | dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110, | 1151 | dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110, |
1127 | &dev->i2c_adap); | 1152 | &dev->i2c_adap); |
1128 | if (dev->dvb.frontend) { | 1153 | if (dev->dvb.frontend) |
1129 | dvb_attach(simple_tuner_attach, dev->dvb.frontend, | 1154 | dvb_attach(simple_tuner_attach, dev->dvb.frontend, |
1130 | &dev->i2c_adap, 0x61, | 1155 | &dev->i2c_adap, 0x61, |
1131 | TUNER_PHILIPS_TUV1236D); | 1156 | TUNER_PHILIPS_TUV1236D); |
1132 | } | ||
1133 | break; | 1157 | break; |
1134 | case SAA7134_BOARD_FLYDVBS_LR300: | 1158 | case SAA7134_BOARD_FLYDVBS_LR300: |
1135 | dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, | 1159 | dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, |
@@ -1138,10 +1162,12 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1138 | if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, | 1162 | if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, |
1139 | &dev->i2c_adap, 0) == NULL) { | 1163 | &dev->i2c_adap, 0) == NULL) { |
1140 | wprintk("%s: No tda826x found!\n", __func__); | 1164 | wprintk("%s: No tda826x found!\n", __func__); |
1165 | goto dettach_frontend; | ||
1141 | } | 1166 | } |
1142 | if (dvb_attach(isl6421_attach, dev->dvb.frontend, | 1167 | if (dvb_attach(isl6421_attach, dev->dvb.frontend, |
1143 | &dev->i2c_adap, 0x08, 0, 0) == NULL) { | 1168 | &dev->i2c_adap, 0x08, 0, 0) == NULL) { |
1144 | wprintk("%s: No ISL6421 found!\n", __func__); | 1169 | wprintk("%s: No ISL6421 found!\n", __func__); |
1170 | goto dettach_frontend; | ||
1145 | } | 1171 | } |
1146 | } | 1172 | } |
1147 | break; | 1173 | break; |
@@ -1168,66 +1194,95 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1168 | } | 1194 | } |
1169 | break; | 1195 | break; |
1170 | case SAA7134_BOARD_CINERGY_HT_PCMCIA: | 1196 | case SAA7134_BOARD_CINERGY_HT_PCMCIA: |
1171 | configure_tda827x_fe(dev, &cinergy_ht_config, &tda827x_cfg_0); | 1197 | if (configure_tda827x_fe(dev, &cinergy_ht_config, |
1198 | &tda827x_cfg_0) < 0) | ||
1199 | goto dettach_frontend; | ||
1172 | break; | 1200 | break; |
1173 | case SAA7134_BOARD_CINERGY_HT_PCI: | 1201 | case SAA7134_BOARD_CINERGY_HT_PCI: |
1174 | configure_tda827x_fe(dev, &cinergy_ht_pci_config, &tda827x_cfg_0); | 1202 | if (configure_tda827x_fe(dev, &cinergy_ht_pci_config, |
1203 | &tda827x_cfg_0) < 0) | ||
1204 | goto dettach_frontend; | ||
1175 | break; | 1205 | break; |
1176 | case SAA7134_BOARD_PHILIPS_TIGER_S: | 1206 | case SAA7134_BOARD_PHILIPS_TIGER_S: |
1177 | configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2); | 1207 | if (configure_tda827x_fe(dev, &philips_tiger_s_config, |
1208 | &tda827x_cfg_2) < 0) | ||
1209 | goto dettach_frontend; | ||
1178 | break; | 1210 | break; |
1179 | case SAA7134_BOARD_ASUS_P7131_4871: | 1211 | case SAA7134_BOARD_ASUS_P7131_4871: |
1180 | configure_tda827x_fe(dev, &asus_p7131_4871_config, &tda827x_cfg_2); | 1212 | if (configure_tda827x_fe(dev, &asus_p7131_4871_config, |
1213 | &tda827x_cfg_2) < 0) | ||
1214 | goto dettach_frontend; | ||
1181 | break; | 1215 | break; |
1182 | case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: | 1216 | case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: |
1183 | configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config, &tda827x_cfg_2); | 1217 | if (configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config, |
1218 | &tda827x_cfg_2) < 0) | ||
1219 | goto dettach_frontend; | ||
1184 | break; | 1220 | break; |
1185 | case SAA7134_BOARD_AVERMEDIA_SUPER_007: | 1221 | case SAA7134_BOARD_AVERMEDIA_SUPER_007: |
1186 | configure_tda827x_fe(dev, &avermedia_super_007_config, &tda827x_cfg_0); | 1222 | if (configure_tda827x_fe(dev, &avermedia_super_007_config, |
1223 | &tda827x_cfg_0) < 0) | ||
1224 | goto dettach_frontend; | ||
1187 | break; | 1225 | break; |
1188 | case SAA7134_BOARD_TWINHAN_DTV_DVB_3056: | 1226 | case SAA7134_BOARD_TWINHAN_DTV_DVB_3056: |
1189 | configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config, &tda827x_cfg_2_sw42); | 1227 | if (configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config, |
1228 | &tda827x_cfg_2_sw42) < 0) | ||
1229 | goto dettach_frontend; | ||
1190 | break; | 1230 | break; |
1191 | case SAA7134_BOARD_PHILIPS_SNAKE: | 1231 | case SAA7134_BOARD_PHILIPS_SNAKE: |
1192 | dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, | 1232 | dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, |
1193 | &dev->i2c_adap); | 1233 | &dev->i2c_adap); |
1194 | if (dev->dvb.frontend) { | 1234 | if (dev->dvb.frontend) { |
1195 | if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, | 1235 | if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, |
1196 | &dev->i2c_adap, 0) == NULL) | 1236 | &dev->i2c_adap, 0) == NULL) { |
1197 | wprintk("%s: No tda826x found!\n", __func__); | 1237 | wprintk("%s: No tda826x found!\n", __func__); |
1238 | goto dettach_frontend; | ||
1239 | } | ||
1198 | if (dvb_attach(lnbp21_attach, dev->dvb.frontend, | 1240 | if (dvb_attach(lnbp21_attach, dev->dvb.frontend, |
1199 | &dev->i2c_adap, 0, 0) == NULL) | 1241 | &dev->i2c_adap, 0, 0) == NULL) { |
1200 | wprintk("%s: No lnbp21 found!\n", __func__); | 1242 | wprintk("%s: No lnbp21 found!\n", __func__); |
1243 | goto dettach_frontend; | ||
1244 | } | ||
1201 | } | 1245 | } |
1202 | break; | 1246 | break; |
1203 | case SAA7134_BOARD_CREATIX_CTX953: | 1247 | case SAA7134_BOARD_CREATIX_CTX953: |
1204 | configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0); | 1248 | if (configure_tda827x_fe(dev, &md8800_dvbt_config, |
1249 | &tda827x_cfg_0) < 0) | ||
1250 | goto dettach_frontend; | ||
1205 | break; | 1251 | break; |
1206 | case SAA7134_BOARD_MSI_TVANYWHERE_AD11: | 1252 | case SAA7134_BOARD_MSI_TVANYWHERE_AD11: |
1207 | configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2); | 1253 | if (configure_tda827x_fe(dev, &philips_tiger_s_config, |
1254 | &tda827x_cfg_2) < 0) | ||
1255 | goto dettach_frontend; | ||
1208 | break; | 1256 | break; |
1209 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: | 1257 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: |
1258 | dprintk("AverMedia E506R dvb setup\n"); | ||
1259 | saa7134_set_gpio(dev, 25, 0); | ||
1260 | msleep(10); | ||
1261 | saa7134_set_gpio(dev, 25, 1); | ||
1210 | dev->dvb.frontend = dvb_attach(mt352_attach, | 1262 | dev->dvb.frontend = dvb_attach(mt352_attach, |
1211 | &avermedia_e506r_mt352_dev, | 1263 | &avermedia_xc3028_mt352_dev, |
1212 | &dev->i2c_adap); | 1264 | &dev->i2c_adap); |
1213 | attach_xc3028 = 1; | 1265 | attach_xc3028 = 1; |
1214 | break; | ||
1215 | case SAA7134_BOARD_MD7134_BRIDGE_2: | 1266 | case SAA7134_BOARD_MD7134_BRIDGE_2: |
1216 | dev->dvb.frontend = dvb_attach(tda10086_attach, | 1267 | dev->dvb.frontend = dvb_attach(tda10086_attach, |
1217 | &sd1878_4m, &dev->i2c_adap); | 1268 | &sd1878_4m, &dev->i2c_adap); |
1218 | if (dev->dvb.frontend) { | 1269 | if (dev->dvb.frontend) { |
1219 | struct dvb_frontend *fe; | 1270 | struct dvb_frontend *fe; |
1220 | if (dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, | 1271 | if (dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, |
1221 | &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) | 1272 | &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) { |
1222 | wprintk("%s: MD7134 DVB-S, no SD1878 " | 1273 | wprintk("%s: MD7134 DVB-S, no SD1878 " |
1223 | "found !\n", __func__); | 1274 | "found !\n", __func__); |
1275 | goto dettach_frontend; | ||
1276 | } | ||
1224 | /* we need to open the i2c gate (we know it exists) */ | 1277 | /* we need to open the i2c gate (we know it exists) */ |
1225 | fe = dev->dvb.frontend; | 1278 | fe = dev->dvb.frontend; |
1226 | fe->ops.i2c_gate_ctrl(fe, 1); | 1279 | fe->ops.i2c_gate_ctrl(fe, 1); |
1227 | if (dvb_attach(isl6405_attach, fe, | 1280 | if (dvb_attach(isl6405_attach, fe, |
1228 | &dev->i2c_adap, 0x08, 0, 0) == NULL) | 1281 | &dev->i2c_adap, 0x08, 0, 0) == NULL) { |
1229 | wprintk("%s: MD7134 DVB-S, no ISL6405 " | 1282 | wprintk("%s: MD7134 DVB-S, no ISL6405 " |
1230 | "found !\n", __func__); | 1283 | "found !\n", __func__); |
1284 | goto dettach_frontend; | ||
1285 | } | ||
1231 | fe->ops.i2c_gate_ctrl(fe, 0); | 1286 | fe->ops.i2c_gate_ctrl(fe, 0); |
1232 | dev->original_set_voltage = fe->ops.set_voltage; | 1287 | dev->original_set_voltage = fe->ops.set_voltage; |
1233 | fe->ops.set_voltage = md8800_set_voltage; | 1288 | fe->ops.set_voltage = md8800_set_voltage; |
@@ -1254,10 +1309,7 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1254 | if (!fe) { | 1309 | if (!fe) { |
1255 | printk(KERN_ERR "%s/2: xc3028 attach failed\n", | 1310 | printk(KERN_ERR "%s/2: xc3028 attach failed\n", |
1256 | dev->name); | 1311 | dev->name); |
1257 | dvb_frontend_detach(dev->dvb.frontend); | 1312 | goto dettach_frontend; |
1258 | dvb_unregister_frontend(dev->dvb.frontend); | ||
1259 | dev->dvb.frontend = NULL; | ||
1260 | return -1; | ||
1261 | } | 1313 | } |
1262 | } | 1314 | } |
1263 | 1315 | ||
@@ -1282,6 +1334,13 @@ static int dvb_init(struct saa7134_dev *dev) | |||
1282 | dev->dvb.frontend->ops.tuner_ops.sleep(dev->dvb.frontend); | 1334 | dev->dvb.frontend->ops.tuner_ops.sleep(dev->dvb.frontend); |
1283 | } | 1335 | } |
1284 | return ret; | 1336 | return ret; |
1337 | |||
1338 | dettach_frontend: | ||
1339 | if (dev->dvb.frontend) | ||
1340 | dvb_frontend_detach(dev->dvb.frontend); | ||
1341 | dev->dvb.frontend = NULL; | ||
1342 | |||
1343 | return -1; | ||
1285 | } | 1344 | } |
1286 | 1345 | ||
1287 | static int dvb_fini(struct saa7134_dev *dev) | 1346 | static int dvb_fini(struct saa7134_dev *dev) |
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 1314522a8130..3ae71a340822 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c | |||
@@ -110,9 +110,10 @@ static int ts_release(struct inode *inode, struct file *file) | |||
110 | { | 110 | { |
111 | struct saa7134_dev *dev = file->private_data; | 111 | struct saa7134_dev *dev = file->private_data; |
112 | 112 | ||
113 | mutex_lock(&dev->empress_tsq.vb_lock); | ||
114 | |||
113 | videobuf_stop(&dev->empress_tsq); | 115 | videobuf_stop(&dev->empress_tsq); |
114 | videobuf_mmap_free(&dev->empress_tsq); | 116 | videobuf_mmap_free(&dev->empress_tsq); |
115 | dev->empress_users--; | ||
116 | 117 | ||
117 | /* stop the encoder */ | 118 | /* stop the encoder */ |
118 | ts_reset_encoder(dev); | 119 | ts_reset_encoder(dev); |
@@ -121,6 +122,10 @@ static int ts_release(struct inode *inode, struct file *file) | |||
121 | saa_writeb(SAA7134_AUDIO_MUTE_CTRL, | 122 | saa_writeb(SAA7134_AUDIO_MUTE_CTRL, |
122 | saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6)); | 123 | saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6)); |
123 | 124 | ||
125 | dev->empress_users--; | ||
126 | |||
127 | mutex_unlock(&dev->empress_tsq.vb_lock); | ||
128 | |||
124 | return 0; | 129 | return 0; |
125 | } | 130 | } |
126 | 131 | ||
@@ -163,8 +168,7 @@ ts_mmap(struct file *file, struct vm_area_struct * vma) | |||
163 | static int empress_querycap(struct file *file, void *priv, | 168 | static int empress_querycap(struct file *file, void *priv, |
164 | struct v4l2_capability *cap) | 169 | struct v4l2_capability *cap) |
165 | { | 170 | { |
166 | struct saa7134_fh *fh = priv; | 171 | struct saa7134_dev *dev = file->private_data; |
167 | struct saa7134_dev *dev = fh->dev; | ||
168 | 172 | ||
169 | strcpy(cap->driver, "saa7134"); | 173 | strcpy(cap->driver, "saa7134"); |
170 | strlcpy(cap->card, saa7134_boards[dev->board].name, | 174 | strlcpy(cap->card, saa7134_boards[dev->board].name, |
@@ -219,8 +223,7 @@ static int empress_enum_fmt_cap(struct file *file, void *priv, | |||
219 | static int empress_g_fmt_cap(struct file *file, void *priv, | 223 | static int empress_g_fmt_cap(struct file *file, void *priv, |
220 | struct v4l2_format *f) | 224 | struct v4l2_format *f) |
221 | { | 225 | { |
222 | struct saa7134_fh *fh = priv; | 226 | struct saa7134_dev *dev = file->private_data; |
223 | struct saa7134_dev *dev = fh->dev; | ||
224 | 227 | ||
225 | saa7134_i2c_call_clients(dev, VIDIOC_G_FMT, f); | 228 | saa7134_i2c_call_clients(dev, VIDIOC_G_FMT, f); |
226 | 229 | ||
@@ -233,8 +236,7 @@ static int empress_g_fmt_cap(struct file *file, void *priv, | |||
233 | static int empress_s_fmt_cap(struct file *file, void *priv, | 236 | static int empress_s_fmt_cap(struct file *file, void *priv, |
234 | struct v4l2_format *f) | 237 | struct v4l2_format *f) |
235 | { | 238 | { |
236 | struct saa7134_fh *fh = priv; | 239 | struct saa7134_dev *dev = file->private_data; |
237 | struct saa7134_dev *dev = fh->dev; | ||
238 | 240 | ||
239 | saa7134_i2c_call_clients(dev, VIDIOC_S_FMT, f); | 241 | saa7134_i2c_call_clients(dev, VIDIOC_S_FMT, f); |
240 | 242 | ||
@@ -248,8 +250,7 @@ static int empress_s_fmt_cap(struct file *file, void *priv, | |||
248 | static int empress_reqbufs(struct file *file, void *priv, | 250 | static int empress_reqbufs(struct file *file, void *priv, |
249 | struct v4l2_requestbuffers *p) | 251 | struct v4l2_requestbuffers *p) |
250 | { | 252 | { |
251 | struct saa7134_fh *fh = priv; | 253 | struct saa7134_dev *dev = file->private_data; |
252 | struct saa7134_dev *dev = fh->dev; | ||
253 | 254 | ||
254 | return videobuf_reqbufs(&dev->empress_tsq, p); | 255 | return videobuf_reqbufs(&dev->empress_tsq, p); |
255 | } | 256 | } |
@@ -257,24 +258,21 @@ static int empress_reqbufs(struct file *file, void *priv, | |||
257 | static int empress_querybuf(struct file *file, void *priv, | 258 | static int empress_querybuf(struct file *file, void *priv, |
258 | struct v4l2_buffer *b) | 259 | struct v4l2_buffer *b) |
259 | { | 260 | { |
260 | struct saa7134_fh *fh = priv; | 261 | struct saa7134_dev *dev = file->private_data; |
261 | struct saa7134_dev *dev = fh->dev; | ||
262 | 262 | ||
263 | return videobuf_querybuf(&dev->empress_tsq, b); | 263 | return videobuf_querybuf(&dev->empress_tsq, b); |
264 | } | 264 | } |
265 | 265 | ||
266 | static int empress_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) | 266 | static int empress_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) |
267 | { | 267 | { |
268 | struct saa7134_fh *fh = priv; | 268 | struct saa7134_dev *dev = file->private_data; |
269 | struct saa7134_dev *dev = fh->dev; | ||
270 | 269 | ||
271 | return videobuf_qbuf(&dev->empress_tsq, b); | 270 | return videobuf_qbuf(&dev->empress_tsq, b); |
272 | } | 271 | } |
273 | 272 | ||
274 | static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) | 273 | static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) |
275 | { | 274 | { |
276 | struct saa7134_fh *fh = priv; | 275 | struct saa7134_dev *dev = file->private_data; |
277 | struct saa7134_dev *dev = fh->dev; | ||
278 | 276 | ||
279 | return videobuf_dqbuf(&dev->empress_tsq, b, | 277 | return videobuf_dqbuf(&dev->empress_tsq, b, |
280 | file->f_flags & O_NONBLOCK); | 278 | file->f_flags & O_NONBLOCK); |
@@ -283,8 +281,7 @@ static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) | |||
283 | static int empress_streamon(struct file *file, void *priv, | 281 | static int empress_streamon(struct file *file, void *priv, |
284 | enum v4l2_buf_type type) | 282 | enum v4l2_buf_type type) |
285 | { | 283 | { |
286 | struct saa7134_fh *fh = priv; | 284 | struct saa7134_dev *dev = file->private_data; |
287 | struct saa7134_dev *dev = fh->dev; | ||
288 | 285 | ||
289 | return videobuf_streamon(&dev->empress_tsq); | 286 | return videobuf_streamon(&dev->empress_tsq); |
290 | } | 287 | } |
@@ -292,8 +289,7 @@ static int empress_streamon(struct file *file, void *priv, | |||
292 | static int empress_streamoff(struct file *file, void *priv, | 289 | static int empress_streamoff(struct file *file, void *priv, |
293 | enum v4l2_buf_type type) | 290 | enum v4l2_buf_type type) |
294 | { | 291 | { |
295 | struct saa7134_fh *fh = priv; | 292 | struct saa7134_dev *dev = file->private_data; |
296 | struct saa7134_dev *dev = fh->dev; | ||
297 | 293 | ||
298 | return videobuf_streamoff(&dev->empress_tsq); | 294 | return videobuf_streamoff(&dev->empress_tsq); |
299 | } | 295 | } |
@@ -301,8 +297,7 @@ static int empress_streamoff(struct file *file, void *priv, | |||
301 | static int empress_s_ext_ctrls(struct file *file, void *priv, | 297 | static int empress_s_ext_ctrls(struct file *file, void *priv, |
302 | struct v4l2_ext_controls *ctrls) | 298 | struct v4l2_ext_controls *ctrls) |
303 | { | 299 | { |
304 | struct saa7134_fh *fh = priv; | 300 | struct saa7134_dev *dev = file->private_data; |
305 | struct saa7134_dev *dev = fh->dev; | ||
306 | 301 | ||
307 | /* count == 0 is abused in saa6752hs.c, so that special | 302 | /* count == 0 is abused in saa6752hs.c, so that special |
308 | case is handled here explicitly. */ | 303 | case is handled here explicitly. */ |
@@ -321,8 +316,7 @@ static int empress_s_ext_ctrls(struct file *file, void *priv, | |||
321 | static int empress_g_ext_ctrls(struct file *file, void *priv, | 316 | static int empress_g_ext_ctrls(struct file *file, void *priv, |
322 | struct v4l2_ext_controls *ctrls) | 317 | struct v4l2_ext_controls *ctrls) |
323 | { | 318 | { |
324 | struct saa7134_fh *fh = priv; | 319 | struct saa7134_dev *dev = file->private_data; |
325 | struct saa7134_dev *dev = fh->dev; | ||
326 | 320 | ||
327 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) | 321 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) |
328 | return -EINVAL; | 322 | return -EINVAL; |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 919632b10aae..76e6501d238d 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -323,6 +323,15 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
323 | saa_setb(SAA7134_GPIO_GPMODE1, 0x1); | 323 | saa_setb(SAA7134_GPIO_GPMODE1, 0x1); |
324 | saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); | 324 | saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); |
325 | break; | 325 | break; |
326 | case SAA7134_BOARD_AVERMEDIA_A16D: | ||
327 | ir_codes = ir_codes_avermedia_a16d; | ||
328 | mask_keycode = 0x02F200; | ||
329 | mask_keydown = 0x000400; | ||
330 | polling = 50; /* ms */ | ||
331 | /* Without this we won't receive key up events */ | ||
332 | saa_setb(SAA7134_GPIO_GPMODE1, 0x1); | ||
333 | saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); | ||
334 | break; | ||
326 | case SAA7134_BOARD_KWORLD_TERMINATOR: | 335 | case SAA7134_BOARD_KWORLD_TERMINATOR: |
327 | ir_codes = ir_codes_pixelview; | 336 | ir_codes = ir_codes_pixelview; |
328 | mask_keycode = 0x00001f; | 337 | mask_keycode = 0x00001f; |
diff --git a/drivers/media/video/saa717x.c b/drivers/media/video/saa717x.c index 72c4081feff5..2220f9569941 100644 --- a/drivers/media/video/saa717x.c +++ b/drivers/media/video/saa717x.c | |||
@@ -1429,8 +1429,6 @@ static int saa717x_probe(struct i2c_client *client, | |||
1429 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 1429 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
1430 | return -EIO; | 1430 | return -EIO; |
1431 | 1431 | ||
1432 | snprintf(client->name, sizeof(client->name) - 1, "saa717x"); | ||
1433 | |||
1434 | if (saa717x_write(client, 0x5a4, 0xfe) && | 1432 | if (saa717x_write(client, 0x5a4, 0xfe) && |
1435 | saa717x_write(client, 0x5a5, 0x0f) && | 1433 | saa717x_write(client, 0x5a5, 0x0f) && |
1436 | saa717x_write(client, 0x5a6, 0x00) && | 1434 | saa717x_write(client, 0x5a6, 0x00) && |
@@ -1507,6 +1505,12 @@ static int saa717x_remove(struct i2c_client *client) | |||
1507 | 1505 | ||
1508 | /* ----------------------------------------------------------------------- */ | 1506 | /* ----------------------------------------------------------------------- */ |
1509 | 1507 | ||
1508 | static const struct i2c_device_id saa717x_id[] = { | ||
1509 | { "saa717x", 0 }, | ||
1510 | { } | ||
1511 | }; | ||
1512 | MODULE_DEVICE_TABLE(i2c, saa717x_id); | ||
1513 | |||
1510 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 1514 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
1511 | .name = "saa717x", | 1515 | .name = "saa717x", |
1512 | .driverid = I2C_DRIVERID_SAA717X, | 1516 | .driverid = I2C_DRIVERID_SAA717X, |
@@ -1514,4 +1518,5 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { | |||
1514 | .probe = saa717x_probe, | 1518 | .probe = saa717x_probe, |
1515 | .remove = saa717x_remove, | 1519 | .remove = saa717x_remove, |
1516 | .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, | 1520 | .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL, |
1521 | .id_table = saa717x_id, | ||
1517 | }; | 1522 | }; |
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 5748b1e1a128..7f9c7bcf3c85 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include <linux/mm.h> | 34 | #include <linux/mm.h> |
35 | #include <linux/vmalloc.h> | 35 | #include <linux/vmalloc.h> |
36 | #include <linux/page-flags.h> | 36 | #include <linux/page-flags.h> |
37 | #include <linux/byteorder/generic.h> | 37 | #include <asm/byteorder.h> |
38 | #include <asm/page.h> | 38 | #include <asm/page.h> |
39 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
40 | 40 | ||
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index a1b92446c8b4..d015bfe00950 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -763,15 +763,6 @@ static struct device_driver ic_drv = { | |||
763 | .owner = THIS_MODULE, | 763 | .owner = THIS_MODULE, |
764 | }; | 764 | }; |
765 | 765 | ||
766 | /* | ||
767 | * Image capture host - this is a host device, not a bus device, so, | ||
768 | * no bus reference, no probing. | ||
769 | */ | ||
770 | static struct class soc_camera_host_class = { | ||
771 | .owner = THIS_MODULE, | ||
772 | .name = "camera_host", | ||
773 | }; | ||
774 | |||
775 | static void dummy_release(struct device *dev) | 766 | static void dummy_release(struct device *dev) |
776 | { | 767 | { |
777 | } | 768 | } |
@@ -801,7 +792,6 @@ int soc_camera_host_register(struct soc_camera_host *ici) | |||
801 | 792 | ||
802 | /* Number might be equal to the platform device ID */ | 793 | /* Number might be equal to the platform device ID */ |
803 | sprintf(ici->dev.bus_id, "camera_host%d", ici->nr); | 794 | sprintf(ici->dev.bus_id, "camera_host%d", ici->nr); |
804 | ici->dev.class = &soc_camera_host_class; | ||
805 | 795 | ||
806 | mutex_lock(&list_lock); | 796 | mutex_lock(&list_lock); |
807 | list_for_each_entry(ix, &hosts, list) { | 797 | list_for_each_entry(ix, &hosts, list) { |
@@ -1003,14 +993,9 @@ static int __init soc_camera_init(void) | |||
1003 | ret = driver_register(&ic_drv); | 993 | ret = driver_register(&ic_drv); |
1004 | if (ret) | 994 | if (ret) |
1005 | goto edrvr; | 995 | goto edrvr; |
1006 | ret = class_register(&soc_camera_host_class); | ||
1007 | if (ret) | ||
1008 | goto eclr; | ||
1009 | 996 | ||
1010 | return 0; | 997 | return 0; |
1011 | 998 | ||
1012 | eclr: | ||
1013 | driver_unregister(&ic_drv); | ||
1014 | edrvr: | 999 | edrvr: |
1015 | bus_unregister(&soc_camera_bus_type); | 1000 | bus_unregister(&soc_camera_bus_type); |
1016 | return ret; | 1001 | return ret; |
@@ -1018,7 +1003,6 @@ edrvr: | |||
1018 | 1003 | ||
1019 | static void __exit soc_camera_exit(void) | 1004 | static void __exit soc_camera_exit(void) |
1020 | { | 1005 | { |
1021 | class_unregister(&soc_camera_host_class); | ||
1022 | driver_unregister(&ic_drv); | 1006 | driver_unregister(&ic_drv); |
1023 | bus_unregister(&soc_camera_bus_type); | 1007 | bus_unregister(&soc_camera_bus_type); |
1024 | } | 1008 | } |
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index 9276ed997388..b12c60cf5a09 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/kref.h> | 30 | #include <linux/kref.h> |
31 | 31 | ||
32 | #include <linux/usb.h> | 32 | #include <linux/usb.h> |
33 | #include <linux/mm.h> | ||
33 | #include <linux/vmalloc.h> | 34 | #include <linux/vmalloc.h> |
34 | #include <linux/videodev2.h> | 35 | #include <linux/videodev2.h> |
35 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
@@ -245,6 +246,8 @@ static int stk_initialise(struct stk_camera *dev) | |||
245 | return -1; | 246 | return -1; |
246 | } | 247 | } |
247 | 248 | ||
249 | #ifdef CONFIG_VIDEO_V4L1_COMPAT | ||
250 | |||
248 | /* sysfs functions */ | 251 | /* sysfs functions */ |
249 | /*FIXME cleanup this */ | 252 | /*FIXME cleanup this */ |
250 | 253 | ||
@@ -350,6 +353,10 @@ static void stk_remove_sysfs_files(struct video_device *vdev) | |||
350 | video_device_remove_file(vdev, &dev_attr_vflip); | 353 | video_device_remove_file(vdev, &dev_attr_vflip); |
351 | } | 354 | } |
352 | 355 | ||
356 | #else | ||
357 | #define stk_create_sysfs_files(a) | ||
358 | #define stk_remove_sysfs_files(a) | ||
359 | #endif | ||
353 | 360 | ||
354 | /* *********************************************** */ | 361 | /* *********************************************** */ |
355 | /* | 362 | /* |
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 6bf104ea051d..0d12ace61665 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -40,11 +40,11 @@ | |||
40 | typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ | 40 | typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ |
41 | if (__a) { \ | 41 | if (__a) { \ |
42 | __r = (int) __a(ARGS); \ | 42 | __r = (int) __a(ARGS); \ |
43 | symbol_put(FUNCTION); \ | ||
43 | } else { \ | 44 | } else { \ |
44 | printk(KERN_ERR "TUNER: Unable to find " \ | 45 | printk(KERN_ERR "TUNER: Unable to find " \ |
45 | "symbol "#FUNCTION"()\n"); \ | 46 | "symbol "#FUNCTION"()\n"); \ |
46 | } \ | 47 | } \ |
47 | symbol_put(FUNCTION); \ | ||
48 | __r; \ | 48 | __r; \ |
49 | }) | 49 | }) |
50 | 50 | ||
@@ -92,6 +92,7 @@ struct tuner { | |||
92 | unsigned int type; /* chip type id */ | 92 | unsigned int type; /* chip type id */ |
93 | unsigned int config; | 93 | unsigned int config; |
94 | int (*tuner_callback) (void *dev, int command, int arg); | 94 | int (*tuner_callback) (void *dev, int command, int arg); |
95 | const char *name; | ||
95 | }; | 96 | }; |
96 | 97 | ||
97 | /* standard i2c insmod options */ | 98 | /* standard i2c insmod options */ |
@@ -330,26 +331,16 @@ static void tuner_i2c_address_check(struct tuner *t) | |||
330 | tuner_warn("Support for tuners in i2c address range 0x64 thru 0x6f\n"); | 331 | tuner_warn("Support for tuners in i2c address range 0x64 thru 0x6f\n"); |
331 | tuner_warn("will soon be dropped. This message indicates that your\n"); | 332 | tuner_warn("will soon be dropped. This message indicates that your\n"); |
332 | tuner_warn("hardware has a %s tuner at i2c address 0x%02x.\n", | 333 | tuner_warn("hardware has a %s tuner at i2c address 0x%02x.\n", |
333 | t->i2c->name, t->i2c->addr); | 334 | t->name, t->i2c->addr); |
334 | tuner_warn("To ensure continued support for your device, please\n"); | 335 | tuner_warn("To ensure continued support for your device, please\n"); |
335 | tuner_warn("send a copy of this message, along with full dmesg\n"); | 336 | tuner_warn("send a copy of this message, along with full dmesg\n"); |
336 | tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n"); | 337 | tuner_warn("output to v4l-dvb-maintainer@linuxtv.org\n"); |
337 | tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n"); | 338 | tuner_warn("Please use subject line: \"obsolete tuner i2c address.\"\n"); |
338 | tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n", | 339 | tuner_warn("driver: %s, addr: 0x%02x, type: %d (%s)\n", |
339 | t->i2c->adapter->name, t->i2c->addr, t->type, t->i2c->name); | 340 | t->i2c->adapter->name, t->i2c->addr, t->type, t->name); |
340 | tuner_warn("====================== WARNING! ======================\n"); | 341 | tuner_warn("====================== WARNING! ======================\n"); |
341 | } | 342 | } |
342 | 343 | ||
343 | static void attach_tda829x(struct tuner *t) | ||
344 | { | ||
345 | struct tda829x_config cfg = { | ||
346 | .lna_cfg = t->config, | ||
347 | .tuner_callback = t->tuner_callback, | ||
348 | }; | ||
349 | dvb_attach(tda829x_attach, | ||
350 | &t->fe, t->i2c->adapter, t->i2c->addr, &cfg); | ||
351 | } | ||
352 | |||
353 | static struct xc5000_config xc5000_cfg; | 344 | static struct xc5000_config xc5000_cfg; |
354 | 345 | ||
355 | static void set_type(struct i2c_client *c, unsigned int type, | 346 | static void set_type(struct i2c_client *c, unsigned int type, |
@@ -385,12 +376,19 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
385 | 376 | ||
386 | switch (t->type) { | 377 | switch (t->type) { |
387 | case TUNER_MT2032: | 378 | case TUNER_MT2032: |
388 | dvb_attach(microtune_attach, | 379 | if (!dvb_attach(microtune_attach, |
389 | &t->fe, t->i2c->adapter, t->i2c->addr); | 380 | &t->fe, t->i2c->adapter, t->i2c->addr)) |
381 | goto attach_failed; | ||
390 | break; | 382 | break; |
391 | case TUNER_PHILIPS_TDA8290: | 383 | case TUNER_PHILIPS_TDA8290: |
392 | { | 384 | { |
393 | attach_tda829x(t); | 385 | struct tda829x_config cfg = { |
386 | .lna_cfg = t->config, | ||
387 | .tuner_callback = t->tuner_callback, | ||
388 | }; | ||
389 | if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter, | ||
390 | t->i2c->addr, &cfg)) | ||
391 | goto attach_failed; | ||
394 | break; | 392 | break; |
395 | } | 393 | } |
396 | case TUNER_TEA5767: | 394 | case TUNER_TEA5767: |
@@ -441,8 +439,9 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
441 | break; | 439 | break; |
442 | } | 440 | } |
443 | case TUNER_TDA9887: | 441 | case TUNER_TDA9887: |
444 | dvb_attach(tda9887_attach, | 442 | if (!dvb_attach(tda9887_attach, |
445 | &t->fe, t->i2c->adapter, t->i2c->addr); | 443 | &t->fe, t->i2c->adapter, t->i2c->addr)) |
444 | goto attach_failed; | ||
446 | break; | 445 | break; |
447 | case TUNER_XC5000: | 446 | case TUNER_XC5000: |
448 | { | 447 | { |
@@ -450,10 +449,10 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
450 | 449 | ||
451 | xc5000_cfg.i2c_address = t->i2c->addr; | 450 | xc5000_cfg.i2c_address = t->i2c->addr; |
452 | xc5000_cfg.if_khz = 5380; | 451 | xc5000_cfg.if_khz = 5380; |
453 | xc5000_cfg.priv = c->adapter->algo_data; | ||
454 | xc5000_cfg.tuner_callback = t->tuner_callback; | 452 | xc5000_cfg.tuner_callback = t->tuner_callback; |
455 | if (!dvb_attach(xc5000_attach, | 453 | if (!dvb_attach(xc5000_attach, |
456 | &t->fe, t->i2c->adapter, &xc5000_cfg)) | 454 | &t->fe, t->i2c->adapter, &xc5000_cfg, |
455 | c->adapter->algo_data)) | ||
457 | goto attach_failed; | 456 | goto attach_failed; |
458 | 457 | ||
459 | xc_tuner_ops = &t->fe.ops.tuner_ops; | 458 | xc_tuner_ops = &t->fe.ops.tuner_ops; |
@@ -472,19 +471,17 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
472 | if ((NULL == analog_ops->set_params) && | 471 | if ((NULL == analog_ops->set_params) && |
473 | (fe_tuner_ops->set_analog_params)) { | 472 | (fe_tuner_ops->set_analog_params)) { |
474 | 473 | ||
475 | strlcpy(t->i2c->name, fe_tuner_ops->info.name, | 474 | t->name = fe_tuner_ops->info.name; |
476 | sizeof(t->i2c->name)); | ||
477 | 475 | ||
478 | t->fe.analog_demod_priv = t; | 476 | t->fe.analog_demod_priv = t; |
479 | memcpy(analog_ops, &tuner_core_ops, | 477 | memcpy(analog_ops, &tuner_core_ops, |
480 | sizeof(struct analog_demod_ops)); | 478 | sizeof(struct analog_demod_ops)); |
481 | 479 | ||
482 | } else { | 480 | } else { |
483 | strlcpy(t->i2c->name, analog_ops->info.name, | 481 | t->name = analog_ops->info.name; |
484 | sizeof(t->i2c->name)); | ||
485 | } | 482 | } |
486 | 483 | ||
487 | tuner_dbg("type set to %s\n", t->i2c->name); | 484 | tuner_dbg("type set to %s\n", t->name); |
488 | 485 | ||
489 | if (t->mode_mask == T_UNINITIALIZED) | 486 | if (t->mode_mask == T_UNINITIALIZED) |
490 | t->mode_mask = new_mode_mask; | 487 | t->mode_mask = new_mode_mask; |
@@ -539,7 +536,7 @@ static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup) | |||
539 | static inline int check_mode(struct tuner *t, char *cmd) | 536 | static inline int check_mode(struct tuner *t, char *cmd) |
540 | { | 537 | { |
541 | if ((1 << t->mode & t->mode_mask) == 0) { | 538 | if ((1 << t->mode & t->mode_mask) == 0) { |
542 | return EINVAL; | 539 | return -EINVAL; |
543 | } | 540 | } |
544 | 541 | ||
545 | switch (t->mode) { | 542 | switch (t->mode) { |
@@ -733,11 +730,11 @@ static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, | |||
733 | 730 | ||
734 | t->mode = mode; | 731 | t->mode = mode; |
735 | 732 | ||
736 | if (check_mode(t, cmd) == EINVAL) { | 733 | if (check_mode(t, cmd) == -EINVAL) { |
737 | t->mode = T_STANDBY; | 734 | t->mode = T_STANDBY; |
738 | if (analog_ops->standby) | 735 | if (analog_ops->standby) |
739 | analog_ops->standby(&t->fe); | 736 | analog_ops->standby(&t->fe); |
740 | return EINVAL; | 737 | return -EINVAL; |
741 | } | 738 | } |
742 | return 0; | 739 | return 0; |
743 | } | 740 | } |
@@ -779,13 +776,13 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
779 | break; | 776 | break; |
780 | case AUDC_SET_RADIO: | 777 | case AUDC_SET_RADIO: |
781 | if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO") | 778 | if (set_mode(client, t, V4L2_TUNER_RADIO, "AUDC_SET_RADIO") |
782 | == EINVAL) | 779 | == -EINVAL) |
783 | return 0; | 780 | return 0; |
784 | if (t->radio_freq) | 781 | if (t->radio_freq) |
785 | set_freq(client, t->radio_freq); | 782 | set_freq(client, t->radio_freq); |
786 | break; | 783 | break; |
787 | case TUNER_SET_STANDBY: | 784 | case TUNER_SET_STANDBY: |
788 | if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL) | 785 | if (check_mode(t, "TUNER_SET_STANDBY") == -EINVAL) |
789 | return 0; | 786 | return 0; |
790 | t->mode = T_STANDBY; | 787 | t->mode = T_STANDBY; |
791 | if (analog_ops->standby) | 788 | if (analog_ops->standby) |
@@ -793,9 +790,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
793 | break; | 790 | break; |
794 | #ifdef CONFIG_VIDEO_ALLOW_V4L1 | 791 | #ifdef CONFIG_VIDEO_ALLOW_V4L1 |
795 | case VIDIOCSAUDIO: | 792 | case VIDIOCSAUDIO: |
796 | if (check_mode(t, "VIDIOCSAUDIO") == EINVAL) | 793 | if (check_mode(t, "VIDIOCSAUDIO") == -EINVAL) |
797 | return 0; | 794 | return 0; |
798 | if (check_v4l2(t) == EINVAL) | 795 | if (check_v4l2(t) == -EINVAL) |
799 | return 0; | 796 | return 0; |
800 | 797 | ||
801 | /* Should be implemented, since bttv calls it */ | 798 | /* Should be implemented, since bttv calls it */ |
@@ -813,10 +810,10 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
813 | }; | 810 | }; |
814 | struct video_channel *vc = arg; | 811 | struct video_channel *vc = arg; |
815 | 812 | ||
816 | if (check_v4l2(t) == EINVAL) | 813 | if (check_v4l2(t) == -EINVAL) |
817 | return 0; | 814 | return 0; |
818 | 815 | ||
819 | if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==EINVAL) | 816 | if (set_mode(client,t,V4L2_TUNER_ANALOG_TV, "VIDIOCSCHAN")==-EINVAL) |
820 | return 0; | 817 | return 0; |
821 | 818 | ||
822 | if (vc->norm < ARRAY_SIZE(map)) | 819 | if (vc->norm < ARRAY_SIZE(map)) |
@@ -830,9 +827,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
830 | { | 827 | { |
831 | unsigned long *v = arg; | 828 | unsigned long *v = arg; |
832 | 829 | ||
833 | if (check_mode(t, "VIDIOCSFREQ") == EINVAL) | 830 | if (check_mode(t, "VIDIOCSFREQ") == -EINVAL) |
834 | return 0; | 831 | return 0; |
835 | if (check_v4l2(t) == EINVAL) | 832 | if (check_v4l2(t) == -EINVAL) |
836 | return 0; | 833 | return 0; |
837 | 834 | ||
838 | set_freq(client, *v); | 835 | set_freq(client, *v); |
@@ -842,9 +839,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
842 | { | 839 | { |
843 | struct video_tuner *vt = arg; | 840 | struct video_tuner *vt = arg; |
844 | 841 | ||
845 | if (check_mode(t, "VIDIOCGTUNER") == EINVAL) | 842 | if (check_mode(t, "VIDIOCGTUNER") == -EINVAL) |
846 | return 0; | 843 | return 0; |
847 | if (check_v4l2(t) == EINVAL) | 844 | if (check_v4l2(t) == -EINVAL) |
848 | return 0; | 845 | return 0; |
849 | 846 | ||
850 | if (V4L2_TUNER_RADIO == t->mode) { | 847 | if (V4L2_TUNER_RADIO == t->mode) { |
@@ -886,9 +883,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
886 | { | 883 | { |
887 | struct video_audio *va = arg; | 884 | struct video_audio *va = arg; |
888 | 885 | ||
889 | if (check_mode(t, "VIDIOCGAUDIO") == EINVAL) | 886 | if (check_mode(t, "VIDIOCGAUDIO") == -EINVAL) |
890 | return 0; | 887 | return 0; |
891 | if (check_v4l2(t) == EINVAL) | 888 | if (check_v4l2(t) == -EINVAL) |
892 | return 0; | 889 | return 0; |
893 | 890 | ||
894 | if (V4L2_TUNER_RADIO == t->mode) { | 891 | if (V4L2_TUNER_RADIO == t->mode) { |
@@ -928,7 +925,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
928 | v4l2_std_id *id = arg; | 925 | v4l2_std_id *id = arg; |
929 | 926 | ||
930 | if (set_mode (client, t, V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD") | 927 | if (set_mode (client, t, V4L2_TUNER_ANALOG_TV, "VIDIOC_S_STD") |
931 | == EINVAL) | 928 | == -EINVAL) |
932 | return 0; | 929 | return 0; |
933 | 930 | ||
934 | switch_v4l2(); | 931 | switch_v4l2(); |
@@ -944,7 +941,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
944 | struct v4l2_frequency *f = arg; | 941 | struct v4l2_frequency *f = arg; |
945 | 942 | ||
946 | if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY") | 943 | if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY") |
947 | == EINVAL) | 944 | == -EINVAL) |
948 | return 0; | 945 | return 0; |
949 | switch_v4l2(); | 946 | switch_v4l2(); |
950 | set_freq(client,f->frequency); | 947 | set_freq(client,f->frequency); |
@@ -955,7 +952,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
955 | { | 952 | { |
956 | struct v4l2_frequency *f = arg; | 953 | struct v4l2_frequency *f = arg; |
957 | 954 | ||
958 | if (check_mode(t, "VIDIOC_G_FREQUENCY") == EINVAL) | 955 | if (check_mode(t, "VIDIOC_G_FREQUENCY") == -EINVAL) |
959 | return 0; | 956 | return 0; |
960 | switch_v4l2(); | 957 | switch_v4l2(); |
961 | f->type = t->mode; | 958 | f->type = t->mode; |
@@ -976,7 +973,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
976 | { | 973 | { |
977 | struct v4l2_tuner *tuner = arg; | 974 | struct v4l2_tuner *tuner = arg; |
978 | 975 | ||
979 | if (check_mode(t, "VIDIOC_G_TUNER") == EINVAL) | 976 | if (check_mode(t, "VIDIOC_G_TUNER") == -EINVAL) |
980 | return 0; | 977 | return 0; |
981 | switch_v4l2(); | 978 | switch_v4l2(); |
982 | 979 | ||
@@ -1023,7 +1020,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) | |||
1023 | { | 1020 | { |
1024 | struct v4l2_tuner *tuner = arg; | 1021 | struct v4l2_tuner *tuner = arg; |
1025 | 1022 | ||
1026 | if (check_mode(t, "VIDIOC_S_TUNER") == EINVAL) | 1023 | if (check_mode(t, "VIDIOC_S_TUNER") == -EINVAL) |
1027 | return 0; | 1024 | return 0; |
1028 | 1025 | ||
1029 | switch_v4l2(); | 1026 | switch_v4l2(); |
@@ -1117,7 +1114,7 @@ static int tuner_probe(struct i2c_client *client, | |||
1117 | if (NULL == t) | 1114 | if (NULL == t) |
1118 | return -ENOMEM; | 1115 | return -ENOMEM; |
1119 | t->i2c = client; | 1116 | t->i2c = client; |
1120 | strlcpy(client->name, "(tuner unset)", sizeof(client->name)); | 1117 | t->name = "(tuner unset)"; |
1121 | i2c_set_clientdata(client, t); | 1118 | i2c_set_clientdata(client, t); |
1122 | t->type = UNSET; | 1119 | t->type = UNSET; |
1123 | t->audmode = V4L2_TUNER_MODE_STEREO; | 1120 | t->audmode = V4L2_TUNER_MODE_STEREO; |
@@ -1167,7 +1164,7 @@ static int tuner_probe(struct i2c_client *client, | |||
1167 | /* If chip is not tda8290, don't register. | 1164 | /* If chip is not tda8290, don't register. |
1168 | since it can be tda9887*/ | 1165 | since it can be tda9887*/ |
1169 | if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter, | 1166 | if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter, |
1170 | t->i2c->addr) == 0) { | 1167 | t->i2c->addr) >= 0) { |
1171 | tuner_dbg("tda829x detected\n"); | 1168 | tuner_dbg("tda829x detected\n"); |
1172 | } else { | 1169 | } else { |
1173 | /* Default is being tda9887 */ | 1170 | /* Default is being tda9887 */ |
@@ -1181,7 +1178,7 @@ static int tuner_probe(struct i2c_client *client, | |||
1181 | case 0x60: | 1178 | case 0x60: |
1182 | if (tuner_symbol_probe(tea5767_autodetection, | 1179 | if (tuner_symbol_probe(tea5767_autodetection, |
1183 | t->i2c->adapter, t->i2c->addr) | 1180 | t->i2c->adapter, t->i2c->addr) |
1184 | != EINVAL) { | 1181 | >= 0) { |
1185 | t->type = TUNER_TEA5767; | 1182 | t->type = TUNER_TEA5767; |
1186 | t->mode_mask = T_RADIO; | 1183 | t->mode_mask = T_RADIO; |
1187 | t->mode = T_STANDBY; | 1184 | t->mode = T_STANDBY; |
@@ -1280,6 +1277,15 @@ static int tuner_remove(struct i2c_client *client) | |||
1280 | 1277 | ||
1281 | /* ----------------------------------------------------------------------- */ | 1278 | /* ----------------------------------------------------------------------- */ |
1282 | 1279 | ||
1280 | /* This driver supports many devices and the idea is to let the driver | ||
1281 | detect which device is present. So rather than listing all supported | ||
1282 | devices here, we pretend to support a single, fake device type. */ | ||
1283 | static const struct i2c_device_id tuner_id[] = { | ||
1284 | { "tuner", }, /* autodetect */ | ||
1285 | { } | ||
1286 | }; | ||
1287 | MODULE_DEVICE_TABLE(i2c, tuner_id); | ||
1288 | |||
1283 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 1289 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
1284 | .name = "tuner", | 1290 | .name = "tuner", |
1285 | .driverid = I2C_DRIVERID_TUNER, | 1291 | .driverid = I2C_DRIVERID_TUNER, |
@@ -1289,6 +1295,7 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { | |||
1289 | .suspend = tuner_suspend, | 1295 | .suspend = tuner_suspend, |
1290 | .resume = tuner_resume, | 1296 | .resume = tuner_resume, |
1291 | .legacy_probe = tuner_legacy_probe, | 1297 | .legacy_probe = tuner_legacy_probe, |
1298 | .id_table = tuner_id, | ||
1292 | }; | 1299 | }; |
1293 | 1300 | ||
1294 | 1301 | ||
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 3cf8a8e801e5..9da0e1807ffb 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c | |||
@@ -319,10 +319,12 @@ audioIC[] = | |||
319 | {AUDIO_CHIP_INTERNAL, "CX25843"}, | 319 | {AUDIO_CHIP_INTERNAL, "CX25843"}, |
320 | {AUDIO_CHIP_INTERNAL, "CX23418"}, | 320 | {AUDIO_CHIP_INTERNAL, "CX23418"}, |
321 | {AUDIO_CHIP_INTERNAL, "CX23885"}, | 321 | {AUDIO_CHIP_INTERNAL, "CX23885"}, |
322 | /* 40-42 */ | 322 | /* 40-44 */ |
323 | {AUDIO_CHIP_INTERNAL, "CX23888"}, | 323 | {AUDIO_CHIP_INTERNAL, "CX23888"}, |
324 | {AUDIO_CHIP_INTERNAL, "SAA7131"}, | 324 | {AUDIO_CHIP_INTERNAL, "SAA7131"}, |
325 | {AUDIO_CHIP_INTERNAL, "CX23887"}, | 325 | {AUDIO_CHIP_INTERNAL, "CX23887"}, |
326 | {AUDIO_CHIP_INTERNAL, "SAA7164"}, | ||
327 | {AUDIO_CHIP_INTERNAL, "AU8522"}, | ||
326 | }; | 328 | }; |
327 | 329 | ||
328 | /* This list is supplied by Hauppauge. Thanks! */ | 330 | /* This list is supplied by Hauppauge. Thanks! */ |
@@ -341,8 +343,10 @@ static const char *decoderIC[] = { | |||
341 | "CX882", "TVP5150A", "CX25840", "CX25841", "CX25842", | 343 | "CX882", "TVP5150A", "CX25840", "CX25841", "CX25842", |
342 | /* 30-34 */ | 344 | /* 30-34 */ |
343 | "CX25843", "CX23418", "NEC61153", "CX23885", "CX23888", | 345 | "CX25843", "CX23418", "NEC61153", "CX23885", "CX23888", |
344 | /* 35-37 */ | 346 | /* 35-39 */ |
345 | "SAA7131", "CX25837", "CX23887" | 347 | "SAA7131", "CX25837", "CX23887", "CX23885A", "CX23887A", |
348 | /* 40-42 */ | ||
349 | "SAA7164", "CX23885B", "AU8522" | ||
346 | }; | 350 | }; |
347 | 351 | ||
348 | static int hasRadioTuner(int tunerType) | 352 | static int hasRadioTuner(int tunerType) |
diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index 93bfd19dec7d..b4628874933b 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c | |||
@@ -228,6 +228,11 @@ static int upd64031a_remove(struct i2c_client *client) | |||
228 | 228 | ||
229 | /* ----------------------------------------------------------------------- */ | 229 | /* ----------------------------------------------------------------------- */ |
230 | 230 | ||
231 | static const struct i2c_device_id upd64031a_id[] = { | ||
232 | { "upd64031a", 0 }, | ||
233 | { } | ||
234 | }; | ||
235 | MODULE_DEVICE_TABLE(i2c, upd64031a_id); | ||
231 | 236 | ||
232 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 237 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
233 | .name = "upd64031a", | 238 | .name = "upd64031a", |
@@ -235,4 +240,5 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { | |||
235 | .command = upd64031a_command, | 240 | .command = upd64031a_command, |
236 | .probe = upd64031a_probe, | 241 | .probe = upd64031a_probe, |
237 | .remove = upd64031a_remove, | 242 | .remove = upd64031a_remove, |
243 | .id_table = upd64031a_id, | ||
238 | }; | 244 | }; |
diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index 9ab712a56ce0..9521ce004dcc 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c | |||
@@ -205,6 +205,11 @@ static int upd64083_remove(struct i2c_client *client) | |||
205 | 205 | ||
206 | /* ----------------------------------------------------------------------- */ | 206 | /* ----------------------------------------------------------------------- */ |
207 | 207 | ||
208 | static const struct i2c_device_id upd64083_id[] = { | ||
209 | { "upd64083", 0 }, | ||
210 | { } | ||
211 | }; | ||
212 | MODULE_DEVICE_TABLE(i2c, upd64083_id); | ||
208 | 213 | ||
209 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 214 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
210 | .name = "upd64083", | 215 | .name = "upd64083", |
@@ -212,4 +217,5 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { | |||
212 | .command = upd64083_command, | 217 | .command = upd64083_command, |
213 | .probe = upd64083_probe, | 218 | .probe = upd64083_probe, |
214 | .remove = upd64083_remove, | 219 | .remove = upd64083_remove, |
220 | .id_table = upd64083_id, | ||
215 | }; | 221 | }; |
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index 32e536edf09d..3d26a30abe1e 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c | |||
@@ -210,7 +210,7 @@ static int qcm_stv_setb(struct usb_device *dev, u16 reg, u8 val) | |||
210 | return ret; | 210 | return ret; |
211 | } | 211 | } |
212 | 212 | ||
213 | static int qcm_stv_setw(struct usb_device *dev, u16 reg, u16 val) | 213 | static int qcm_stv_setw(struct usb_device *dev, u16 reg, __le16 val) |
214 | { | 214 | { |
215 | int ret; | 215 | int ret; |
216 | 216 | ||
diff --git a/drivers/media/video/usbvision/Kconfig b/drivers/media/video/usbvision/Kconfig index 74e1d3075a20..fc24ef05b3f3 100644 --- a/drivers/media/video/usbvision/Kconfig +++ b/drivers/media/video/usbvision/Kconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | config VIDEO_USBVISION | 1 | config VIDEO_USBVISION |
2 | tristate "USB video devices based on Nogatech NT1003/1004/1005" | 2 | tristate "USB video devices based on Nogatech NT1003/1004/1005" |
3 | depends on I2C && VIDEO_V4L2 | 3 | depends on I2C && VIDEO_V4L2 |
4 | select MEDIA_TUNER | 4 | select VIDEO_TUNER |
5 | select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO | 5 | select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO |
6 | ---help--- | 6 | ---help--- |
7 | There are more than 50 different USB video devices based on | 7 | There are more than 50 different USB video devices based on |
diff --git a/drivers/media/video/uvc/Makefile b/drivers/media/video/uvc/Makefile new file mode 100644 index 000000000000..968c1994eda0 --- /dev/null +++ b/drivers/media/video/uvc/Makefile | |||
@@ -0,0 +1,3 @@ | |||
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 | ||
3 | obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o | ||
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c new file mode 100644 index 000000000000..f0ee46d15540 --- /dev/null +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
@@ -0,0 +1,1256 @@ | |||
1 | /* | ||
2 | * uvc_ctrl.c -- USB Video Class driver - Controls | ||
3 | * | ||
4 | * Copyright (C) 2005-2008 | ||
5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | ||
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/version.h> | ||
16 | #include <linux/list.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/uaccess.h> | ||
19 | #include <linux/usb.h> | ||
20 | #include <linux/videodev2.h> | ||
21 | #include <linux/vmalloc.h> | ||
22 | #include <linux/wait.h> | ||
23 | #include <asm/atomic.h> | ||
24 | |||
25 | #include "uvcvideo.h" | ||
26 | |||
27 | #define UVC_CTRL_NDATA 2 | ||
28 | #define UVC_CTRL_DATA_CURRENT 0 | ||
29 | #define UVC_CTRL_DATA_BACKUP 1 | ||
30 | |||
31 | /* ------------------------------------------------------------------------ | ||
32 | * Control, formats, ... | ||
33 | */ | ||
34 | |||
35 | static struct uvc_control_info uvc_ctrls[] = { | ||
36 | { | ||
37 | .entity = UVC_GUID_UVC_PROCESSING, | ||
38 | .selector = PU_BRIGHTNESS_CONTROL, | ||
39 | .index = 0, | ||
40 | .size = 2, | ||
41 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
42 | | UVC_CONTROL_RESTORE, | ||
43 | }, | ||
44 | { | ||
45 | .entity = UVC_GUID_UVC_PROCESSING, | ||
46 | .selector = PU_CONTRAST_CONTROL, | ||
47 | .index = 1, | ||
48 | .size = 2, | ||
49 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
50 | | UVC_CONTROL_RESTORE, | ||
51 | }, | ||
52 | { | ||
53 | .entity = UVC_GUID_UVC_PROCESSING, | ||
54 | .selector = PU_HUE_CONTROL, | ||
55 | .index = 2, | ||
56 | .size = 2, | ||
57 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
58 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
59 | }, | ||
60 | { | ||
61 | .entity = UVC_GUID_UVC_PROCESSING, | ||
62 | .selector = PU_SATURATION_CONTROL, | ||
63 | .index = 3, | ||
64 | .size = 2, | ||
65 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
66 | | UVC_CONTROL_RESTORE, | ||
67 | }, | ||
68 | { | ||
69 | .entity = UVC_GUID_UVC_PROCESSING, | ||
70 | .selector = PU_SHARPNESS_CONTROL, | ||
71 | .index = 4, | ||
72 | .size = 2, | ||
73 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
74 | | UVC_CONTROL_RESTORE, | ||
75 | }, | ||
76 | { | ||
77 | .entity = UVC_GUID_UVC_PROCESSING, | ||
78 | .selector = PU_GAMMA_CONTROL, | ||
79 | .index = 5, | ||
80 | .size = 2, | ||
81 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
82 | | UVC_CONTROL_RESTORE, | ||
83 | }, | ||
84 | { | ||
85 | .entity = UVC_GUID_UVC_PROCESSING, | ||
86 | .selector = PU_BACKLIGHT_COMPENSATION_CONTROL, | ||
87 | .index = 8, | ||
88 | .size = 2, | ||
89 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
90 | | UVC_CONTROL_RESTORE, | ||
91 | }, | ||
92 | { | ||
93 | .entity = UVC_GUID_UVC_PROCESSING, | ||
94 | .selector = PU_GAIN_CONTROL, | ||
95 | .index = 9, | ||
96 | .size = 2, | ||
97 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
98 | | UVC_CONTROL_RESTORE, | ||
99 | }, | ||
100 | { | ||
101 | .entity = UVC_GUID_UVC_PROCESSING, | ||
102 | .selector = PU_POWER_LINE_FREQUENCY_CONTROL, | ||
103 | .index = 10, | ||
104 | .size = 1, | ||
105 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
106 | | UVC_CONTROL_RESTORE, | ||
107 | }, | ||
108 | { | ||
109 | .entity = UVC_GUID_UVC_PROCESSING, | ||
110 | .selector = PU_HUE_AUTO_CONTROL, | ||
111 | .index = 11, | ||
112 | .size = 1, | ||
113 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
114 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | ||
115 | }, | ||
116 | { | ||
117 | .entity = UVC_GUID_UVC_CAMERA, | ||
118 | .selector = CT_AE_MODE_CONTROL, | ||
119 | .index = 1, | ||
120 | .size = 1, | ||
121 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
122 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_GET_RES | ||
123 | | UVC_CONTROL_RESTORE, | ||
124 | }, | ||
125 | { | ||
126 | .entity = UVC_GUID_UVC_CAMERA, | ||
127 | .selector = CT_AE_PRIORITY_CONTROL, | ||
128 | .index = 2, | ||
129 | .size = 1, | ||
130 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
131 | | UVC_CONTROL_RESTORE, | ||
132 | }, | ||
133 | { | ||
134 | .entity = UVC_GUID_UVC_CAMERA, | ||
135 | .selector = CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, | ||
136 | .index = 3, | ||
137 | .size = 4, | ||
138 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
139 | | UVC_CONTROL_RESTORE, | ||
140 | }, | ||
141 | { | ||
142 | .entity = UVC_GUID_UVC_CAMERA, | ||
143 | .selector = CT_FOCUS_ABSOLUTE_CONTROL, | ||
144 | .index = 5, | ||
145 | .size = 2, | ||
146 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
147 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
148 | }, | ||
149 | { | ||
150 | .entity = UVC_GUID_UVC_CAMERA, | ||
151 | .selector = CT_FOCUS_AUTO_CONTROL, | ||
152 | .index = 17, | ||
153 | .size = 1, | ||
154 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
155 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | ||
156 | }, | ||
157 | { | ||
158 | .entity = UVC_GUID_UVC_PROCESSING, | ||
159 | .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, | ||
160 | .index = 12, | ||
161 | .size = 1, | ||
162 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
163 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | ||
164 | }, | ||
165 | { | ||
166 | .entity = UVC_GUID_UVC_PROCESSING, | ||
167 | .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, | ||
168 | .index = 6, | ||
169 | .size = 2, | ||
170 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
171 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
172 | }, | ||
173 | { | ||
174 | .entity = UVC_GUID_UVC_PROCESSING, | ||
175 | .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, | ||
176 | .index = 13, | ||
177 | .size = 1, | ||
178 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
179 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | ||
180 | }, | ||
181 | { | ||
182 | .entity = UVC_GUID_UVC_PROCESSING, | ||
183 | .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, | ||
184 | .index = 7, | ||
185 | .size = 4, | ||
186 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
187 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
188 | }, | ||
189 | }; | ||
190 | |||
191 | static struct uvc_menu_info power_line_frequency_controls[] = { | ||
192 | { 0, "Disabled" }, | ||
193 | { 1, "50 Hz" }, | ||
194 | { 2, "60 Hz" }, | ||
195 | }; | ||
196 | |||
197 | static struct uvc_menu_info exposure_auto_controls[] = { | ||
198 | { 1, "Manual Mode" }, | ||
199 | { 2, "Auto Mode" }, | ||
200 | { 4, "Shutter Priority Mode" }, | ||
201 | { 8, "Aperture Priority Mode" }, | ||
202 | }; | ||
203 | |||
204 | static struct uvc_control_mapping uvc_ctrl_mappings[] = { | ||
205 | { | ||
206 | .id = V4L2_CID_BRIGHTNESS, | ||
207 | .name = "Brightness", | ||
208 | .entity = UVC_GUID_UVC_PROCESSING, | ||
209 | .selector = PU_BRIGHTNESS_CONTROL, | ||
210 | .size = 16, | ||
211 | .offset = 0, | ||
212 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
213 | .data_type = UVC_CTRL_DATA_TYPE_SIGNED, | ||
214 | }, | ||
215 | { | ||
216 | .id = V4L2_CID_CONTRAST, | ||
217 | .name = "Contrast", | ||
218 | .entity = UVC_GUID_UVC_PROCESSING, | ||
219 | .selector = PU_CONTRAST_CONTROL, | ||
220 | .size = 16, | ||
221 | .offset = 0, | ||
222 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
223 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
224 | }, | ||
225 | { | ||
226 | .id = V4L2_CID_HUE, | ||
227 | .name = "Hue", | ||
228 | .entity = UVC_GUID_UVC_PROCESSING, | ||
229 | .selector = PU_HUE_CONTROL, | ||
230 | .size = 16, | ||
231 | .offset = 0, | ||
232 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
233 | .data_type = UVC_CTRL_DATA_TYPE_SIGNED, | ||
234 | }, | ||
235 | { | ||
236 | .id = V4L2_CID_SATURATION, | ||
237 | .name = "Saturation", | ||
238 | .entity = UVC_GUID_UVC_PROCESSING, | ||
239 | .selector = PU_SATURATION_CONTROL, | ||
240 | .size = 16, | ||
241 | .offset = 0, | ||
242 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
243 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
244 | }, | ||
245 | { | ||
246 | .id = V4L2_CID_SHARPNESS, | ||
247 | .name = "Sharpness", | ||
248 | .entity = UVC_GUID_UVC_PROCESSING, | ||
249 | .selector = PU_SHARPNESS_CONTROL, | ||
250 | .size = 16, | ||
251 | .offset = 0, | ||
252 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
253 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
254 | }, | ||
255 | { | ||
256 | .id = V4L2_CID_GAMMA, | ||
257 | .name = "Gamma", | ||
258 | .entity = UVC_GUID_UVC_PROCESSING, | ||
259 | .selector = PU_GAMMA_CONTROL, | ||
260 | .size = 16, | ||
261 | .offset = 0, | ||
262 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
263 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
264 | }, | ||
265 | { | ||
266 | .id = V4L2_CID_BACKLIGHT_COMPENSATION, | ||
267 | .name = "Backlight Compensation", | ||
268 | .entity = UVC_GUID_UVC_PROCESSING, | ||
269 | .selector = PU_BACKLIGHT_COMPENSATION_CONTROL, | ||
270 | .size = 16, | ||
271 | .offset = 0, | ||
272 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
273 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
274 | }, | ||
275 | { | ||
276 | .id = V4L2_CID_GAIN, | ||
277 | .name = "Gain", | ||
278 | .entity = UVC_GUID_UVC_PROCESSING, | ||
279 | .selector = PU_GAIN_CONTROL, | ||
280 | .size = 16, | ||
281 | .offset = 0, | ||
282 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
283 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
284 | }, | ||
285 | { | ||
286 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
287 | .name = "Power Line Frequency", | ||
288 | .entity = UVC_GUID_UVC_PROCESSING, | ||
289 | .selector = PU_POWER_LINE_FREQUENCY_CONTROL, | ||
290 | .size = 2, | ||
291 | .offset = 0, | ||
292 | .v4l2_type = V4L2_CTRL_TYPE_MENU, | ||
293 | .data_type = UVC_CTRL_DATA_TYPE_ENUM, | ||
294 | .menu_info = power_line_frequency_controls, | ||
295 | .menu_count = ARRAY_SIZE(power_line_frequency_controls), | ||
296 | }, | ||
297 | { | ||
298 | .id = V4L2_CID_HUE_AUTO, | ||
299 | .name = "Hue, Auto", | ||
300 | .entity = UVC_GUID_UVC_PROCESSING, | ||
301 | .selector = PU_HUE_AUTO_CONTROL, | ||
302 | .size = 1, | ||
303 | .offset = 0, | ||
304 | .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, | ||
305 | .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, | ||
306 | }, | ||
307 | { | ||
308 | .id = V4L2_CID_EXPOSURE_AUTO, | ||
309 | .name = "Exposure, Auto", | ||
310 | .entity = UVC_GUID_UVC_CAMERA, | ||
311 | .selector = CT_AE_MODE_CONTROL, | ||
312 | .size = 4, | ||
313 | .offset = 0, | ||
314 | .v4l2_type = V4L2_CTRL_TYPE_MENU, | ||
315 | .data_type = UVC_CTRL_DATA_TYPE_BITMASK, | ||
316 | .menu_info = exposure_auto_controls, | ||
317 | .menu_count = ARRAY_SIZE(exposure_auto_controls), | ||
318 | }, | ||
319 | { | ||
320 | .id = V4L2_CID_EXPOSURE_AUTO_PRIORITY, | ||
321 | .name = "Exposure, Auto Priority", | ||
322 | .entity = UVC_GUID_UVC_CAMERA, | ||
323 | .selector = CT_AE_PRIORITY_CONTROL, | ||
324 | .size = 1, | ||
325 | .offset = 0, | ||
326 | .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, | ||
327 | .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, | ||
328 | }, | ||
329 | { | ||
330 | .id = V4L2_CID_EXPOSURE_ABSOLUTE, | ||
331 | .name = "Exposure (Absolute)", | ||
332 | .entity = UVC_GUID_UVC_CAMERA, | ||
333 | .selector = CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, | ||
334 | .size = 32, | ||
335 | .offset = 0, | ||
336 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
337 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
338 | }, | ||
339 | { | ||
340 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | ||
341 | .name = "White Balance Temperature, Auto", | ||
342 | .entity = UVC_GUID_UVC_PROCESSING, | ||
343 | .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, | ||
344 | .size = 1, | ||
345 | .offset = 0, | ||
346 | .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, | ||
347 | .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, | ||
348 | }, | ||
349 | { | ||
350 | .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, | ||
351 | .name = "White Balance Temperature", | ||
352 | .entity = UVC_GUID_UVC_PROCESSING, | ||
353 | .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, | ||
354 | .size = 16, | ||
355 | .offset = 0, | ||
356 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
357 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
358 | }, | ||
359 | { | ||
360 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | ||
361 | .name = "White Balance Component, Auto", | ||
362 | .entity = UVC_GUID_UVC_PROCESSING, | ||
363 | .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, | ||
364 | .size = 1, | ||
365 | .offset = 0, | ||
366 | .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, | ||
367 | .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, | ||
368 | }, | ||
369 | { | ||
370 | .id = V4L2_CID_BLUE_BALANCE, | ||
371 | .name = "White Balance Blue Component", | ||
372 | .entity = UVC_GUID_UVC_PROCESSING, | ||
373 | .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, | ||
374 | .size = 16, | ||
375 | .offset = 0, | ||
376 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
377 | .data_type = UVC_CTRL_DATA_TYPE_SIGNED, | ||
378 | }, | ||
379 | { | ||
380 | .id = V4L2_CID_RED_BALANCE, | ||
381 | .name = "White Balance Red Component", | ||
382 | .entity = UVC_GUID_UVC_PROCESSING, | ||
383 | .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, | ||
384 | .size = 16, | ||
385 | .offset = 16, | ||
386 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
387 | .data_type = UVC_CTRL_DATA_TYPE_SIGNED, | ||
388 | }, | ||
389 | { | ||
390 | .id = V4L2_CID_FOCUS_ABSOLUTE, | ||
391 | .name = "Focus (absolute)", | ||
392 | .entity = UVC_GUID_UVC_CAMERA, | ||
393 | .selector = CT_FOCUS_ABSOLUTE_CONTROL, | ||
394 | .size = 16, | ||
395 | .offset = 0, | ||
396 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
397 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
398 | }, | ||
399 | { | ||
400 | .id = V4L2_CID_FOCUS_AUTO, | ||
401 | .name = "Focus, Auto", | ||
402 | .entity = UVC_GUID_UVC_CAMERA, | ||
403 | .selector = CT_FOCUS_AUTO_CONTROL, | ||
404 | .size = 1, | ||
405 | .offset = 0, | ||
406 | .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, | ||
407 | .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, | ||
408 | }, | ||
409 | }; | ||
410 | |||
411 | /* ------------------------------------------------------------------------ | ||
412 | * Utility functions | ||
413 | */ | ||
414 | |||
415 | static inline __u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id) | ||
416 | { | ||
417 | return ctrl->data + id * ctrl->info->size; | ||
418 | } | ||
419 | |||
420 | static inline int uvc_get_bit(const __u8 *data, int bit) | ||
421 | { | ||
422 | return (data[bit >> 3] >> (bit & 7)) & 1; | ||
423 | } | ||
424 | |||
425 | /* Extract the bit string specified by mapping->offset and mapping->size | ||
426 | * from the little-endian data stored at 'data' and return the result as | ||
427 | * a signed 32bit integer. Sign extension will be performed if the mapping | ||
428 | * references a signed data type. | ||
429 | */ | ||
430 | static __s32 uvc_get_le_value(const __u8 *data, | ||
431 | struct uvc_control_mapping *mapping) | ||
432 | { | ||
433 | int bits = mapping->size; | ||
434 | int offset = mapping->offset; | ||
435 | __s32 value = 0; | ||
436 | __u8 mask; | ||
437 | |||
438 | data += offset / 8; | ||
439 | offset &= 7; | ||
440 | mask = ((1LL << bits) - 1) << offset; | ||
441 | |||
442 | for (; bits > 0; data++) { | ||
443 | __u8 byte = *data & mask; | ||
444 | value |= offset > 0 ? (byte >> offset) : (byte << (-offset)); | ||
445 | bits -= 8 - (offset > 0 ? offset : 0); | ||
446 | offset -= 8; | ||
447 | mask = (1 << bits) - 1; | ||
448 | } | ||
449 | |||
450 | /* Sign-extend the value if needed */ | ||
451 | if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) | ||
452 | value |= -(value & (1 << (mapping->size - 1))); | ||
453 | |||
454 | return value; | ||
455 | } | ||
456 | |||
457 | /* Set the bit string specified by mapping->offset and mapping->size | ||
458 | * in the little-endian data stored at 'data' to the value 'value'. | ||
459 | */ | ||
460 | static void uvc_set_le_value(__s32 value, __u8 *data, | ||
461 | struct uvc_control_mapping *mapping) | ||
462 | { | ||
463 | int bits = mapping->size; | ||
464 | int offset = mapping->offset; | ||
465 | __u8 mask; | ||
466 | |||
467 | data += offset / 8; | ||
468 | offset &= 7; | ||
469 | |||
470 | for (; bits > 0; data++) { | ||
471 | mask = ((1LL << bits) - 1) << offset; | ||
472 | *data = (*data & ~mask) | ((value << offset) & mask); | ||
473 | value >>= offset ? offset : 8; | ||
474 | bits -= 8 - offset; | ||
475 | offset = 0; | ||
476 | } | ||
477 | } | ||
478 | |||
479 | /* ------------------------------------------------------------------------ | ||
480 | * Terminal and unit management | ||
481 | */ | ||
482 | |||
483 | static const __u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING; | ||
484 | static const __u8 uvc_camera_guid[16] = UVC_GUID_UVC_CAMERA; | ||
485 | static const __u8 uvc_media_transport_input_guid[16] = | ||
486 | UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT; | ||
487 | |||
488 | static int uvc_entity_match_guid(struct uvc_entity *entity, __u8 guid[16]) | ||
489 | { | ||
490 | switch (UVC_ENTITY_TYPE(entity)) { | ||
491 | case ITT_CAMERA: | ||
492 | return memcmp(uvc_camera_guid, guid, 16) == 0; | ||
493 | |||
494 | case ITT_MEDIA_TRANSPORT_INPUT: | ||
495 | return memcmp(uvc_media_transport_input_guid, guid, 16) == 0; | ||
496 | |||
497 | case VC_PROCESSING_UNIT: | ||
498 | return memcmp(uvc_processing_guid, guid, 16) == 0; | ||
499 | |||
500 | case VC_EXTENSION_UNIT: | ||
501 | return memcmp(entity->extension.guidExtensionCode, | ||
502 | guid, 16) == 0; | ||
503 | |||
504 | default: | ||
505 | return 0; | ||
506 | } | ||
507 | } | ||
508 | |||
509 | /* ------------------------------------------------------------------------ | ||
510 | * UVC Controls | ||
511 | */ | ||
512 | |||
513 | static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id, | ||
514 | struct uvc_control_mapping **mapping, struct uvc_control **control, | ||
515 | int next) | ||
516 | { | ||
517 | struct uvc_control *ctrl; | ||
518 | struct uvc_control_mapping *map; | ||
519 | unsigned int i; | ||
520 | |||
521 | if (entity == NULL) | ||
522 | return; | ||
523 | |||
524 | for (i = 0; i < entity->ncontrols; ++i) { | ||
525 | ctrl = &entity->controls[i]; | ||
526 | if (ctrl->info == NULL) | ||
527 | continue; | ||
528 | |||
529 | list_for_each_entry(map, &ctrl->info->mappings, list) { | ||
530 | if ((map->id == v4l2_id) && !next) { | ||
531 | *control = ctrl; | ||
532 | *mapping = map; | ||
533 | return; | ||
534 | } | ||
535 | |||
536 | if ((*mapping == NULL || (*mapping)->id > map->id) && | ||
537 | (map->id > v4l2_id) && next) { | ||
538 | *control = ctrl; | ||
539 | *mapping = map; | ||
540 | } | ||
541 | } | ||
542 | } | ||
543 | } | ||
544 | |||
545 | struct uvc_control *uvc_find_control(struct uvc_video_device *video, | ||
546 | __u32 v4l2_id, struct uvc_control_mapping **mapping) | ||
547 | { | ||
548 | struct uvc_control *ctrl = NULL; | ||
549 | struct uvc_entity *entity; | ||
550 | int next = v4l2_id & V4L2_CTRL_FLAG_NEXT_CTRL; | ||
551 | |||
552 | *mapping = NULL; | ||
553 | |||
554 | /* Mask the query flags. */ | ||
555 | v4l2_id &= V4L2_CTRL_ID_MASK; | ||
556 | |||
557 | /* Find the control. */ | ||
558 | __uvc_find_control(video->processing, v4l2_id, mapping, &ctrl, next); | ||
559 | if (ctrl && !next) | ||
560 | return ctrl; | ||
561 | |||
562 | list_for_each_entry(entity, &video->iterms, chain) { | ||
563 | __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); | ||
564 | if (ctrl && !next) | ||
565 | return ctrl; | ||
566 | } | ||
567 | |||
568 | list_for_each_entry(entity, &video->extensions, chain) { | ||
569 | __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); | ||
570 | if (ctrl && !next) | ||
571 | return ctrl; | ||
572 | } | ||
573 | |||
574 | if (ctrl == NULL && !next) | ||
575 | uvc_trace(UVC_TRACE_CONTROL, "Control 0x%08x not found.\n", | ||
576 | v4l2_id); | ||
577 | |||
578 | return ctrl; | ||
579 | } | ||
580 | |||
581 | int uvc_query_v4l2_ctrl(struct uvc_video_device *video, | ||
582 | struct v4l2_queryctrl *v4l2_ctrl) | ||
583 | { | ||
584 | struct uvc_control *ctrl; | ||
585 | struct uvc_control_mapping *mapping; | ||
586 | struct uvc_menu_info *menu; | ||
587 | unsigned int i; | ||
588 | __u8 data[8]; | ||
589 | int ret; | ||
590 | |||
591 | ctrl = uvc_find_control(video, v4l2_ctrl->id, &mapping); | ||
592 | if (ctrl == NULL) | ||
593 | return -EINVAL; | ||
594 | |||
595 | v4l2_ctrl->id = mapping->id; | ||
596 | v4l2_ctrl->type = mapping->v4l2_type; | ||
597 | strncpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name); | ||
598 | v4l2_ctrl->flags = 0; | ||
599 | |||
600 | if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR)) | ||
601 | v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; | ||
602 | |||
603 | if (ctrl->info->flags & UVC_CONTROL_GET_DEF) { | ||
604 | if ((ret = uvc_query_ctrl(video->dev, GET_DEF, ctrl->entity->id, | ||
605 | video->dev->intfnum, ctrl->info->selector, | ||
606 | &data, ctrl->info->size)) < 0) | ||
607 | return ret; | ||
608 | v4l2_ctrl->default_value = uvc_get_le_value(data, mapping); | ||
609 | } | ||
610 | |||
611 | if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { | ||
612 | v4l2_ctrl->minimum = 0; | ||
613 | v4l2_ctrl->maximum = mapping->menu_count - 1; | ||
614 | v4l2_ctrl->step = 1; | ||
615 | |||
616 | menu = mapping->menu_info; | ||
617 | for (i = 0; i < mapping->menu_count; ++i, ++menu) { | ||
618 | if (menu->value == v4l2_ctrl->default_value) { | ||
619 | v4l2_ctrl->default_value = i; | ||
620 | break; | ||
621 | } | ||
622 | } | ||
623 | |||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | if (ctrl->info->flags & UVC_CONTROL_GET_MIN) { | ||
628 | if ((ret = uvc_query_ctrl(video->dev, GET_MIN, ctrl->entity->id, | ||
629 | video->dev->intfnum, ctrl->info->selector, | ||
630 | &data, ctrl->info->size)) < 0) | ||
631 | return ret; | ||
632 | v4l2_ctrl->minimum = uvc_get_le_value(data, mapping); | ||
633 | } | ||
634 | if (ctrl->info->flags & UVC_CONTROL_GET_MAX) { | ||
635 | if ((ret = uvc_query_ctrl(video->dev, GET_MAX, ctrl->entity->id, | ||
636 | video->dev->intfnum, ctrl->info->selector, | ||
637 | &data, ctrl->info->size)) < 0) | ||
638 | return ret; | ||
639 | v4l2_ctrl->maximum = uvc_get_le_value(data, mapping); | ||
640 | } | ||
641 | if (ctrl->info->flags & UVC_CONTROL_GET_RES) { | ||
642 | if ((ret = uvc_query_ctrl(video->dev, GET_RES, ctrl->entity->id, | ||
643 | video->dev->intfnum, ctrl->info->selector, | ||
644 | &data, ctrl->info->size)) < 0) | ||
645 | return ret; | ||
646 | v4l2_ctrl->step = uvc_get_le_value(data, mapping); | ||
647 | } | ||
648 | |||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | |||
653 | /* -------------------------------------------------------------------------- | ||
654 | * Control transactions | ||
655 | * | ||
656 | * To make extended set operations as atomic as the hardware allows, controls | ||
657 | * are handled using begin/commit/rollback operations. | ||
658 | * | ||
659 | * At the beginning of a set request, uvc_ctrl_begin should be called to | ||
660 | * initialize the request. This function acquires the control lock. | ||
661 | * | ||
662 | * When setting a control, the new value is stored in the control data field | ||
663 | * at position UVC_CTRL_DATA_CURRENT. The control is then marked as dirty for | ||
664 | * later processing. If the UVC and V4L2 control sizes differ, the current | ||
665 | * value is loaded from the hardware before storing the new value in the data | ||
666 | * field. | ||
667 | * | ||
668 | * After processing all controls in the transaction, uvc_ctrl_commit or | ||
669 | * uvc_ctrl_rollback must be called to apply the pending changes to the | ||
670 | * hardware or revert them. When applying changes, all controls marked as | ||
671 | * dirty will be modified in the UVC device, and the dirty flag will be | ||
672 | * cleared. When reverting controls, the control data field | ||
673 | * UVC_CTRL_DATA_CURRENT is reverted to its previous value | ||
674 | * (UVC_CTRL_DATA_BACKUP) for all dirty controls. Both functions release the | ||
675 | * control lock. | ||
676 | */ | ||
677 | int uvc_ctrl_begin(struct uvc_video_device *video) | ||
678 | { | ||
679 | return mutex_lock_interruptible(&video->ctrl_mutex) ? -ERESTARTSYS : 0; | ||
680 | } | ||
681 | |||
682 | static int uvc_ctrl_commit_entity(struct uvc_device *dev, | ||
683 | struct uvc_entity *entity, int rollback) | ||
684 | { | ||
685 | struct uvc_control *ctrl; | ||
686 | unsigned int i; | ||
687 | int ret; | ||
688 | |||
689 | if (entity == NULL) | ||
690 | return 0; | ||
691 | |||
692 | for (i = 0; i < entity->ncontrols; ++i) { | ||
693 | ctrl = &entity->controls[i]; | ||
694 | if (ctrl->info == NULL || !ctrl->dirty) | ||
695 | continue; | ||
696 | |||
697 | if (!rollback) | ||
698 | ret = uvc_query_ctrl(dev, SET_CUR, ctrl->entity->id, | ||
699 | dev->intfnum, ctrl->info->selector, | ||
700 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
701 | ctrl->info->size); | ||
702 | else | ||
703 | ret = 0; | ||
704 | |||
705 | if (rollback || ret < 0) | ||
706 | memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
707 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), | ||
708 | ctrl->info->size); | ||
709 | |||
710 | if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) | ||
711 | ctrl->loaded = 0; | ||
712 | |||
713 | ctrl->dirty = 0; | ||
714 | |||
715 | if (ret < 0) | ||
716 | return ret; | ||
717 | } | ||
718 | |||
719 | return 0; | ||
720 | } | ||
721 | |||
722 | int __uvc_ctrl_commit(struct uvc_video_device *video, int rollback) | ||
723 | { | ||
724 | struct uvc_entity *entity; | ||
725 | int ret = 0; | ||
726 | |||
727 | /* Find the control. */ | ||
728 | ret = uvc_ctrl_commit_entity(video->dev, video->processing, rollback); | ||
729 | if (ret < 0) | ||
730 | goto done; | ||
731 | |||
732 | list_for_each_entry(entity, &video->iterms, chain) { | ||
733 | ret = uvc_ctrl_commit_entity(video->dev, entity, rollback); | ||
734 | if (ret < 0) | ||
735 | goto done; | ||
736 | } | ||
737 | |||
738 | list_for_each_entry(entity, &video->extensions, chain) { | ||
739 | ret = uvc_ctrl_commit_entity(video->dev, entity, rollback); | ||
740 | if (ret < 0) | ||
741 | goto done; | ||
742 | } | ||
743 | |||
744 | done: | ||
745 | mutex_unlock(&video->ctrl_mutex); | ||
746 | return ret; | ||
747 | } | ||
748 | |||
749 | int uvc_ctrl_get(struct uvc_video_device *video, | ||
750 | struct v4l2_ext_control *xctrl) | ||
751 | { | ||
752 | struct uvc_control *ctrl; | ||
753 | struct uvc_control_mapping *mapping; | ||
754 | struct uvc_menu_info *menu; | ||
755 | unsigned int i; | ||
756 | int ret; | ||
757 | |||
758 | ctrl = uvc_find_control(video, xctrl->id, &mapping); | ||
759 | if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) | ||
760 | return -EINVAL; | ||
761 | |||
762 | if (!ctrl->loaded) { | ||
763 | ret = uvc_query_ctrl(video->dev, GET_CUR, ctrl->entity->id, | ||
764 | video->dev->intfnum, ctrl->info->selector, | ||
765 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
766 | ctrl->info->size); | ||
767 | if (ret < 0) | ||
768 | return ret; | ||
769 | |||
770 | if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0) | ||
771 | ctrl->loaded = 1; | ||
772 | } | ||
773 | |||
774 | xctrl->value = uvc_get_le_value( | ||
775 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping); | ||
776 | |||
777 | if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { | ||
778 | menu = mapping->menu_info; | ||
779 | for (i = 0; i < mapping->menu_count; ++i, ++menu) { | ||
780 | if (menu->value == xctrl->value) { | ||
781 | xctrl->value = i; | ||
782 | break; | ||
783 | } | ||
784 | } | ||
785 | } | ||
786 | |||
787 | return 0; | ||
788 | } | ||
789 | |||
790 | int uvc_ctrl_set(struct uvc_video_device *video, | ||
791 | struct v4l2_ext_control *xctrl) | ||
792 | { | ||
793 | struct uvc_control *ctrl; | ||
794 | struct uvc_control_mapping *mapping; | ||
795 | s32 value = xctrl->value; | ||
796 | int ret; | ||
797 | |||
798 | ctrl = uvc_find_control(video, xctrl->id, &mapping); | ||
799 | if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_SET_CUR) == 0) | ||
800 | return -EINVAL; | ||
801 | |||
802 | if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { | ||
803 | if (value < 0 || value >= mapping->menu_count) | ||
804 | return -EINVAL; | ||
805 | value = mapping->menu_info[value].value; | ||
806 | } | ||
807 | |||
808 | if (!ctrl->loaded && (ctrl->info->size * 8) != mapping->size) { | ||
809 | if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) { | ||
810 | memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
811 | 0, ctrl->info->size); | ||
812 | } else { | ||
813 | ret = uvc_query_ctrl(video->dev, GET_CUR, | ||
814 | ctrl->entity->id, video->dev->intfnum, | ||
815 | ctrl->info->selector, | ||
816 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
817 | ctrl->info->size); | ||
818 | if (ret < 0) | ||
819 | return ret; | ||
820 | } | ||
821 | |||
822 | if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0) | ||
823 | ctrl->loaded = 1; | ||
824 | } | ||
825 | |||
826 | if (!ctrl->dirty) { | ||
827 | memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), | ||
828 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
829 | ctrl->info->size); | ||
830 | } | ||
831 | |||
832 | uvc_set_le_value(value, | ||
833 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping); | ||
834 | |||
835 | ctrl->dirty = 1; | ||
836 | ctrl->modified = 1; | ||
837 | return 0; | ||
838 | } | ||
839 | |||
840 | /* -------------------------------------------------------------------------- | ||
841 | * Dynamic controls | ||
842 | */ | ||
843 | |||
844 | int uvc_xu_ctrl_query(struct uvc_video_device *video, | ||
845 | struct uvc_xu_control *xctrl, int set) | ||
846 | { | ||
847 | struct uvc_entity *entity; | ||
848 | struct uvc_control *ctrl = NULL; | ||
849 | unsigned int i, found = 0; | ||
850 | __u8 *data; | ||
851 | int ret; | ||
852 | |||
853 | /* Find the extension unit. */ | ||
854 | list_for_each_entry(entity, &video->extensions, chain) { | ||
855 | if (entity->id == xctrl->unit) | ||
856 | break; | ||
857 | } | ||
858 | |||
859 | if (entity->id != xctrl->unit) { | ||
860 | uvc_trace(UVC_TRACE_CONTROL, "Extension unit %u not found.\n", | ||
861 | xctrl->unit); | ||
862 | return -EINVAL; | ||
863 | } | ||
864 | |||
865 | /* Find the control. */ | ||
866 | for (i = 0; i < entity->ncontrols; ++i) { | ||
867 | ctrl = &entity->controls[i]; | ||
868 | if (ctrl->info == NULL) | ||
869 | continue; | ||
870 | |||
871 | if (ctrl->info->selector == xctrl->selector) { | ||
872 | found = 1; | ||
873 | break; | ||
874 | } | ||
875 | } | ||
876 | |||
877 | if (!found) { | ||
878 | uvc_trace(UVC_TRACE_CONTROL, | ||
879 | "Control " UVC_GUID_FORMAT "/%u not found.\n", | ||
880 | UVC_GUID_ARGS(entity->extension.guidExtensionCode), | ||
881 | xctrl->selector); | ||
882 | return -EINVAL; | ||
883 | } | ||
884 | |||
885 | /* Validate control data size. */ | ||
886 | if (ctrl->info->size != xctrl->size) | ||
887 | return -EINVAL; | ||
888 | |||
889 | if ((set && !(ctrl->info->flags & UVC_CONTROL_SET_CUR)) || | ||
890 | (!set && !(ctrl->info->flags & UVC_CONTROL_GET_CUR))) | ||
891 | return -EINVAL; | ||
892 | |||
893 | if (mutex_lock_interruptible(&video->ctrl_mutex)) | ||
894 | return -ERESTARTSYS; | ||
895 | |||
896 | memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), | ||
897 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
898 | xctrl->size); | ||
899 | data = uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT); | ||
900 | |||
901 | if (set && copy_from_user(data, xctrl->data, xctrl->size)) { | ||
902 | ret = -EFAULT; | ||
903 | goto out; | ||
904 | } | ||
905 | |||
906 | ret = uvc_query_ctrl(video->dev, set ? SET_CUR : GET_CUR, xctrl->unit, | ||
907 | video->dev->intfnum, xctrl->selector, data, | ||
908 | xctrl->size); | ||
909 | if (ret < 0) | ||
910 | goto out; | ||
911 | |||
912 | if (!set && copy_to_user(xctrl->data, data, xctrl->size)) { | ||
913 | ret = -EFAULT; | ||
914 | goto out; | ||
915 | } | ||
916 | |||
917 | out: | ||
918 | if (ret) | ||
919 | memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
920 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), | ||
921 | xctrl->size); | ||
922 | |||
923 | mutex_unlock(&video->ctrl_mutex); | ||
924 | return ret; | ||
925 | } | ||
926 | |||
927 | /* -------------------------------------------------------------------------- | ||
928 | * Suspend/resume | ||
929 | */ | ||
930 | |||
931 | /* | ||
932 | * Restore control values after resume, skipping controls that haven't been | ||
933 | * changed. | ||
934 | * | ||
935 | * TODO | ||
936 | * - Don't restore modified controls that are back to their default value. | ||
937 | * - Handle restore order (Auto-Exposure Mode should be restored before | ||
938 | * Exposure Time). | ||
939 | */ | ||
940 | int uvc_ctrl_resume_device(struct uvc_device *dev) | ||
941 | { | ||
942 | struct uvc_control *ctrl; | ||
943 | struct uvc_entity *entity; | ||
944 | unsigned int i; | ||
945 | int ret; | ||
946 | |||
947 | /* Walk the entities list and restore controls when possible. */ | ||
948 | list_for_each_entry(entity, &dev->entities, list) { | ||
949 | |||
950 | for (i = 0; i < entity->ncontrols; ++i) { | ||
951 | ctrl = &entity->controls[i]; | ||
952 | |||
953 | if (ctrl->info == NULL || !ctrl->modified || | ||
954 | (ctrl->info->flags & UVC_CONTROL_RESTORE) == 0) | ||
955 | continue; | ||
956 | |||
957 | printk(KERN_INFO "restoring control " UVC_GUID_FORMAT | ||
958 | "/%u/%u\n", UVC_GUID_ARGS(ctrl->info->entity), | ||
959 | ctrl->info->index, ctrl->info->selector); | ||
960 | ctrl->dirty = 1; | ||
961 | } | ||
962 | |||
963 | ret = uvc_ctrl_commit_entity(dev, entity, 0); | ||
964 | if (ret < 0) | ||
965 | return ret; | ||
966 | } | ||
967 | |||
968 | return 0; | ||
969 | } | ||
970 | |||
971 | /* -------------------------------------------------------------------------- | ||
972 | * Control and mapping handling | ||
973 | */ | ||
974 | |||
975 | static void uvc_ctrl_add_ctrl(struct uvc_device *dev, | ||
976 | struct uvc_control_info *info) | ||
977 | { | ||
978 | struct uvc_entity *entity; | ||
979 | struct uvc_control *ctrl = NULL; | ||
980 | int ret, found = 0; | ||
981 | unsigned int i; | ||
982 | |||
983 | list_for_each_entry(entity, &dev->entities, list) { | ||
984 | if (!uvc_entity_match_guid(entity, info->entity)) | ||
985 | continue; | ||
986 | |||
987 | for (i = 0; i < entity->ncontrols; ++i) { | ||
988 | ctrl = &entity->controls[i]; | ||
989 | if (ctrl->index == info->index) { | ||
990 | found = 1; | ||
991 | break; | ||
992 | } | ||
993 | } | ||
994 | |||
995 | if (found) | ||
996 | break; | ||
997 | } | ||
998 | |||
999 | if (!found) | ||
1000 | return; | ||
1001 | |||
1002 | if (UVC_ENTITY_TYPE(entity) == VC_EXTENSION_UNIT) { | ||
1003 | /* Check if the device control information and length match | ||
1004 | * the user supplied information. | ||
1005 | */ | ||
1006 | __u32 flags; | ||
1007 | __le16 size; | ||
1008 | __u8 inf; | ||
1009 | |||
1010 | if ((ret = uvc_query_ctrl(dev, GET_LEN, ctrl->entity->id, | ||
1011 | dev->intfnum, info->selector, (__u8 *)&size, 2)) < 0) { | ||
1012 | uvc_trace(UVC_TRACE_CONTROL, "GET_LEN failed on " | ||
1013 | "control " UVC_GUID_FORMAT "/%u (%d).\n", | ||
1014 | UVC_GUID_ARGS(info->entity), info->selector, | ||
1015 | ret); | ||
1016 | return; | ||
1017 | } | ||
1018 | |||
1019 | if (info->size != le16_to_cpu(size)) { | ||
1020 | uvc_trace(UVC_TRACE_CONTROL, "Control " UVC_GUID_FORMAT | ||
1021 | "/%u size doesn't match user supplied " | ||
1022 | "value.\n", UVC_GUID_ARGS(info->entity), | ||
1023 | info->selector); | ||
1024 | return; | ||
1025 | } | ||
1026 | |||
1027 | if ((ret = uvc_query_ctrl(dev, GET_INFO, ctrl->entity->id, | ||
1028 | dev->intfnum, info->selector, &inf, 1)) < 0) { | ||
1029 | uvc_trace(UVC_TRACE_CONTROL, "GET_INFO failed on " | ||
1030 | "control " UVC_GUID_FORMAT "/%u (%d).\n", | ||
1031 | UVC_GUID_ARGS(info->entity), info->selector, | ||
1032 | ret); | ||
1033 | return; | ||
1034 | } | ||
1035 | |||
1036 | flags = info->flags; | ||
1037 | if (((flags & UVC_CONTROL_GET_CUR) && !(inf & (1 << 0))) || | ||
1038 | ((flags & UVC_CONTROL_SET_CUR) && !(inf & (1 << 1)))) { | ||
1039 | uvc_trace(UVC_TRACE_CONTROL, "Control " | ||
1040 | UVC_GUID_FORMAT "/%u flags don't match " | ||
1041 | "supported operations.\n", | ||
1042 | UVC_GUID_ARGS(info->entity), info->selector); | ||
1043 | return; | ||
1044 | } | ||
1045 | } | ||
1046 | |||
1047 | ctrl->info = info; | ||
1048 | ctrl->data = kmalloc(ctrl->info->size * UVC_CTRL_NDATA, GFP_KERNEL); | ||
1049 | uvc_trace(UVC_TRACE_CONTROL, "Added control " UVC_GUID_FORMAT "/%u " | ||
1050 | "to device %s entity %u\n", UVC_GUID_ARGS(ctrl->info->entity), | ||
1051 | ctrl->info->selector, dev->udev->devpath, entity->id); | ||
1052 | } | ||
1053 | |||
1054 | /* | ||
1055 | * Add an item to the UVC control information list, and instantiate a control | ||
1056 | * structure for each device that supports the control. | ||
1057 | */ | ||
1058 | int uvc_ctrl_add_info(struct uvc_control_info *info) | ||
1059 | { | ||
1060 | struct uvc_control_info *ctrl; | ||
1061 | struct uvc_device *dev; | ||
1062 | int ret = 0; | ||
1063 | |||
1064 | /* Find matching controls by walking the devices, entities and | ||
1065 | * controls list. | ||
1066 | */ | ||
1067 | mutex_lock(&uvc_driver.ctrl_mutex); | ||
1068 | |||
1069 | /* First check if the list contains a control matching the new one. | ||
1070 | * Bail out if it does. | ||
1071 | */ | ||
1072 | list_for_each_entry(ctrl, &uvc_driver.controls, list) { | ||
1073 | if (memcmp(ctrl->entity, info->entity, 16)) | ||
1074 | continue; | ||
1075 | |||
1076 | if (ctrl->selector == info->selector) { | ||
1077 | uvc_trace(UVC_TRACE_CONTROL, "Control " | ||
1078 | UVC_GUID_FORMAT "/%u is already defined.\n", | ||
1079 | UVC_GUID_ARGS(info->entity), info->selector); | ||
1080 | ret = -EEXIST; | ||
1081 | goto end; | ||
1082 | } | ||
1083 | if (ctrl->index == info->index) { | ||
1084 | uvc_trace(UVC_TRACE_CONTROL, "Control " | ||
1085 | UVC_GUID_FORMAT "/%u would overwrite index " | ||
1086 | "%d.\n", UVC_GUID_ARGS(info->entity), | ||
1087 | info->selector, info->index); | ||
1088 | ret = -EEXIST; | ||
1089 | goto end; | ||
1090 | } | ||
1091 | } | ||
1092 | |||
1093 | list_for_each_entry(dev, &uvc_driver.devices, list) | ||
1094 | uvc_ctrl_add_ctrl(dev, info); | ||
1095 | |||
1096 | INIT_LIST_HEAD(&info->mappings); | ||
1097 | list_add_tail(&info->list, &uvc_driver.controls); | ||
1098 | end: | ||
1099 | mutex_unlock(&uvc_driver.ctrl_mutex); | ||
1100 | return ret; | ||
1101 | } | ||
1102 | |||
1103 | int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping) | ||
1104 | { | ||
1105 | struct uvc_control_info *info; | ||
1106 | struct uvc_control_mapping *map; | ||
1107 | int ret = -EINVAL; | ||
1108 | |||
1109 | if (mapping->id & ~V4L2_CTRL_ID_MASK) { | ||
1110 | uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s' with " | ||
1111 | "invalid control id 0x%08x\n", mapping->name, | ||
1112 | mapping->id); | ||
1113 | return -EINVAL; | ||
1114 | } | ||
1115 | |||
1116 | mutex_lock(&uvc_driver.ctrl_mutex); | ||
1117 | list_for_each_entry(info, &uvc_driver.controls, list) { | ||
1118 | if (memcmp(info->entity, mapping->entity, 16) || | ||
1119 | info->selector != mapping->selector) | ||
1120 | continue; | ||
1121 | |||
1122 | if (info->size * 8 < mapping->size + mapping->offset) { | ||
1123 | uvc_trace(UVC_TRACE_CONTROL, "Mapping '%s' would " | ||
1124 | "overflow control " UVC_GUID_FORMAT "/%u\n", | ||
1125 | mapping->name, UVC_GUID_ARGS(info->entity), | ||
1126 | info->selector); | ||
1127 | ret = -EOVERFLOW; | ||
1128 | goto end; | ||
1129 | } | ||
1130 | |||
1131 | /* Check if the list contains a mapping matching the new one. | ||
1132 | * Bail out if it does. | ||
1133 | */ | ||
1134 | list_for_each_entry(map, &info->mappings, list) { | ||
1135 | if (map->id == mapping->id) { | ||
1136 | uvc_trace(UVC_TRACE_CONTROL, "Mapping '%s' is " | ||
1137 | "already defined.\n", mapping->name); | ||
1138 | ret = -EEXIST; | ||
1139 | goto end; | ||
1140 | } | ||
1141 | } | ||
1142 | |||
1143 | mapping->ctrl = info; | ||
1144 | list_add_tail(&mapping->list, &info->mappings); | ||
1145 | uvc_trace(UVC_TRACE_CONTROL, "Adding mapping %s to control " | ||
1146 | UVC_GUID_FORMAT "/%u.\n", mapping->name, | ||
1147 | UVC_GUID_ARGS(info->entity), info->selector); | ||
1148 | |||
1149 | ret = 0; | ||
1150 | break; | ||
1151 | } | ||
1152 | end: | ||
1153 | mutex_unlock(&uvc_driver.ctrl_mutex); | ||
1154 | return ret; | ||
1155 | } | ||
1156 | |||
1157 | /* | ||
1158 | * Initialize device controls. | ||
1159 | */ | ||
1160 | int uvc_ctrl_init_device(struct uvc_device *dev) | ||
1161 | { | ||
1162 | struct uvc_control_info *info; | ||
1163 | struct uvc_control *ctrl; | ||
1164 | struct uvc_entity *entity; | ||
1165 | unsigned int i; | ||
1166 | |||
1167 | /* Walk the entities list and instantiate controls */ | ||
1168 | list_for_each_entry(entity, &dev->entities, list) { | ||
1169 | unsigned int bControlSize = 0, ncontrols = 0; | ||
1170 | __u8 *bmControls = NULL; | ||
1171 | |||
1172 | if (UVC_ENTITY_TYPE(entity) == VC_EXTENSION_UNIT) { | ||
1173 | bmControls = entity->extension.bmControls; | ||
1174 | bControlSize = entity->extension.bControlSize; | ||
1175 | } else if (UVC_ENTITY_TYPE(entity) == VC_PROCESSING_UNIT) { | ||
1176 | bmControls = entity->processing.bmControls; | ||
1177 | bControlSize = entity->processing.bControlSize; | ||
1178 | } else if (UVC_ENTITY_TYPE(entity) == ITT_CAMERA) { | ||
1179 | bmControls = entity->camera.bmControls; | ||
1180 | bControlSize = entity->camera.bControlSize; | ||
1181 | } | ||
1182 | |||
1183 | for (i = 0; i < bControlSize; ++i) | ||
1184 | ncontrols += hweight8(bmControls[i]); | ||
1185 | |||
1186 | if (ncontrols == 0) | ||
1187 | continue; | ||
1188 | |||
1189 | entity->controls = kzalloc(ncontrols*sizeof *ctrl, GFP_KERNEL); | ||
1190 | if (entity->controls == NULL) | ||
1191 | return -ENOMEM; | ||
1192 | |||
1193 | entity->ncontrols = ncontrols; | ||
1194 | |||
1195 | ctrl = entity->controls; | ||
1196 | for (i = 0; i < bControlSize * 8; ++i) { | ||
1197 | if (uvc_get_bit(bmControls, i) == 0) | ||
1198 | continue; | ||
1199 | |||
1200 | ctrl->entity = entity; | ||
1201 | ctrl->index = i; | ||
1202 | ctrl++; | ||
1203 | } | ||
1204 | } | ||
1205 | |||
1206 | /* Walk the controls info list and associate them with the device | ||
1207 | * controls, then add the device to the global device list. This has | ||
1208 | * to be done while holding the controls lock, to make sure | ||
1209 | * uvc_ctrl_add_info() will not get called in-between. | ||
1210 | */ | ||
1211 | mutex_lock(&uvc_driver.ctrl_mutex); | ||
1212 | list_for_each_entry(info, &uvc_driver.controls, list) | ||
1213 | uvc_ctrl_add_ctrl(dev, info); | ||
1214 | |||
1215 | list_add_tail(&dev->list, &uvc_driver.devices); | ||
1216 | mutex_unlock(&uvc_driver.ctrl_mutex); | ||
1217 | |||
1218 | return 0; | ||
1219 | } | ||
1220 | |||
1221 | /* | ||
1222 | * Cleanup device controls. | ||
1223 | */ | ||
1224 | void uvc_ctrl_cleanup_device(struct uvc_device *dev) | ||
1225 | { | ||
1226 | struct uvc_entity *entity; | ||
1227 | unsigned int i; | ||
1228 | |||
1229 | /* Remove the device from the global devices list */ | ||
1230 | mutex_lock(&uvc_driver.ctrl_mutex); | ||
1231 | if (dev->list.next != NULL) | ||
1232 | list_del(&dev->list); | ||
1233 | mutex_unlock(&uvc_driver.ctrl_mutex); | ||
1234 | |||
1235 | list_for_each_entry(entity, &dev->entities, list) { | ||
1236 | for (i = 0; i < entity->ncontrols; ++i) | ||
1237 | kfree(entity->controls[i].data); | ||
1238 | |||
1239 | kfree(entity->controls); | ||
1240 | } | ||
1241 | } | ||
1242 | |||
1243 | void uvc_ctrl_init(void) | ||
1244 | { | ||
1245 | struct uvc_control_info *ctrl = uvc_ctrls; | ||
1246 | struct uvc_control_info *cend = ctrl + ARRAY_SIZE(uvc_ctrls); | ||
1247 | struct uvc_control_mapping *mapping = uvc_ctrl_mappings; | ||
1248 | struct uvc_control_mapping *mend = | ||
1249 | mapping + ARRAY_SIZE(uvc_ctrl_mappings); | ||
1250 | |||
1251 | for (; ctrl < cend; ++ctrl) | ||
1252 | uvc_ctrl_add_info(ctrl); | ||
1253 | |||
1254 | for (; mapping < mend; ++mapping) | ||
1255 | uvc_ctrl_add_mapping(mapping); | ||
1256 | } | ||
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c new file mode 100644 index 000000000000..60ced589f898 --- /dev/null +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -0,0 +1,1955 @@ | |||
1 | /* | ||
2 | * uvc_driver.c -- USB Video Class driver | ||
3 | * | ||
4 | * Copyright (C) 2005-2008 | ||
5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | ||
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 | /* | ||
15 | * This driver aims to support video input devices compliant with the 'USB | ||
16 | * Video Class' specification. | ||
17 | * | ||
18 | * The driver doesn't support the deprecated v4l1 interface. It implements the | ||
19 | * mmap capture method only, and doesn't do any image format conversion in | ||
20 | * software. If your user-space application doesn't support YUYV or MJPEG, fix | ||
21 | * it :-). Please note that the MJPEG data have been stripped from their | ||
22 | * Huffman tables (DHT marker), you will need to add it back if your JPEG | ||
23 | * codec can't handle MJPEG data. | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/version.h> | ||
28 | #include <linux/list.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/usb.h> | ||
31 | #include <linux/videodev2.h> | ||
32 | #include <linux/vmalloc.h> | ||
33 | #include <linux/wait.h> | ||
34 | #include <asm/atomic.h> | ||
35 | |||
36 | #include <media/v4l2-common.h> | ||
37 | |||
38 | #include "uvcvideo.h" | ||
39 | |||
40 | #define DRIVER_AUTHOR "Laurent Pinchart <laurent.pinchart@skynet.be>" | ||
41 | #define DRIVER_DESC "USB Video Class driver" | ||
42 | #ifndef DRIVER_VERSION | ||
43 | #define DRIVER_VERSION "v0.1.0" | ||
44 | #endif | ||
45 | |||
46 | static unsigned int uvc_quirks_param; | ||
47 | unsigned int uvc_trace_param; | ||
48 | |||
49 | /* ------------------------------------------------------------------------ | ||
50 | * Control, formats, ... | ||
51 | */ | ||
52 | |||
53 | static struct uvc_format_desc uvc_fmts[] = { | ||
54 | { | ||
55 | .name = "YUV 4:2:2 (YUYV)", | ||
56 | .guid = UVC_GUID_FORMAT_YUY2, | ||
57 | .fcc = V4L2_PIX_FMT_YUYV, | ||
58 | }, | ||
59 | { | ||
60 | .name = "YUV 4:2:0 (NV12)", | ||
61 | .guid = UVC_GUID_FORMAT_NV12, | ||
62 | .fcc = V4L2_PIX_FMT_NV12, | ||
63 | }, | ||
64 | { | ||
65 | .name = "MJPEG", | ||
66 | .guid = UVC_GUID_FORMAT_MJPEG, | ||
67 | .fcc = V4L2_PIX_FMT_MJPEG, | ||
68 | }, | ||
69 | { | ||
70 | .name = "YVU 4:2:0 (YV12)", | ||
71 | .guid = UVC_GUID_FORMAT_YV12, | ||
72 | .fcc = V4L2_PIX_FMT_YVU420, | ||
73 | }, | ||
74 | { | ||
75 | .name = "YUV 4:2:0 (I420)", | ||
76 | .guid = UVC_GUID_FORMAT_I420, | ||
77 | .fcc = V4L2_PIX_FMT_YUV420, | ||
78 | }, | ||
79 | { | ||
80 | .name = "YUV 4:2:2 (UYVY)", | ||
81 | .guid = UVC_GUID_FORMAT_UYVY, | ||
82 | .fcc = V4L2_PIX_FMT_UYVY, | ||
83 | }, | ||
84 | { | ||
85 | .name = "Greyscale", | ||
86 | .guid = UVC_GUID_FORMAT_Y800, | ||
87 | .fcc = V4L2_PIX_FMT_GREY, | ||
88 | }, | ||
89 | { | ||
90 | .name = "RGB Bayer", | ||
91 | .guid = UVC_GUID_FORMAT_BY8, | ||
92 | .fcc = V4L2_PIX_FMT_SBGGR8, | ||
93 | }, | ||
94 | }; | ||
95 | |||
96 | /* ------------------------------------------------------------------------ | ||
97 | * Utility functions | ||
98 | */ | ||
99 | |||
100 | struct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts, | ||
101 | __u8 epaddr) | ||
102 | { | ||
103 | struct usb_host_endpoint *ep; | ||
104 | unsigned int i; | ||
105 | |||
106 | for (i = 0; i < alts->desc.bNumEndpoints; ++i) { | ||
107 | ep = &alts->endpoint[i]; | ||
108 | if (ep->desc.bEndpointAddress == epaddr) | ||
109 | return ep; | ||
110 | } | ||
111 | |||
112 | return NULL; | ||
113 | } | ||
114 | |||
115 | static struct uvc_format_desc *uvc_format_by_guid(const __u8 guid[16]) | ||
116 | { | ||
117 | unsigned int len = ARRAY_SIZE(uvc_fmts); | ||
118 | unsigned int i; | ||
119 | |||
120 | for (i = 0; i < len; ++i) { | ||
121 | if (memcmp(guid, uvc_fmts[i].guid, 16) == 0) | ||
122 | return &uvc_fmts[i]; | ||
123 | } | ||
124 | |||
125 | return NULL; | ||
126 | } | ||
127 | |||
128 | static __u32 uvc_colorspace(const __u8 primaries) | ||
129 | { | ||
130 | static const __u8 colorprimaries[] = { | ||
131 | 0, | ||
132 | V4L2_COLORSPACE_SRGB, | ||
133 | V4L2_COLORSPACE_470_SYSTEM_M, | ||
134 | V4L2_COLORSPACE_470_SYSTEM_BG, | ||
135 | V4L2_COLORSPACE_SMPTE170M, | ||
136 | V4L2_COLORSPACE_SMPTE240M, | ||
137 | }; | ||
138 | |||
139 | if (primaries < ARRAY_SIZE(colorprimaries)) | ||
140 | return colorprimaries[primaries]; | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | /* Simplify a fraction using a simple continued fraction decomposition. The | ||
146 | * idea here is to convert fractions such as 333333/10000000 to 1/30 using | ||
147 | * 32 bit arithmetic only. The algorithm is not perfect and relies upon two | ||
148 | * arbitrary parameters to remove non-significative terms from the simple | ||
149 | * continued fraction decomposition. Using 8 and 333 for n_terms and threshold | ||
150 | * respectively seems to give nice results. | ||
151 | */ | ||
152 | void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator, | ||
153 | unsigned int n_terms, unsigned int threshold) | ||
154 | { | ||
155 | uint32_t *an; | ||
156 | uint32_t x, y, r; | ||
157 | unsigned int i, n; | ||
158 | |||
159 | an = kmalloc(n_terms * sizeof *an, GFP_KERNEL); | ||
160 | if (an == NULL) | ||
161 | return; | ||
162 | |||
163 | /* Convert the fraction to a simple continued fraction. See | ||
164 | * http://mathforum.org/dr.math/faq/faq.fractions.html | ||
165 | * Stop if the current term is bigger than or equal to the given | ||
166 | * threshold. | ||
167 | */ | ||
168 | x = *numerator; | ||
169 | y = *denominator; | ||
170 | |||
171 | for (n = 0; n < n_terms && y != 0; ++n) { | ||
172 | an[n] = x / y; | ||
173 | if (an[n] >= threshold) { | ||
174 | if (n < 2) | ||
175 | n++; | ||
176 | break; | ||
177 | } | ||
178 | |||
179 | r = x - an[n] * y; | ||
180 | x = y; | ||
181 | y = r; | ||
182 | } | ||
183 | |||
184 | /* Expand the simple continued fraction back to an integer fraction. */ | ||
185 | x = 0; | ||
186 | y = 1; | ||
187 | |||
188 | for (i = n; i > 0; --i) { | ||
189 | r = y; | ||
190 | y = an[i-1] * y + x; | ||
191 | x = r; | ||
192 | } | ||
193 | |||
194 | *numerator = y; | ||
195 | *denominator = x; | ||
196 | kfree(an); | ||
197 | } | ||
198 | |||
199 | /* Convert a fraction to a frame interval in 100ns multiples. The idea here is | ||
200 | * to compute numerator / denominator * 10000000 using 32 bit fixed point | ||
201 | * arithmetic only. | ||
202 | */ | ||
203 | uint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator) | ||
204 | { | ||
205 | uint32_t multiplier; | ||
206 | |||
207 | /* Saturate the result if the operation would overflow. */ | ||
208 | if (denominator == 0 || | ||
209 | numerator/denominator >= ((uint32_t)-1)/10000000) | ||
210 | return (uint32_t)-1; | ||
211 | |||
212 | /* Divide both the denominator and the multiplier by two until | ||
213 | * numerator * multiplier doesn't overflow. If anyone knows a better | ||
214 | * algorithm please let me know. | ||
215 | */ | ||
216 | multiplier = 10000000; | ||
217 | while (numerator > ((uint32_t)-1)/multiplier) { | ||
218 | multiplier /= 2; | ||
219 | denominator /= 2; | ||
220 | } | ||
221 | |||
222 | return denominator ? numerator * multiplier / denominator : 0; | ||
223 | } | ||
224 | |||
225 | /* ------------------------------------------------------------------------ | ||
226 | * Terminal and unit management | ||
227 | */ | ||
228 | |||
229 | static struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id) | ||
230 | { | ||
231 | struct uvc_entity *entity; | ||
232 | |||
233 | list_for_each_entry(entity, &dev->entities, list) { | ||
234 | if (entity->id == id) | ||
235 | return entity; | ||
236 | } | ||
237 | |||
238 | return NULL; | ||
239 | } | ||
240 | |||
241 | static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev, | ||
242 | int id, struct uvc_entity *entity) | ||
243 | { | ||
244 | unsigned int i; | ||
245 | |||
246 | if (entity == NULL) | ||
247 | entity = list_entry(&dev->entities, struct uvc_entity, list); | ||
248 | |||
249 | list_for_each_entry_continue(entity, &dev->entities, list) { | ||
250 | switch (UVC_ENTITY_TYPE(entity)) { | ||
251 | case TT_STREAMING: | ||
252 | if (entity->output.bSourceID == id) | ||
253 | return entity; | ||
254 | break; | ||
255 | |||
256 | case VC_PROCESSING_UNIT: | ||
257 | if (entity->processing.bSourceID == id) | ||
258 | return entity; | ||
259 | break; | ||
260 | |||
261 | case VC_SELECTOR_UNIT: | ||
262 | for (i = 0; i < entity->selector.bNrInPins; ++i) | ||
263 | if (entity->selector.baSourceID[i] == id) | ||
264 | return entity; | ||
265 | break; | ||
266 | |||
267 | case VC_EXTENSION_UNIT: | ||
268 | for (i = 0; i < entity->extension.bNrInPins; ++i) | ||
269 | if (entity->extension.baSourceID[i] == id) | ||
270 | return entity; | ||
271 | break; | ||
272 | } | ||
273 | } | ||
274 | |||
275 | return NULL; | ||
276 | } | ||
277 | |||
278 | /* ------------------------------------------------------------------------ | ||
279 | * Descriptors handling | ||
280 | */ | ||
281 | |||
282 | static int uvc_parse_format(struct uvc_device *dev, | ||
283 | struct uvc_streaming *streaming, struct uvc_format *format, | ||
284 | __u32 **intervals, unsigned char *buffer, int buflen) | ||
285 | { | ||
286 | struct usb_interface *intf = streaming->intf; | ||
287 | struct usb_host_interface *alts = intf->cur_altsetting; | ||
288 | struct uvc_format_desc *fmtdesc; | ||
289 | struct uvc_frame *frame; | ||
290 | const unsigned char *start = buffer; | ||
291 | unsigned int interval; | ||
292 | unsigned int i, n; | ||
293 | __u8 ftype; | ||
294 | |||
295 | format->type = buffer[2]; | ||
296 | format->index = buffer[3]; | ||
297 | |||
298 | switch (buffer[2]) { | ||
299 | case VS_FORMAT_UNCOMPRESSED: | ||
300 | case VS_FORMAT_FRAME_BASED: | ||
301 | if (buflen < 27) { | ||
302 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
303 | "interface %d FORMAT error\n", | ||
304 | dev->udev->devnum, | ||
305 | alts->desc.bInterfaceNumber); | ||
306 | return -EINVAL; | ||
307 | } | ||
308 | |||
309 | /* Find the format descriptor from its GUID. */ | ||
310 | fmtdesc = uvc_format_by_guid(&buffer[5]); | ||
311 | |||
312 | if (fmtdesc != NULL) { | ||
313 | strncpy(format->name, fmtdesc->name, | ||
314 | sizeof format->name); | ||
315 | format->fcc = fmtdesc->fcc; | ||
316 | } else { | ||
317 | uvc_printk(KERN_INFO, "Unknown video format " | ||
318 | UVC_GUID_FORMAT "\n", | ||
319 | UVC_GUID_ARGS(&buffer[5])); | ||
320 | snprintf(format->name, sizeof format->name, | ||
321 | UVC_GUID_FORMAT, UVC_GUID_ARGS(&buffer[5])); | ||
322 | format->fcc = 0; | ||
323 | } | ||
324 | |||
325 | format->bpp = buffer[21]; | ||
326 | if (buffer[2] == VS_FORMAT_UNCOMPRESSED) { | ||
327 | ftype = VS_FRAME_UNCOMPRESSED; | ||
328 | } else { | ||
329 | ftype = VS_FRAME_FRAME_BASED; | ||
330 | if (buffer[27]) | ||
331 | format->flags = UVC_FMT_FLAG_COMPRESSED; | ||
332 | } | ||
333 | break; | ||
334 | |||
335 | case VS_FORMAT_MJPEG: | ||
336 | if (buflen < 11) { | ||
337 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
338 | "interface %d FORMAT error\n", | ||
339 | dev->udev->devnum, | ||
340 | alts->desc.bInterfaceNumber); | ||
341 | return -EINVAL; | ||
342 | } | ||
343 | |||
344 | strncpy(format->name, "MJPEG", sizeof format->name); | ||
345 | format->fcc = V4L2_PIX_FMT_MJPEG; | ||
346 | format->flags = UVC_FMT_FLAG_COMPRESSED; | ||
347 | format->bpp = 0; | ||
348 | ftype = VS_FRAME_MJPEG; | ||
349 | break; | ||
350 | |||
351 | case VS_FORMAT_DV: | ||
352 | if (buflen < 9) { | ||
353 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
354 | "interface %d FORMAT error\n", | ||
355 | dev->udev->devnum, | ||
356 | alts->desc.bInterfaceNumber); | ||
357 | return -EINVAL; | ||
358 | } | ||
359 | |||
360 | switch (buffer[8] & 0x7f) { | ||
361 | case 0: | ||
362 | strncpy(format->name, "SD-DV", sizeof format->name); | ||
363 | break; | ||
364 | case 1: | ||
365 | strncpy(format->name, "SDL-DV", sizeof format->name); | ||
366 | break; | ||
367 | case 2: | ||
368 | strncpy(format->name, "HD-DV", sizeof format->name); | ||
369 | break; | ||
370 | default: | ||
371 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
372 | "interface %d: unknown DV format %u\n", | ||
373 | dev->udev->devnum, | ||
374 | alts->desc.bInterfaceNumber, buffer[8]); | ||
375 | return -EINVAL; | ||
376 | } | ||
377 | |||
378 | strncat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz", | ||
379 | sizeof format->name); | ||
380 | |||
381 | format->fcc = V4L2_PIX_FMT_DV; | ||
382 | format->flags = UVC_FMT_FLAG_COMPRESSED | UVC_FMT_FLAG_STREAM; | ||
383 | format->bpp = 0; | ||
384 | ftype = 0; | ||
385 | |||
386 | /* Create a dummy frame descriptor. */ | ||
387 | frame = &format->frame[0]; | ||
388 | memset(&format->frame[0], 0, sizeof format->frame[0]); | ||
389 | frame->bFrameIntervalType = 1; | ||
390 | frame->dwDefaultFrameInterval = 1; | ||
391 | frame->dwFrameInterval = *intervals; | ||
392 | *(*intervals)++ = 1; | ||
393 | format->nframes = 1; | ||
394 | break; | ||
395 | |||
396 | case VS_FORMAT_MPEG2TS: | ||
397 | case VS_FORMAT_STREAM_BASED: | ||
398 | /* Not supported yet. */ | ||
399 | default: | ||
400 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
401 | "interface %d unsupported format %u\n", | ||
402 | dev->udev->devnum, alts->desc.bInterfaceNumber, | ||
403 | buffer[2]); | ||
404 | return -EINVAL; | ||
405 | } | ||
406 | |||
407 | uvc_trace(UVC_TRACE_DESCR, "Found format %s.\n", format->name); | ||
408 | |||
409 | buflen -= buffer[0]; | ||
410 | buffer += buffer[0]; | ||
411 | |||
412 | /* Parse the frame descriptors. Only uncompressed, MJPEG and frame | ||
413 | * based formats have frame descriptors. | ||
414 | */ | ||
415 | while (buflen > 2 && buffer[2] == ftype) { | ||
416 | frame = &format->frame[format->nframes]; | ||
417 | |||
418 | if (ftype != VS_FRAME_FRAME_BASED) | ||
419 | n = buflen > 25 ? buffer[25] : 0; | ||
420 | else | ||
421 | n = buflen > 21 ? buffer[21] : 0; | ||
422 | |||
423 | n = n ? n : 3; | ||
424 | |||
425 | if (buflen < 26 + 4*n) { | ||
426 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
427 | "interface %d FRAME error\n", dev->udev->devnum, | ||
428 | alts->desc.bInterfaceNumber); | ||
429 | return -EINVAL; | ||
430 | } | ||
431 | |||
432 | frame->bFrameIndex = buffer[3]; | ||
433 | frame->bmCapabilities = buffer[4]; | ||
434 | frame->wWidth = le16_to_cpup((__le16 *)&buffer[5]); | ||
435 | frame->wHeight = le16_to_cpup((__le16 *)&buffer[7]); | ||
436 | frame->dwMinBitRate = le32_to_cpup((__le32 *)&buffer[9]); | ||
437 | frame->dwMaxBitRate = le32_to_cpup((__le32 *)&buffer[13]); | ||
438 | if (ftype != VS_FRAME_FRAME_BASED) { | ||
439 | frame->dwMaxVideoFrameBufferSize = | ||
440 | le32_to_cpup((__le32 *)&buffer[17]); | ||
441 | frame->dwDefaultFrameInterval = | ||
442 | le32_to_cpup((__le32 *)&buffer[21]); | ||
443 | frame->bFrameIntervalType = buffer[25]; | ||
444 | } else { | ||
445 | frame->dwMaxVideoFrameBufferSize = 0; | ||
446 | frame->dwDefaultFrameInterval = | ||
447 | le32_to_cpup((__le32 *)&buffer[17]); | ||
448 | frame->bFrameIntervalType = buffer[21]; | ||
449 | } | ||
450 | frame->dwFrameInterval = *intervals; | ||
451 | |||
452 | /* Several UVC chipsets screw up dwMaxVideoFrameBufferSize | ||
453 | * completely. Observed behaviours range from setting the | ||
454 | * value to 1.1x the actual frame size of hardwiring the | ||
455 | * 16 low bits to 0. This results in a higher than necessary | ||
456 | * memory usage as well as a wrong image size information. For | ||
457 | * uncompressed formats this can be fixed by computing the | ||
458 | * value from the frame size. | ||
459 | */ | ||
460 | if (!(format->flags & UVC_FMT_FLAG_COMPRESSED)) | ||
461 | frame->dwMaxVideoFrameBufferSize = format->bpp | ||
462 | * frame->wWidth * frame->wHeight / 8; | ||
463 | |||
464 | /* Some bogus devices report dwMinFrameInterval equal to | ||
465 | * dwMaxFrameInterval and have dwFrameIntervalStep set to | ||
466 | * zero. Setting all null intervals to 1 fixes the problem and | ||
467 | * some other divisions by zero which could happen. | ||
468 | */ | ||
469 | for (i = 0; i < n; ++i) { | ||
470 | interval = le32_to_cpup((__le32 *)&buffer[26+4*i]); | ||
471 | *(*intervals)++ = interval ? interval : 1; | ||
472 | } | ||
473 | |||
474 | /* Make sure that the default frame interval stays between | ||
475 | * the boundaries. | ||
476 | */ | ||
477 | n -= frame->bFrameIntervalType ? 1 : 2; | ||
478 | frame->dwDefaultFrameInterval = | ||
479 | min(frame->dwFrameInterval[n], | ||
480 | max(frame->dwFrameInterval[0], | ||
481 | frame->dwDefaultFrameInterval)); | ||
482 | |||
483 | uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n", | ||
484 | frame->wWidth, frame->wHeight, | ||
485 | 10000000/frame->dwDefaultFrameInterval, | ||
486 | (100000000/frame->dwDefaultFrameInterval)%10); | ||
487 | |||
488 | format->nframes++; | ||
489 | buflen -= buffer[0]; | ||
490 | buffer += buffer[0]; | ||
491 | } | ||
492 | |||
493 | if (buflen > 2 && buffer[2] == VS_STILL_IMAGE_FRAME) { | ||
494 | buflen -= buffer[0]; | ||
495 | buffer += buffer[0]; | ||
496 | } | ||
497 | |||
498 | if (buflen > 2 && buffer[2] == VS_COLORFORMAT) { | ||
499 | if (buflen < 6) { | ||
500 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
501 | "interface %d COLORFORMAT error\n", | ||
502 | dev->udev->devnum, | ||
503 | alts->desc.bInterfaceNumber); | ||
504 | return -EINVAL; | ||
505 | } | ||
506 | |||
507 | format->colorspace = uvc_colorspace(buffer[3]); | ||
508 | |||
509 | buflen -= buffer[0]; | ||
510 | buffer += buffer[0]; | ||
511 | } | ||
512 | |||
513 | return buffer - start; | ||
514 | } | ||
515 | |||
516 | static int uvc_parse_streaming(struct uvc_device *dev, | ||
517 | struct usb_interface *intf) | ||
518 | { | ||
519 | struct uvc_streaming *streaming = NULL; | ||
520 | struct uvc_format *format; | ||
521 | struct uvc_frame *frame; | ||
522 | struct usb_host_interface *alts = &intf->altsetting[0]; | ||
523 | unsigned char *_buffer, *buffer = alts->extra; | ||
524 | int _buflen, buflen = alts->extralen; | ||
525 | unsigned int nformats = 0, nframes = 0, nintervals = 0; | ||
526 | unsigned int size, i, n, p; | ||
527 | __u32 *interval; | ||
528 | __u16 psize; | ||
529 | int ret = -EINVAL; | ||
530 | |||
531 | if (intf->cur_altsetting->desc.bInterfaceSubClass | ||
532 | != SC_VIDEOSTREAMING) { | ||
533 | uvc_trace(UVC_TRACE_DESCR, "device %d interface %d isn't a " | ||
534 | "video streaming interface\n", dev->udev->devnum, | ||
535 | intf->altsetting[0].desc.bInterfaceNumber); | ||
536 | return -EINVAL; | ||
537 | } | ||
538 | |||
539 | if (usb_driver_claim_interface(&uvc_driver.driver, intf, dev)) { | ||
540 | uvc_trace(UVC_TRACE_DESCR, "device %d interface %d is already " | ||
541 | "claimed\n", dev->udev->devnum, | ||
542 | intf->altsetting[0].desc.bInterfaceNumber); | ||
543 | return -EINVAL; | ||
544 | } | ||
545 | |||
546 | streaming = kzalloc(sizeof *streaming, GFP_KERNEL); | ||
547 | if (streaming == NULL) { | ||
548 | usb_driver_release_interface(&uvc_driver.driver, intf); | ||
549 | return -EINVAL; | ||
550 | } | ||
551 | |||
552 | mutex_init(&streaming->mutex); | ||
553 | streaming->intf = usb_get_intf(intf); | ||
554 | streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; | ||
555 | |||
556 | /* The Pico iMage webcam has its class-specific interface descriptors | ||
557 | * after the endpoint descriptors. | ||
558 | */ | ||
559 | if (buflen == 0) { | ||
560 | for (i = 0; i < alts->desc.bNumEndpoints; ++i) { | ||
561 | struct usb_host_endpoint *ep = &alts->endpoint[i]; | ||
562 | |||
563 | if (ep->extralen == 0) | ||
564 | continue; | ||
565 | |||
566 | if (ep->extralen > 2 && | ||
567 | ep->extra[1] == USB_DT_CS_INTERFACE) { | ||
568 | uvc_trace(UVC_TRACE_DESCR, "trying extra data " | ||
569 | "from endpoint %u.\n", i); | ||
570 | buffer = alts->endpoint[i].extra; | ||
571 | buflen = alts->endpoint[i].extralen; | ||
572 | break; | ||
573 | } | ||
574 | } | ||
575 | } | ||
576 | |||
577 | /* Skip the standard interface descriptors. */ | ||
578 | while (buflen > 2 && buffer[1] != USB_DT_CS_INTERFACE) { | ||
579 | buflen -= buffer[0]; | ||
580 | buffer += buffer[0]; | ||
581 | } | ||
582 | |||
583 | if (buflen <= 2) { | ||
584 | uvc_trace(UVC_TRACE_DESCR, "no class-specific streaming " | ||
585 | "interface descriptors found.\n"); | ||
586 | goto error; | ||
587 | } | ||
588 | |||
589 | /* Parse the header descriptor. */ | ||
590 | if (buffer[2] == VS_OUTPUT_HEADER) { | ||
591 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " | ||
592 | "%d OUTPUT HEADER descriptor is not supported.\n", | ||
593 | dev->udev->devnum, alts->desc.bInterfaceNumber); | ||
594 | goto error; | ||
595 | } else if (buffer[2] == VS_INPUT_HEADER) { | ||
596 | p = buflen >= 5 ? buffer[3] : 0; | ||
597 | n = buflen >= 12 ? buffer[12] : 0; | ||
598 | |||
599 | if (buflen < 13 + p*n || buffer[2] != VS_INPUT_HEADER) { | ||
600 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " | ||
601 | "interface %d INPUT HEADER descriptor is " | ||
602 | "invalid.\n", dev->udev->devnum, | ||
603 | alts->desc.bInterfaceNumber); | ||
604 | goto error; | ||
605 | } | ||
606 | |||
607 | streaming->header.bNumFormats = p; | ||
608 | streaming->header.bEndpointAddress = buffer[6]; | ||
609 | streaming->header.bmInfo = buffer[7]; | ||
610 | streaming->header.bTerminalLink = buffer[8]; | ||
611 | streaming->header.bStillCaptureMethod = buffer[9]; | ||
612 | streaming->header.bTriggerSupport = buffer[10]; | ||
613 | streaming->header.bTriggerUsage = buffer[11]; | ||
614 | streaming->header.bControlSize = n; | ||
615 | |||
616 | streaming->header.bmaControls = kmalloc(p*n, GFP_KERNEL); | ||
617 | if (streaming->header.bmaControls == NULL) { | ||
618 | ret = -ENOMEM; | ||
619 | goto error; | ||
620 | } | ||
621 | |||
622 | memcpy(streaming->header.bmaControls, &buffer[13], p*n); | ||
623 | } else { | ||
624 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " | ||
625 | "%d HEADER descriptor not found.\n", dev->udev->devnum, | ||
626 | alts->desc.bInterfaceNumber); | ||
627 | goto error; | ||
628 | } | ||
629 | |||
630 | buflen -= buffer[0]; | ||
631 | buffer += buffer[0]; | ||
632 | |||
633 | _buffer = buffer; | ||
634 | _buflen = buflen; | ||
635 | |||
636 | /* Count the format and frame descriptors. */ | ||
637 | while (_buflen > 2) { | ||
638 | switch (_buffer[2]) { | ||
639 | case VS_FORMAT_UNCOMPRESSED: | ||
640 | case VS_FORMAT_MJPEG: | ||
641 | case VS_FORMAT_FRAME_BASED: | ||
642 | nformats++; | ||
643 | break; | ||
644 | |||
645 | case VS_FORMAT_DV: | ||
646 | /* DV format has no frame descriptor. We will create a | ||
647 | * dummy frame descriptor with a dummy frame interval. | ||
648 | */ | ||
649 | nformats++; | ||
650 | nframes++; | ||
651 | nintervals++; | ||
652 | break; | ||
653 | |||
654 | case VS_FORMAT_MPEG2TS: | ||
655 | case VS_FORMAT_STREAM_BASED: | ||
656 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " | ||
657 | "interface %d FORMAT %u is not supported.\n", | ||
658 | dev->udev->devnum, | ||
659 | alts->desc.bInterfaceNumber, _buffer[2]); | ||
660 | break; | ||
661 | |||
662 | case VS_FRAME_UNCOMPRESSED: | ||
663 | case VS_FRAME_MJPEG: | ||
664 | nframes++; | ||
665 | if (_buflen > 25) | ||
666 | nintervals += _buffer[25] ? _buffer[25] : 3; | ||
667 | break; | ||
668 | |||
669 | case VS_FRAME_FRAME_BASED: | ||
670 | nframes++; | ||
671 | if (_buflen > 21) | ||
672 | nintervals += _buffer[21] ? _buffer[21] : 3; | ||
673 | break; | ||
674 | } | ||
675 | |||
676 | _buflen -= _buffer[0]; | ||
677 | _buffer += _buffer[0]; | ||
678 | } | ||
679 | |||
680 | if (nformats == 0) { | ||
681 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " | ||
682 | "%d has no supported formats defined.\n", | ||
683 | dev->udev->devnum, alts->desc.bInterfaceNumber); | ||
684 | goto error; | ||
685 | } | ||
686 | |||
687 | size = nformats * sizeof *format + nframes * sizeof *frame | ||
688 | + nintervals * sizeof *interval; | ||
689 | format = kzalloc(size, GFP_KERNEL); | ||
690 | if (format == NULL) { | ||
691 | ret = -ENOMEM; | ||
692 | goto error; | ||
693 | } | ||
694 | |||
695 | frame = (struct uvc_frame *)&format[nformats]; | ||
696 | interval = (__u32 *)&frame[nframes]; | ||
697 | |||
698 | streaming->format = format; | ||
699 | streaming->nformats = nformats; | ||
700 | |||
701 | /* Parse the format descriptors. */ | ||
702 | while (buflen > 2) { | ||
703 | switch (buffer[2]) { | ||
704 | case VS_FORMAT_UNCOMPRESSED: | ||
705 | case VS_FORMAT_MJPEG: | ||
706 | case VS_FORMAT_DV: | ||
707 | case VS_FORMAT_FRAME_BASED: | ||
708 | format->frame = frame; | ||
709 | ret = uvc_parse_format(dev, streaming, format, | ||
710 | &interval, buffer, buflen); | ||
711 | if (ret < 0) | ||
712 | goto error; | ||
713 | |||
714 | frame += format->nframes; | ||
715 | format++; | ||
716 | |||
717 | buflen -= ret; | ||
718 | buffer += ret; | ||
719 | continue; | ||
720 | |||
721 | default: | ||
722 | break; | ||
723 | } | ||
724 | |||
725 | buflen -= buffer[0]; | ||
726 | buffer += buffer[0]; | ||
727 | } | ||
728 | |||
729 | /* Parse the alternate settings to find the maximum bandwidth. */ | ||
730 | for (i = 0; i < intf->num_altsetting; ++i) { | ||
731 | struct usb_host_endpoint *ep; | ||
732 | alts = &intf->altsetting[i]; | ||
733 | ep = uvc_find_endpoint(alts, | ||
734 | streaming->header.bEndpointAddress); | ||
735 | if (ep == NULL) | ||
736 | continue; | ||
737 | |||
738 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); | ||
739 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); | ||
740 | if (psize > streaming->maxpsize) | ||
741 | streaming->maxpsize = psize; | ||
742 | } | ||
743 | |||
744 | list_add_tail(&streaming->list, &dev->streaming); | ||
745 | return 0; | ||
746 | |||
747 | error: | ||
748 | usb_driver_release_interface(&uvc_driver.driver, intf); | ||
749 | usb_put_intf(intf); | ||
750 | kfree(streaming->format); | ||
751 | kfree(streaming->header.bmaControls); | ||
752 | kfree(streaming); | ||
753 | return ret; | ||
754 | } | ||
755 | |||
756 | /* Parse vendor-specific extensions. */ | ||
757 | static int uvc_parse_vendor_control(struct uvc_device *dev, | ||
758 | const unsigned char *buffer, int buflen) | ||
759 | { | ||
760 | struct usb_device *udev = dev->udev; | ||
761 | struct usb_host_interface *alts = dev->intf->cur_altsetting; | ||
762 | struct uvc_entity *unit; | ||
763 | unsigned int n, p; | ||
764 | int handled = 0; | ||
765 | |||
766 | switch (le16_to_cpu(dev->udev->descriptor.idVendor)) { | ||
767 | case 0x046d: /* Logitech */ | ||
768 | if (buffer[1] != 0x41 || buffer[2] != 0x01) | ||
769 | break; | ||
770 | |||
771 | /* Logitech implements several vendor specific functions | ||
772 | * through vendor specific extension units (LXU). | ||
773 | * | ||
774 | * The LXU descriptors are similar to XU descriptors | ||
775 | * (see "USB Device Video Class for Video Devices", section | ||
776 | * 3.7.2.6 "Extension Unit Descriptor") with the following | ||
777 | * differences: | ||
778 | * | ||
779 | * ---------------------------------------------------------- | ||
780 | * 0 bLength 1 Number | ||
781 | * Size of this descriptor, in bytes: 24+p+n*2 | ||
782 | * ---------------------------------------------------------- | ||
783 | * 23+p+n bmControlsType N Bitmap | ||
784 | * Individual bits in the set are defined: | ||
785 | * 0: Absolute | ||
786 | * 1: Relative | ||
787 | * | ||
788 | * This bitset is mapped exactly the same as bmControls. | ||
789 | * ---------------------------------------------------------- | ||
790 | * 23+p+n*2 bReserved 1 Boolean | ||
791 | * ---------------------------------------------------------- | ||
792 | * 24+p+n*2 iExtension 1 Index | ||
793 | * Index of a string descriptor that describes this | ||
794 | * extension unit. | ||
795 | * ---------------------------------------------------------- | ||
796 | */ | ||
797 | p = buflen >= 22 ? buffer[21] : 0; | ||
798 | n = buflen >= 25 + p ? buffer[22+p] : 0; | ||
799 | |||
800 | if (buflen < 25 + p + 2*n) { | ||
801 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
802 | "interface %d EXTENSION_UNIT error\n", | ||
803 | udev->devnum, alts->desc.bInterfaceNumber); | ||
804 | break; | ||
805 | } | ||
806 | |||
807 | unit = kzalloc(sizeof *unit + p + 2*n, GFP_KERNEL); | ||
808 | if (unit == NULL) | ||
809 | return -ENOMEM; | ||
810 | |||
811 | unit->id = buffer[3]; | ||
812 | unit->type = VC_EXTENSION_UNIT; | ||
813 | memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); | ||
814 | unit->extension.bNumControls = buffer[20]; | ||
815 | unit->extension.bNrInPins = | ||
816 | le16_to_cpup((__le16 *)&buffer[21]); | ||
817 | unit->extension.baSourceID = (__u8 *)unit + sizeof *unit; | ||
818 | memcpy(unit->extension.baSourceID, &buffer[22], p); | ||
819 | unit->extension.bControlSize = buffer[22+p]; | ||
820 | unit->extension.bmControls = (__u8 *)unit + sizeof *unit + p; | ||
821 | unit->extension.bmControlsType = (__u8 *)unit + sizeof *unit | ||
822 | + p + n; | ||
823 | memcpy(unit->extension.bmControls, &buffer[23+p], 2*n); | ||
824 | |||
825 | if (buffer[24+p+2*n] != 0) | ||
826 | usb_string(udev, buffer[24+p+2*n], unit->name, | ||
827 | sizeof unit->name); | ||
828 | else | ||
829 | sprintf(unit->name, "Extension %u", buffer[3]); | ||
830 | |||
831 | list_add_tail(&unit->list, &dev->entities); | ||
832 | handled = 1; | ||
833 | break; | ||
834 | } | ||
835 | |||
836 | return handled; | ||
837 | } | ||
838 | |||
839 | static int uvc_parse_standard_control(struct uvc_device *dev, | ||
840 | const unsigned char *buffer, int buflen) | ||
841 | { | ||
842 | struct usb_device *udev = dev->udev; | ||
843 | struct uvc_entity *unit, *term; | ||
844 | struct usb_interface *intf; | ||
845 | struct usb_host_interface *alts = dev->intf->cur_altsetting; | ||
846 | unsigned int i, n, p, len; | ||
847 | __u16 type; | ||
848 | |||
849 | switch (buffer[2]) { | ||
850 | case VC_HEADER: | ||
851 | n = buflen >= 12 ? buffer[11] : 0; | ||
852 | |||
853 | if (buflen < 12 || buflen < 12 + n) { | ||
854 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
855 | "interface %d HEADER error\n", udev->devnum, | ||
856 | alts->desc.bInterfaceNumber); | ||
857 | return -EINVAL; | ||
858 | } | ||
859 | |||
860 | dev->uvc_version = le16_to_cpup((__le16 *)&buffer[3]); | ||
861 | dev->clock_frequency = le32_to_cpup((__le32 *)&buffer[7]); | ||
862 | |||
863 | /* Parse all USB Video Streaming interfaces. */ | ||
864 | for (i = 0; i < n; ++i) { | ||
865 | intf = usb_ifnum_to_if(udev, buffer[12+i]); | ||
866 | if (intf == NULL) { | ||
867 | uvc_trace(UVC_TRACE_DESCR, "device %d " | ||
868 | "interface %d doesn't exists\n", | ||
869 | udev->devnum, i); | ||
870 | continue; | ||
871 | } | ||
872 | |||
873 | uvc_parse_streaming(dev, intf); | ||
874 | } | ||
875 | break; | ||
876 | |||
877 | case VC_INPUT_TERMINAL: | ||
878 | if (buflen < 8) { | ||
879 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
880 | "interface %d INPUT_TERMINAL error\n", | ||
881 | udev->devnum, alts->desc.bInterfaceNumber); | ||
882 | return -EINVAL; | ||
883 | } | ||
884 | |||
885 | /* Make sure the terminal type MSB is not null, otherwise it | ||
886 | * could be confused with a unit. | ||
887 | */ | ||
888 | type = le16_to_cpup((__le16 *)&buffer[4]); | ||
889 | if ((type & 0xff00) == 0) { | ||
890 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
891 | "interface %d INPUT_TERMINAL %d has invalid " | ||
892 | "type 0x%04x, skipping\n", udev->devnum, | ||
893 | alts->desc.bInterfaceNumber, | ||
894 | buffer[3], type); | ||
895 | return 0; | ||
896 | } | ||
897 | |||
898 | n = 0; | ||
899 | p = 0; | ||
900 | len = 8; | ||
901 | |||
902 | if (type == ITT_CAMERA) { | ||
903 | n = buflen >= 15 ? buffer[14] : 0; | ||
904 | len = 15; | ||
905 | |||
906 | } else if (type == ITT_MEDIA_TRANSPORT_INPUT) { | ||
907 | n = buflen >= 9 ? buffer[8] : 0; | ||
908 | p = buflen >= 10 + n ? buffer[9+n] : 0; | ||
909 | len = 10; | ||
910 | } | ||
911 | |||
912 | if (buflen < len + n + p) { | ||
913 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
914 | "interface %d INPUT_TERMINAL error\n", | ||
915 | udev->devnum, alts->desc.bInterfaceNumber); | ||
916 | return -EINVAL; | ||
917 | } | ||
918 | |||
919 | term = kzalloc(sizeof *term + n + p, GFP_KERNEL); | ||
920 | if (term == NULL) | ||
921 | return -ENOMEM; | ||
922 | |||
923 | term->id = buffer[3]; | ||
924 | term->type = type | UVC_TERM_INPUT; | ||
925 | |||
926 | if (UVC_ENTITY_TYPE(term) == ITT_CAMERA) { | ||
927 | term->camera.bControlSize = n; | ||
928 | term->camera.bmControls = (__u8 *)term + sizeof *term; | ||
929 | term->camera.wObjectiveFocalLengthMin = | ||
930 | le16_to_cpup((__le16 *)&buffer[8]); | ||
931 | term->camera.wObjectiveFocalLengthMax = | ||
932 | le16_to_cpup((__le16 *)&buffer[10]); | ||
933 | term->camera.wOcularFocalLength = | ||
934 | le16_to_cpup((__le16 *)&buffer[12]); | ||
935 | memcpy(term->camera.bmControls, &buffer[15], n); | ||
936 | } else if (UVC_ENTITY_TYPE(term) == ITT_MEDIA_TRANSPORT_INPUT) { | ||
937 | term->media.bControlSize = n; | ||
938 | term->media.bmControls = (__u8 *)term + sizeof *term; | ||
939 | term->media.bTransportModeSize = p; | ||
940 | term->media.bmTransportModes = (__u8 *)term | ||
941 | + sizeof *term + n; | ||
942 | memcpy(term->media.bmControls, &buffer[9], n); | ||
943 | memcpy(term->media.bmTransportModes, &buffer[10+n], p); | ||
944 | } | ||
945 | |||
946 | if (buffer[7] != 0) | ||
947 | usb_string(udev, buffer[7], term->name, | ||
948 | sizeof term->name); | ||
949 | else if (UVC_ENTITY_TYPE(term) == ITT_CAMERA) | ||
950 | sprintf(term->name, "Camera %u", buffer[3]); | ||
951 | else if (UVC_ENTITY_TYPE(term) == ITT_MEDIA_TRANSPORT_INPUT) | ||
952 | sprintf(term->name, "Media %u", buffer[3]); | ||
953 | else | ||
954 | sprintf(term->name, "Input %u", buffer[3]); | ||
955 | |||
956 | list_add_tail(&term->list, &dev->entities); | ||
957 | break; | ||
958 | |||
959 | case VC_OUTPUT_TERMINAL: | ||
960 | if (buflen < 9) { | ||
961 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
962 | "interface %d OUTPUT_TERMINAL error\n", | ||
963 | udev->devnum, alts->desc.bInterfaceNumber); | ||
964 | return -EINVAL; | ||
965 | } | ||
966 | |||
967 | /* Make sure the terminal type MSB is not null, otherwise it | ||
968 | * could be confused with a unit. | ||
969 | */ | ||
970 | type = le16_to_cpup((__le16 *)&buffer[4]); | ||
971 | if ((type & 0xff00) == 0) { | ||
972 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
973 | "interface %d OUTPUT_TERMINAL %d has invalid " | ||
974 | "type 0x%04x, skipping\n", udev->devnum, | ||
975 | alts->desc.bInterfaceNumber, buffer[3], type); | ||
976 | return 0; | ||
977 | } | ||
978 | |||
979 | term = kzalloc(sizeof *term, GFP_KERNEL); | ||
980 | if (term == NULL) | ||
981 | return -ENOMEM; | ||
982 | |||
983 | term->id = buffer[3]; | ||
984 | term->type = type | UVC_TERM_OUTPUT; | ||
985 | term->output.bSourceID = buffer[7]; | ||
986 | |||
987 | if (buffer[8] != 0) | ||
988 | usb_string(udev, buffer[8], term->name, | ||
989 | sizeof term->name); | ||
990 | else | ||
991 | sprintf(term->name, "Output %u", buffer[3]); | ||
992 | |||
993 | list_add_tail(&term->list, &dev->entities); | ||
994 | break; | ||
995 | |||
996 | case VC_SELECTOR_UNIT: | ||
997 | p = buflen >= 5 ? buffer[4] : 0; | ||
998 | |||
999 | if (buflen < 5 || buflen < 6 + p) { | ||
1000 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
1001 | "interface %d SELECTOR_UNIT error\n", | ||
1002 | udev->devnum, alts->desc.bInterfaceNumber); | ||
1003 | return -EINVAL; | ||
1004 | } | ||
1005 | |||
1006 | unit = kzalloc(sizeof *unit + p, GFP_KERNEL); | ||
1007 | if (unit == NULL) | ||
1008 | return -ENOMEM; | ||
1009 | |||
1010 | unit->id = buffer[3]; | ||
1011 | unit->type = buffer[2]; | ||
1012 | unit->selector.bNrInPins = buffer[4]; | ||
1013 | unit->selector.baSourceID = (__u8 *)unit + sizeof *unit; | ||
1014 | memcpy(unit->selector.baSourceID, &buffer[5], p); | ||
1015 | |||
1016 | if (buffer[5+p] != 0) | ||
1017 | usb_string(udev, buffer[5+p], unit->name, | ||
1018 | sizeof unit->name); | ||
1019 | else | ||
1020 | sprintf(unit->name, "Selector %u", buffer[3]); | ||
1021 | |||
1022 | list_add_tail(&unit->list, &dev->entities); | ||
1023 | break; | ||
1024 | |||
1025 | case VC_PROCESSING_UNIT: | ||
1026 | n = buflen >= 8 ? buffer[7] : 0; | ||
1027 | p = dev->uvc_version >= 0x0110 ? 10 : 9; | ||
1028 | |||
1029 | if (buflen < p + n) { | ||
1030 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
1031 | "interface %d PROCESSING_UNIT error\n", | ||
1032 | udev->devnum, alts->desc.bInterfaceNumber); | ||
1033 | return -EINVAL; | ||
1034 | } | ||
1035 | |||
1036 | unit = kzalloc(sizeof *unit + n, GFP_KERNEL); | ||
1037 | if (unit == NULL) | ||
1038 | return -ENOMEM; | ||
1039 | |||
1040 | unit->id = buffer[3]; | ||
1041 | unit->type = buffer[2]; | ||
1042 | unit->processing.bSourceID = buffer[4]; | ||
1043 | unit->processing.wMaxMultiplier = | ||
1044 | le16_to_cpup((__le16 *)&buffer[5]); | ||
1045 | unit->processing.bControlSize = buffer[7]; | ||
1046 | unit->processing.bmControls = (__u8 *)unit + sizeof *unit; | ||
1047 | memcpy(unit->processing.bmControls, &buffer[8], n); | ||
1048 | if (dev->uvc_version >= 0x0110) | ||
1049 | unit->processing.bmVideoStandards = buffer[9+n]; | ||
1050 | |||
1051 | if (buffer[8+n] != 0) | ||
1052 | usb_string(udev, buffer[8+n], unit->name, | ||
1053 | sizeof unit->name); | ||
1054 | else | ||
1055 | sprintf(unit->name, "Processing %u", buffer[3]); | ||
1056 | |||
1057 | list_add_tail(&unit->list, &dev->entities); | ||
1058 | break; | ||
1059 | |||
1060 | case VC_EXTENSION_UNIT: | ||
1061 | p = buflen >= 22 ? buffer[21] : 0; | ||
1062 | n = buflen >= 24 + p ? buffer[22+p] : 0; | ||
1063 | |||
1064 | if (buflen < 24 + p + n) { | ||
1065 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
1066 | "interface %d EXTENSION_UNIT error\n", | ||
1067 | udev->devnum, alts->desc.bInterfaceNumber); | ||
1068 | return -EINVAL; | ||
1069 | } | ||
1070 | |||
1071 | unit = kzalloc(sizeof *unit + p + n, GFP_KERNEL); | ||
1072 | if (unit == NULL) | ||
1073 | return -ENOMEM; | ||
1074 | |||
1075 | unit->id = buffer[3]; | ||
1076 | unit->type = buffer[2]; | ||
1077 | memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); | ||
1078 | unit->extension.bNumControls = buffer[20]; | ||
1079 | unit->extension.bNrInPins = | ||
1080 | le16_to_cpup((__le16 *)&buffer[21]); | ||
1081 | unit->extension.baSourceID = (__u8 *)unit + sizeof *unit; | ||
1082 | memcpy(unit->extension.baSourceID, &buffer[22], p); | ||
1083 | unit->extension.bControlSize = buffer[22+p]; | ||
1084 | unit->extension.bmControls = (__u8 *)unit + sizeof *unit + p; | ||
1085 | memcpy(unit->extension.bmControls, &buffer[23+p], n); | ||
1086 | |||
1087 | if (buffer[23+p+n] != 0) | ||
1088 | usb_string(udev, buffer[23+p+n], unit->name, | ||
1089 | sizeof unit->name); | ||
1090 | else | ||
1091 | sprintf(unit->name, "Extension %u", buffer[3]); | ||
1092 | |||
1093 | list_add_tail(&unit->list, &dev->entities); | ||
1094 | break; | ||
1095 | |||
1096 | default: | ||
1097 | uvc_trace(UVC_TRACE_DESCR, "Found an unknown CS_INTERFACE " | ||
1098 | "descriptor (%u)\n", buffer[2]); | ||
1099 | break; | ||
1100 | } | ||
1101 | |||
1102 | return 0; | ||
1103 | } | ||
1104 | |||
1105 | static int uvc_parse_control(struct uvc_device *dev) | ||
1106 | { | ||
1107 | struct usb_host_interface *alts = dev->intf->cur_altsetting; | ||
1108 | unsigned char *buffer = alts->extra; | ||
1109 | int buflen = alts->extralen; | ||
1110 | int ret; | ||
1111 | |||
1112 | /* Parse the default alternate setting only, as the UVC specification | ||
1113 | * defines a single alternate setting, the default alternate setting | ||
1114 | * zero. | ||
1115 | */ | ||
1116 | |||
1117 | while (buflen > 2) { | ||
1118 | if (uvc_parse_vendor_control(dev, buffer, buflen) || | ||
1119 | buffer[1] != USB_DT_CS_INTERFACE) | ||
1120 | goto next_descriptor; | ||
1121 | |||
1122 | if ((ret = uvc_parse_standard_control(dev, buffer, buflen)) < 0) | ||
1123 | return ret; | ||
1124 | |||
1125 | next_descriptor: | ||
1126 | buflen -= buffer[0]; | ||
1127 | buffer += buffer[0]; | ||
1128 | } | ||
1129 | |||
1130 | /* Check if the optional status endpoint is present. */ | ||
1131 | if (alts->desc.bNumEndpoints == 1) { | ||
1132 | struct usb_host_endpoint *ep = &alts->endpoint[0]; | ||
1133 | struct usb_endpoint_descriptor *desc = &ep->desc; | ||
1134 | |||
1135 | if (usb_endpoint_is_int_in(desc) && | ||
1136 | le16_to_cpu(desc->wMaxPacketSize) >= 8 && | ||
1137 | desc->bInterval != 0) { | ||
1138 | uvc_trace(UVC_TRACE_DESCR, "Found a Status endpoint " | ||
1139 | "(addr %02x).\n", desc->bEndpointAddress); | ||
1140 | dev->int_ep = ep; | ||
1141 | } | ||
1142 | } | ||
1143 | |||
1144 | return 0; | ||
1145 | } | ||
1146 | |||
1147 | /* ------------------------------------------------------------------------ | ||
1148 | * USB probe and disconnect | ||
1149 | */ | ||
1150 | |||
1151 | /* | ||
1152 | * Unregister the video devices. | ||
1153 | */ | ||
1154 | static void uvc_unregister_video(struct uvc_device *dev) | ||
1155 | { | ||
1156 | if (dev->video.vdev) { | ||
1157 | if (dev->video.vdev->minor == -1) | ||
1158 | video_device_release(dev->video.vdev); | ||
1159 | else | ||
1160 | video_unregister_device(dev->video.vdev); | ||
1161 | dev->video.vdev = NULL; | ||
1162 | } | ||
1163 | } | ||
1164 | |||
1165 | /* | ||
1166 | * Scan the UVC descriptors to locate a chain starting at an Output Terminal | ||
1167 | * and containing the following units: | ||
1168 | * | ||
1169 | * - a USB Streaming Output Terminal | ||
1170 | * - zero or one Processing Unit | ||
1171 | * - zero, one or mode single-input Selector Units | ||
1172 | * - zero or one multiple-input Selector Units, provided all inputs are | ||
1173 | * connected to input terminals | ||
1174 | * - zero, one or mode single-input Extension Units | ||
1175 | * - one Camera Input Terminal, or one or more External terminals. | ||
1176 | * | ||
1177 | * A side forward scan is made on each detected entity to check for additional | ||
1178 | * extension units. | ||
1179 | */ | ||
1180 | static int uvc_scan_chain_entity(struct uvc_video_device *video, | ||
1181 | struct uvc_entity *entity) | ||
1182 | { | ||
1183 | switch (UVC_ENTITY_TYPE(entity)) { | ||
1184 | case VC_EXTENSION_UNIT: | ||
1185 | if (uvc_trace_param & UVC_TRACE_PROBE) | ||
1186 | printk(" <- XU %d", entity->id); | ||
1187 | |||
1188 | if (entity->extension.bNrInPins != 1) { | ||
1189 | uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more " | ||
1190 | "than 1 input pin.\n", entity->id); | ||
1191 | return -1; | ||
1192 | } | ||
1193 | |||
1194 | list_add_tail(&entity->chain, &video->extensions); | ||
1195 | break; | ||
1196 | |||
1197 | case VC_PROCESSING_UNIT: | ||
1198 | if (uvc_trace_param & UVC_TRACE_PROBE) | ||
1199 | printk(" <- PU %d", entity->id); | ||
1200 | |||
1201 | if (video->processing != NULL) { | ||
1202 | uvc_trace(UVC_TRACE_DESCR, "Found multiple " | ||
1203 | "Processing Units in chain.\n"); | ||
1204 | return -1; | ||
1205 | } | ||
1206 | |||
1207 | video->processing = entity; | ||
1208 | break; | ||
1209 | |||
1210 | case VC_SELECTOR_UNIT: | ||
1211 | if (uvc_trace_param & UVC_TRACE_PROBE) | ||
1212 | printk(" <- SU %d", entity->id); | ||
1213 | |||
1214 | /* Single-input selector units are ignored. */ | ||
1215 | if (entity->selector.bNrInPins == 1) | ||
1216 | break; | ||
1217 | |||
1218 | if (video->selector != NULL) { | ||
1219 | uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector " | ||
1220 | "Units in chain.\n"); | ||
1221 | return -1; | ||
1222 | } | ||
1223 | |||
1224 | video->selector = entity; | ||
1225 | break; | ||
1226 | |||
1227 | case ITT_VENDOR_SPECIFIC: | ||
1228 | case ITT_CAMERA: | ||
1229 | case ITT_MEDIA_TRANSPORT_INPUT: | ||
1230 | if (uvc_trace_param & UVC_TRACE_PROBE) | ||
1231 | printk(" <- IT %d\n", entity->id); | ||
1232 | |||
1233 | list_add_tail(&entity->chain, &video->iterms); | ||
1234 | break; | ||
1235 | |||
1236 | default: | ||
1237 | uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type " | ||
1238 | "0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity)); | ||
1239 | return -1; | ||
1240 | } | ||
1241 | |||
1242 | return 0; | ||
1243 | } | ||
1244 | |||
1245 | static int uvc_scan_chain_forward(struct uvc_video_device *video, | ||
1246 | struct uvc_entity *entity, struct uvc_entity *prev) | ||
1247 | { | ||
1248 | struct uvc_entity *forward; | ||
1249 | int found; | ||
1250 | |||
1251 | /* Forward scan */ | ||
1252 | forward = NULL; | ||
1253 | found = 0; | ||
1254 | |||
1255 | while (1) { | ||
1256 | forward = uvc_entity_by_reference(video->dev, entity->id, | ||
1257 | forward); | ||
1258 | if (forward == NULL) | ||
1259 | break; | ||
1260 | |||
1261 | if (UVC_ENTITY_TYPE(forward) != VC_EXTENSION_UNIT || | ||
1262 | forward == prev) | ||
1263 | continue; | ||
1264 | |||
1265 | if (forward->extension.bNrInPins != 1) { | ||
1266 | uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has" | ||
1267 | "more than 1 input pin.\n", entity->id); | ||
1268 | return -1; | ||
1269 | } | ||
1270 | |||
1271 | list_add_tail(&forward->chain, &video->extensions); | ||
1272 | if (uvc_trace_param & UVC_TRACE_PROBE) { | ||
1273 | if (!found) | ||
1274 | printk(" (-> XU"); | ||
1275 | |||
1276 | printk(" %d", forward->id); | ||
1277 | found = 1; | ||
1278 | } | ||
1279 | } | ||
1280 | if (found) | ||
1281 | printk(")"); | ||
1282 | |||
1283 | return 0; | ||
1284 | } | ||
1285 | |||
1286 | static int uvc_scan_chain_backward(struct uvc_video_device *video, | ||
1287 | struct uvc_entity *entity) | ||
1288 | { | ||
1289 | struct uvc_entity *term; | ||
1290 | int id = -1, i; | ||
1291 | |||
1292 | switch (UVC_ENTITY_TYPE(entity)) { | ||
1293 | case VC_EXTENSION_UNIT: | ||
1294 | id = entity->extension.baSourceID[0]; | ||
1295 | break; | ||
1296 | |||
1297 | case VC_PROCESSING_UNIT: | ||
1298 | id = entity->processing.bSourceID; | ||
1299 | break; | ||
1300 | |||
1301 | case VC_SELECTOR_UNIT: | ||
1302 | /* Single-input selector units are ignored. */ | ||
1303 | if (entity->selector.bNrInPins == 1) { | ||
1304 | id = entity->selector.baSourceID[0]; | ||
1305 | break; | ||
1306 | } | ||
1307 | |||
1308 | if (uvc_trace_param & UVC_TRACE_PROBE) | ||
1309 | printk(" <- IT"); | ||
1310 | |||
1311 | video->selector = entity; | ||
1312 | for (i = 0; i < entity->selector.bNrInPins; ++i) { | ||
1313 | id = entity->selector.baSourceID[i]; | ||
1314 | term = uvc_entity_by_id(video->dev, id); | ||
1315 | if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) { | ||
1316 | uvc_trace(UVC_TRACE_DESCR, "Selector unit %d " | ||
1317 | "input %d isn't connected to an " | ||
1318 | "input terminal\n", entity->id, i); | ||
1319 | return -1; | ||
1320 | } | ||
1321 | |||
1322 | if (uvc_trace_param & UVC_TRACE_PROBE) | ||
1323 | printk(" %d", term->id); | ||
1324 | |||
1325 | list_add_tail(&term->chain, &video->iterms); | ||
1326 | uvc_scan_chain_forward(video, term, entity); | ||
1327 | } | ||
1328 | |||
1329 | if (uvc_trace_param & UVC_TRACE_PROBE) | ||
1330 | printk("\n"); | ||
1331 | |||
1332 | id = 0; | ||
1333 | break; | ||
1334 | } | ||
1335 | |||
1336 | return id; | ||
1337 | } | ||
1338 | |||
1339 | static int uvc_scan_chain(struct uvc_video_device *video) | ||
1340 | { | ||
1341 | struct uvc_entity *entity, *prev; | ||
1342 | int id; | ||
1343 | |||
1344 | entity = video->oterm; | ||
1345 | uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id); | ||
1346 | id = entity->output.bSourceID; | ||
1347 | while (id != 0) { | ||
1348 | prev = entity; | ||
1349 | entity = uvc_entity_by_id(video->dev, id); | ||
1350 | if (entity == NULL) { | ||
1351 | uvc_trace(UVC_TRACE_DESCR, "Found reference to " | ||
1352 | "unknown entity %d.\n", id); | ||
1353 | return -1; | ||
1354 | } | ||
1355 | |||
1356 | /* Process entity */ | ||
1357 | if (uvc_scan_chain_entity(video, entity) < 0) | ||
1358 | return -1; | ||
1359 | |||
1360 | /* Forward scan */ | ||
1361 | if (uvc_scan_chain_forward(video, entity, prev) < 0) | ||
1362 | return -1; | ||
1363 | |||
1364 | /* Stop when a terminal is found. */ | ||
1365 | if (!UVC_ENTITY_IS_UNIT(entity)) | ||
1366 | break; | ||
1367 | |||
1368 | /* Backward scan */ | ||
1369 | id = uvc_scan_chain_backward(video, entity); | ||
1370 | if (id < 0) | ||
1371 | return id; | ||
1372 | } | ||
1373 | |||
1374 | /* Initialize the video buffers queue. */ | ||
1375 | uvc_queue_init(&video->queue); | ||
1376 | |||
1377 | return 0; | ||
1378 | } | ||
1379 | |||
1380 | /* | ||
1381 | * Register the video devices. | ||
1382 | * | ||
1383 | * The driver currently supports a single video device per control interface | ||
1384 | * only. The terminal and units must match the following structure: | ||
1385 | * | ||
1386 | * ITT_CAMERA -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> TT_STREAMING | ||
1387 | * | ||
1388 | * The Extension Units, if present, must have a single input pin. The | ||
1389 | * Processing Unit and Extension Units can be in any order. Additional | ||
1390 | * Extension Units connected to the main chain as single-unit branches are | ||
1391 | * also supported. | ||
1392 | */ | ||
1393 | static int uvc_register_video(struct uvc_device *dev) | ||
1394 | { | ||
1395 | struct video_device *vdev; | ||
1396 | struct uvc_entity *term; | ||
1397 | int found = 0, ret; | ||
1398 | |||
1399 | /* Check if the control interface matches the structure we expect. */ | ||
1400 | list_for_each_entry(term, &dev->entities, list) { | ||
1401 | struct uvc_streaming *streaming; | ||
1402 | |||
1403 | if (UVC_ENTITY_TYPE(term) != TT_STREAMING) | ||
1404 | continue; | ||
1405 | |||
1406 | memset(&dev->video, 0, sizeof dev->video); | ||
1407 | mutex_init(&dev->video.ctrl_mutex); | ||
1408 | INIT_LIST_HEAD(&dev->video.iterms); | ||
1409 | INIT_LIST_HEAD(&dev->video.extensions); | ||
1410 | dev->video.oterm = term; | ||
1411 | dev->video.dev = dev; | ||
1412 | if (uvc_scan_chain(&dev->video) < 0) | ||
1413 | continue; | ||
1414 | |||
1415 | list_for_each_entry(streaming, &dev->streaming, list) { | ||
1416 | if (streaming->header.bTerminalLink == term->id) { | ||
1417 | dev->video.streaming = streaming; | ||
1418 | found = 1; | ||
1419 | break; | ||
1420 | } | ||
1421 | } | ||
1422 | |||
1423 | if (found) | ||
1424 | break; | ||
1425 | } | ||
1426 | |||
1427 | if (!found) { | ||
1428 | uvc_printk(KERN_INFO, "No valid video chain found.\n"); | ||
1429 | return -1; | ||
1430 | } | ||
1431 | |||
1432 | if (uvc_trace_param & UVC_TRACE_PROBE) { | ||
1433 | uvc_printk(KERN_INFO, "Found a valid video chain ("); | ||
1434 | list_for_each_entry(term, &dev->video.iterms, chain) { | ||
1435 | printk("%d", term->id); | ||
1436 | if (term->chain.next != &dev->video.iterms) | ||
1437 | printk(","); | ||
1438 | } | ||
1439 | printk(" -> %d).\n", dev->video.oterm->id); | ||
1440 | } | ||
1441 | |||
1442 | /* Initialize the streaming interface with default streaming | ||
1443 | * parameters. | ||
1444 | */ | ||
1445 | if ((ret = uvc_video_init(&dev->video)) < 0) { | ||
1446 | uvc_printk(KERN_ERR, "Failed to initialize the device " | ||
1447 | "(%d).\n", ret); | ||
1448 | return ret; | ||
1449 | } | ||
1450 | |||
1451 | /* Register the device with V4L. */ | ||
1452 | vdev = video_device_alloc(); | ||
1453 | if (vdev == NULL) | ||
1454 | return -1; | ||
1455 | |||
1456 | /* We already hold a reference to dev->udev. The video device will be | ||
1457 | * unregistered before the reference is released, so we don't need to | ||
1458 | * get another one. | ||
1459 | */ | ||
1460 | vdev->dev = &dev->intf->dev; | ||
1461 | vdev->type = 0; | ||
1462 | vdev->type2 = 0; | ||
1463 | vdev->minor = -1; | ||
1464 | vdev->fops = &uvc_fops; | ||
1465 | vdev->release = video_device_release; | ||
1466 | strncpy(vdev->name, dev->name, sizeof vdev->name); | ||
1467 | |||
1468 | /* Set the driver data before calling video_register_device, otherwise | ||
1469 | * uvc_v4l2_open might race us. | ||
1470 | * | ||
1471 | * FIXME: usb_set_intfdata hasn't been called so far. Is that a | ||
1472 | * problem ? Does any function which could be called here get | ||
1473 | * a pointer to the usb_interface ? | ||
1474 | */ | ||
1475 | dev->video.vdev = vdev; | ||
1476 | video_set_drvdata(vdev, &dev->video); | ||
1477 | |||
1478 | if (video_register_device(vdev, VFL_TYPE_GRABBER, -1) < 0) { | ||
1479 | dev->video.vdev = NULL; | ||
1480 | video_device_release(vdev); | ||
1481 | return -1; | ||
1482 | } | ||
1483 | |||
1484 | return 0; | ||
1485 | } | ||
1486 | |||
1487 | /* | ||
1488 | * Delete the UVC device. | ||
1489 | * | ||
1490 | * Called by the kernel when the last reference to the uvc_device structure | ||
1491 | * is released. | ||
1492 | * | ||
1493 | * Unregistering the video devices is done here because every opened instance | ||
1494 | * must be closed before the device can be unregistered. An alternative would | ||
1495 | * have been to use another reference count for uvc_v4l2_open/uvc_release, and | ||
1496 | * unregister the video devices on disconnect when that reference count drops | ||
1497 | * to zero. | ||
1498 | * | ||
1499 | * As this function is called after or during disconnect(), all URBs have | ||
1500 | * already been canceled by the USB core. There is no need to kill the | ||
1501 | * interrupt URB manually. | ||
1502 | */ | ||
1503 | void uvc_delete(struct kref *kref) | ||
1504 | { | ||
1505 | struct uvc_device *dev = container_of(kref, struct uvc_device, kref); | ||
1506 | struct list_head *p, *n; | ||
1507 | |||
1508 | /* Unregister the video device */ | ||
1509 | uvc_unregister_video(dev); | ||
1510 | usb_put_intf(dev->intf); | ||
1511 | usb_put_dev(dev->udev); | ||
1512 | |||
1513 | uvc_status_cleanup(dev); | ||
1514 | uvc_ctrl_cleanup_device(dev); | ||
1515 | |||
1516 | list_for_each_safe(p, n, &dev->entities) { | ||
1517 | struct uvc_entity *entity; | ||
1518 | entity = list_entry(p, struct uvc_entity, list); | ||
1519 | kfree(entity); | ||
1520 | } | ||
1521 | |||
1522 | list_for_each_safe(p, n, &dev->streaming) { | ||
1523 | struct uvc_streaming *streaming; | ||
1524 | streaming = list_entry(p, struct uvc_streaming, list); | ||
1525 | usb_driver_release_interface(&uvc_driver.driver, | ||
1526 | streaming->intf); | ||
1527 | usb_put_intf(streaming->intf); | ||
1528 | kfree(streaming->format); | ||
1529 | kfree(streaming->header.bmaControls); | ||
1530 | kfree(streaming); | ||
1531 | } | ||
1532 | |||
1533 | kfree(dev); | ||
1534 | } | ||
1535 | |||
1536 | static int uvc_probe(struct usb_interface *intf, | ||
1537 | const struct usb_device_id *id) | ||
1538 | { | ||
1539 | struct usb_device *udev = interface_to_usbdev(intf); | ||
1540 | struct uvc_device *dev; | ||
1541 | int ret; | ||
1542 | |||
1543 | if (id->idVendor && id->idProduct) | ||
1544 | uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s " | ||
1545 | "(%04x:%04x)\n", udev->devpath, id->idVendor, | ||
1546 | id->idProduct); | ||
1547 | else | ||
1548 | uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n", | ||
1549 | udev->devpath); | ||
1550 | |||
1551 | /* Allocate memory for the device and initialize it */ | ||
1552 | if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL) | ||
1553 | return -ENOMEM; | ||
1554 | |||
1555 | INIT_LIST_HEAD(&dev->entities); | ||
1556 | INIT_LIST_HEAD(&dev->streaming); | ||
1557 | kref_init(&dev->kref); | ||
1558 | |||
1559 | dev->udev = usb_get_dev(udev); | ||
1560 | dev->intf = usb_get_intf(intf); | ||
1561 | dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; | ||
1562 | dev->quirks = id->driver_info | uvc_quirks_param; | ||
1563 | |||
1564 | if (udev->product != NULL) | ||
1565 | strncpy(dev->name, udev->product, sizeof dev->name); | ||
1566 | else | ||
1567 | snprintf(dev->name, sizeof dev->name, | ||
1568 | "UVC Camera (%04x:%04x)", | ||
1569 | le16_to_cpu(udev->descriptor.idVendor), | ||
1570 | le16_to_cpu(udev->descriptor.idProduct)); | ||
1571 | |||
1572 | /* Parse the Video Class control descriptor */ | ||
1573 | if (uvc_parse_control(dev) < 0) { | ||
1574 | uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC " | ||
1575 | "descriptors.\n"); | ||
1576 | goto error; | ||
1577 | } | ||
1578 | |||
1579 | uvc_printk(KERN_INFO, "Found UVC %u.%02u device %s (%04x:%04x)\n", | ||
1580 | dev->uvc_version >> 8, dev->uvc_version & 0xff, | ||
1581 | udev->product ? udev->product : "<unnamed>", | ||
1582 | le16_to_cpu(udev->descriptor.idVendor), | ||
1583 | le16_to_cpu(udev->descriptor.idProduct)); | ||
1584 | |||
1585 | if (uvc_quirks_param != 0) { | ||
1586 | uvc_printk(KERN_INFO, "Forcing device quirks 0x%x by module " | ||
1587 | "parameter for testing purpose.\n", uvc_quirks_param); | ||
1588 | uvc_printk(KERN_INFO, "Please report required quirks to the " | ||
1589 | "linux-uvc-devel mailing list.\n"); | ||
1590 | } | ||
1591 | |||
1592 | /* Initialize controls */ | ||
1593 | if (uvc_ctrl_init_device(dev) < 0) | ||
1594 | goto error; | ||
1595 | |||
1596 | /* Register the video devices */ | ||
1597 | if (uvc_register_video(dev) < 0) | ||
1598 | goto error; | ||
1599 | |||
1600 | /* Save our data pointer in the interface data */ | ||
1601 | usb_set_intfdata(intf, dev); | ||
1602 | |||
1603 | /* Initialize the interrupt URB */ | ||
1604 | if ((ret = uvc_status_init(dev)) < 0) { | ||
1605 | uvc_printk(KERN_INFO, "Unable to initialize the status " | ||
1606 | "endpoint (%d), status interrupt will not be " | ||
1607 | "supported.\n", ret); | ||
1608 | } | ||
1609 | |||
1610 | uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n"); | ||
1611 | return 0; | ||
1612 | |||
1613 | error: | ||
1614 | kref_put(&dev->kref, uvc_delete); | ||
1615 | return -ENODEV; | ||
1616 | } | ||
1617 | |||
1618 | static void uvc_disconnect(struct usb_interface *intf) | ||
1619 | { | ||
1620 | struct uvc_device *dev = usb_get_intfdata(intf); | ||
1621 | |||
1622 | /* Set the USB interface data to NULL. This can be done outside the | ||
1623 | * lock, as there's no other reader. | ||
1624 | */ | ||
1625 | usb_set_intfdata(intf, NULL); | ||
1626 | |||
1627 | if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOSTREAMING) | ||
1628 | return; | ||
1629 | |||
1630 | /* uvc_v4l2_open() might race uvc_disconnect(). A static driver-wide | ||
1631 | * lock is needed to prevent uvc_disconnect from releasing its | ||
1632 | * reference to the uvc_device instance after uvc_v4l2_open() received | ||
1633 | * the pointer to the device (video_devdata) but before it got the | ||
1634 | * chance to increase the reference count (kref_get). | ||
1635 | */ | ||
1636 | mutex_lock(&uvc_driver.open_mutex); | ||
1637 | |||
1638 | dev->state |= UVC_DEV_DISCONNECTED; | ||
1639 | kref_put(&dev->kref, uvc_delete); | ||
1640 | |||
1641 | mutex_unlock(&uvc_driver.open_mutex); | ||
1642 | } | ||
1643 | |||
1644 | static int uvc_suspend(struct usb_interface *intf, pm_message_t message) | ||
1645 | { | ||
1646 | struct uvc_device *dev = usb_get_intfdata(intf); | ||
1647 | |||
1648 | uvc_trace(UVC_TRACE_SUSPEND, "Suspending interface %u\n", | ||
1649 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
1650 | |||
1651 | /* Controls are cached on the fly so they don't need to be saved. */ | ||
1652 | if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) | ||
1653 | return uvc_status_suspend(dev); | ||
1654 | |||
1655 | if (dev->video.streaming->intf != intf) { | ||
1656 | uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB " | ||
1657 | "interface mismatch.\n"); | ||
1658 | return -EINVAL; | ||
1659 | } | ||
1660 | |||
1661 | return uvc_video_suspend(&dev->video); | ||
1662 | } | ||
1663 | |||
1664 | static int uvc_resume(struct usb_interface *intf) | ||
1665 | { | ||
1666 | struct uvc_device *dev = usb_get_intfdata(intf); | ||
1667 | int ret; | ||
1668 | |||
1669 | uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n", | ||
1670 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
1671 | |||
1672 | if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) { | ||
1673 | if ((ret = uvc_ctrl_resume_device(dev)) < 0) | ||
1674 | return ret; | ||
1675 | |||
1676 | return uvc_status_resume(dev); | ||
1677 | } | ||
1678 | |||
1679 | if (dev->video.streaming->intf != intf) { | ||
1680 | uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB " | ||
1681 | "interface mismatch.\n"); | ||
1682 | return -EINVAL; | ||
1683 | } | ||
1684 | |||
1685 | return uvc_video_resume(&dev->video); | ||
1686 | } | ||
1687 | |||
1688 | /* ------------------------------------------------------------------------ | ||
1689 | * Driver initialization and cleanup | ||
1690 | */ | ||
1691 | |||
1692 | /* | ||
1693 | * The Logitech cameras listed below have their interface class set to | ||
1694 | * VENDOR_SPEC because they don't announce themselves as UVC devices, even | ||
1695 | * though they are compliant. | ||
1696 | */ | ||
1697 | static struct usb_device_id uvc_ids[] = { | ||
1698 | /* ALi M5606 (Clevo M540SR) */ | ||
1699 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1700 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1701 | .idVendor = 0x0402, | ||
1702 | .idProduct = 0x5606, | ||
1703 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1704 | .bInterfaceSubClass = 1, | ||
1705 | .bInterfaceProtocol = 0, | ||
1706 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1707 | /* Creative Live! Optia */ | ||
1708 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1709 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1710 | .idVendor = 0x041e, | ||
1711 | .idProduct = 0x4057, | ||
1712 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1713 | .bInterfaceSubClass = 1, | ||
1714 | .bInterfaceProtocol = 0, | ||
1715 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1716 | /* Microsoft Lifecam NX-6000 */ | ||
1717 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1718 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1719 | .idVendor = 0x045e, | ||
1720 | .idProduct = 0x00f8, | ||
1721 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1722 | .bInterfaceSubClass = 1, | ||
1723 | .bInterfaceProtocol = 0, | ||
1724 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1725 | /* Microsoft Lifecam VX-7000 */ | ||
1726 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1727 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1728 | .idVendor = 0x045e, | ||
1729 | .idProduct = 0x0723, | ||
1730 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1731 | .bInterfaceSubClass = 1, | ||
1732 | .bInterfaceProtocol = 0, | ||
1733 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1734 | /* Logitech Quickcam Fusion */ | ||
1735 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1736 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1737 | .idVendor = 0x046d, | ||
1738 | .idProduct = 0x08c1, | ||
1739 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
1740 | .bInterfaceSubClass = 1, | ||
1741 | .bInterfaceProtocol = 0 }, | ||
1742 | /* Logitech Quickcam Orbit MP */ | ||
1743 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1744 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1745 | .idVendor = 0x046d, | ||
1746 | .idProduct = 0x08c2, | ||
1747 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
1748 | .bInterfaceSubClass = 1, | ||
1749 | .bInterfaceProtocol = 0 }, | ||
1750 | /* Logitech Quickcam Pro for Notebook */ | ||
1751 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1752 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1753 | .idVendor = 0x046d, | ||
1754 | .idProduct = 0x08c3, | ||
1755 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
1756 | .bInterfaceSubClass = 1, | ||
1757 | .bInterfaceProtocol = 0 }, | ||
1758 | /* Logitech Quickcam Pro 5000 */ | ||
1759 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1760 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1761 | .idVendor = 0x046d, | ||
1762 | .idProduct = 0x08c5, | ||
1763 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
1764 | .bInterfaceSubClass = 1, | ||
1765 | .bInterfaceProtocol = 0 }, | ||
1766 | /* Logitech Quickcam OEM Dell Notebook */ | ||
1767 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1768 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1769 | .idVendor = 0x046d, | ||
1770 | .idProduct = 0x08c6, | ||
1771 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
1772 | .bInterfaceSubClass = 1, | ||
1773 | .bInterfaceProtocol = 0 }, | ||
1774 | /* Logitech Quickcam OEM Cisco VT Camera II */ | ||
1775 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1776 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1777 | .idVendor = 0x046d, | ||
1778 | .idProduct = 0x08c7, | ||
1779 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
1780 | .bInterfaceSubClass = 1, | ||
1781 | .bInterfaceProtocol = 0 }, | ||
1782 | /* Apple Built-In iSight */ | ||
1783 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1784 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1785 | .idVendor = 0x05ac, | ||
1786 | .idProduct = 0x8501, | ||
1787 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1788 | .bInterfaceSubClass = 1, | ||
1789 | .bInterfaceProtocol = 0, | ||
1790 | .driver_info = UVC_QUIRK_PROBE_MINMAX | ||
1791 | | UVC_QUIRK_BUILTIN_ISIGHT }, | ||
1792 | /* Genesys Logic USB 2.0 PC Camera */ | ||
1793 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1794 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1795 | .idVendor = 0x05e3, | ||
1796 | .idProduct = 0x0505, | ||
1797 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1798 | .bInterfaceSubClass = 1, | ||
1799 | .bInterfaceProtocol = 0, | ||
1800 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | ||
1801 | /* Silicon Motion SM371 */ | ||
1802 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1803 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1804 | .idVendor = 0x090c, | ||
1805 | .idProduct = 0xb371, | ||
1806 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1807 | .bInterfaceSubClass = 1, | ||
1808 | .bInterfaceProtocol = 0, | ||
1809 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1810 | /* MT6227 */ | ||
1811 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1812 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1813 | .idVendor = 0x0e8d, | ||
1814 | .idProduct = 0x0004, | ||
1815 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1816 | .bInterfaceSubClass = 1, | ||
1817 | .bInterfaceProtocol = 0, | ||
1818 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1819 | /* Syntek (HP Spartan) */ | ||
1820 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1821 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1822 | .idVendor = 0x174f, | ||
1823 | .idProduct = 0x5212, | ||
1824 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1825 | .bInterfaceSubClass = 1, | ||
1826 | .bInterfaceProtocol = 0, | ||
1827 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | ||
1828 | /* Syntek (Asus U3S) */ | ||
1829 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1830 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1831 | .idVendor = 0x174f, | ||
1832 | .idProduct = 0x8a33, | ||
1833 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1834 | .bInterfaceSubClass = 1, | ||
1835 | .bInterfaceProtocol = 0, | ||
1836 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | ||
1837 | /* Ecamm Pico iMage */ | ||
1838 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1839 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1840 | .idVendor = 0x18cd, | ||
1841 | .idProduct = 0xcafe, | ||
1842 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1843 | .bInterfaceSubClass = 1, | ||
1844 | .bInterfaceProtocol = 0, | ||
1845 | .driver_info = UVC_QUIRK_PROBE_EXTRAFIELDS }, | ||
1846 | /* Bodelin ProScopeHR */ | ||
1847 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1848 | | USB_DEVICE_ID_MATCH_DEV_HI | ||
1849 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1850 | .idVendor = 0x19ab, | ||
1851 | .idProduct = 0x1000, | ||
1852 | .bcdDevice_hi = 0x0126, | ||
1853 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1854 | .bInterfaceSubClass = 1, | ||
1855 | .bInterfaceProtocol = 0, | ||
1856 | .driver_info = UVC_QUIRK_STATUS_INTERVAL }, | ||
1857 | /* SiGma Micro USB Web Camera */ | ||
1858 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1859 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1860 | .idVendor = 0x1c4f, | ||
1861 | .idProduct = 0x3000, | ||
1862 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1863 | .bInterfaceSubClass = 1, | ||
1864 | .bInterfaceProtocol = 0, | ||
1865 | .driver_info = UVC_QUIRK_PROBE_MINMAX | ||
1866 | | UVC_QUIRK_IGNORE_SELECTOR_UNIT}, | ||
1867 | /* Acer OEM Webcam - Unknown vendor */ | ||
1868 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1869 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1870 | .idVendor = 0x5986, | ||
1871 | .idProduct = 0x0100, | ||
1872 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1873 | .bInterfaceSubClass = 1, | ||
1874 | .bInterfaceProtocol = 0, | ||
1875 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1876 | /* Packard Bell OEM Webcam */ | ||
1877 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1878 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1879 | .idVendor = 0x5986, | ||
1880 | .idProduct = 0x0101, | ||
1881 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1882 | .bInterfaceSubClass = 1, | ||
1883 | .bInterfaceProtocol = 0, | ||
1884 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1885 | /* Acer Crystal Eye webcam */ | ||
1886 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1887 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1888 | .idVendor = 0x5986, | ||
1889 | .idProduct = 0x0102, | ||
1890 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1891 | .bInterfaceSubClass = 1, | ||
1892 | .bInterfaceProtocol = 0, | ||
1893 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1894 | /* Acer OrbiCam - Unknown vendor */ | ||
1895 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
1896 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
1897 | .idVendor = 0x5986, | ||
1898 | .idProduct = 0x0200, | ||
1899 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
1900 | .bInterfaceSubClass = 1, | ||
1901 | .bInterfaceProtocol = 0, | ||
1902 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
1903 | /* Generic USB Video Class */ | ||
1904 | { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, | ||
1905 | {} | ||
1906 | }; | ||
1907 | |||
1908 | MODULE_DEVICE_TABLE(usb, uvc_ids); | ||
1909 | |||
1910 | struct uvc_driver uvc_driver = { | ||
1911 | .driver = { | ||
1912 | .name = "uvcvideo", | ||
1913 | .probe = uvc_probe, | ||
1914 | .disconnect = uvc_disconnect, | ||
1915 | .suspend = uvc_suspend, | ||
1916 | .resume = uvc_resume, | ||
1917 | .id_table = uvc_ids, | ||
1918 | .supports_autosuspend = 1, | ||
1919 | }, | ||
1920 | }; | ||
1921 | |||
1922 | static int __init uvc_init(void) | ||
1923 | { | ||
1924 | int result; | ||
1925 | |||
1926 | INIT_LIST_HEAD(&uvc_driver.devices); | ||
1927 | INIT_LIST_HEAD(&uvc_driver.controls); | ||
1928 | mutex_init(&uvc_driver.open_mutex); | ||
1929 | mutex_init(&uvc_driver.ctrl_mutex); | ||
1930 | |||
1931 | uvc_ctrl_init(); | ||
1932 | |||
1933 | result = usb_register(&uvc_driver.driver); | ||
1934 | if (result == 0) | ||
1935 | printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n"); | ||
1936 | return result; | ||
1937 | } | ||
1938 | |||
1939 | static void __exit uvc_cleanup(void) | ||
1940 | { | ||
1941 | usb_deregister(&uvc_driver.driver); | ||
1942 | } | ||
1943 | |||
1944 | module_init(uvc_init); | ||
1945 | module_exit(uvc_cleanup); | ||
1946 | |||
1947 | module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR); | ||
1948 | MODULE_PARM_DESC(quirks, "Forced device quirks"); | ||
1949 | module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR); | ||
1950 | MODULE_PARM_DESC(trace, "Trace level bitmask"); | ||
1951 | |||
1952 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
1953 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
1954 | MODULE_LICENSE("GPL"); | ||
1955 | MODULE_VERSION(DRIVER_VERSION); | ||
diff --git a/drivers/media/video/uvc/uvc_isight.c b/drivers/media/video/uvc/uvc_isight.c new file mode 100644 index 000000000000..37bdefdbead5 --- /dev/null +++ b/drivers/media/video/uvc/uvc_isight.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * uvc_isight.c -- USB Video Class driver - iSight support | ||
3 | * | ||
4 | * Copyright (C) 2006-2007 | ||
5 | * Ivan N. Zlatev <contact@i-nz.net> | ||
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/usb.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/mm.h> | ||
17 | |||
18 | #include "uvcvideo.h" | ||
19 | |||
20 | /* Built-in iSight webcams implements most of UVC 1.0 except a | ||
21 | * different packet format. Instead of sending a header at the | ||
22 | * beginning of each isochronous transfer payload, the webcam sends a | ||
23 | * single header per image (on its own in a packet), followed by | ||
24 | * packets containing data only. | ||
25 | * | ||
26 | * Offset Size (bytes) Description | ||
27 | * ------------------------------------------------------------------ | ||
28 | * 0x00 1 Header length | ||
29 | * 0x01 1 Flags (UVC-compliant) | ||
30 | * 0x02 4 Always equal to '11223344' | ||
31 | * 0x06 8 Always equal to 'deadbeefdeadface' | ||
32 | * 0x0e 16 Unknown | ||
33 | * | ||
34 | * The header can be prefixed by an optional, unknown-purpose byte. | ||
35 | */ | ||
36 | |||
37 | static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf, | ||
38 | const __u8 *data, unsigned int len) | ||
39 | { | ||
40 | static const __u8 hdr[] = { | ||
41 | 0x11, 0x22, 0x33, 0x44, | ||
42 | 0xde, 0xad, 0xbe, 0xef, | ||
43 | 0xde, 0xad, 0xfa, 0xce | ||
44 | }; | ||
45 | |||
46 | unsigned int maxlen, nbytes; | ||
47 | __u8 *mem; | ||
48 | int is_header = 0; | ||
49 | |||
50 | if (buf == NULL) | ||
51 | return 0; | ||
52 | |||
53 | if ((len >= 14 && memcmp(&data[2], hdr, 12) == 0) || | ||
54 | (len >= 15 && memcmp(&data[3], hdr, 12) == 0)) { | ||
55 | uvc_trace(UVC_TRACE_FRAME, "iSight header found\n"); | ||
56 | is_header = 1; | ||
57 | } | ||
58 | |||
59 | /* Synchronize to the input stream by waiting for a header packet. */ | ||
60 | if (buf->state != UVC_BUF_STATE_ACTIVE) { | ||
61 | if (!is_header) { | ||
62 | uvc_trace(UVC_TRACE_FRAME, "Dropping packet (out of " | ||
63 | "sync).\n"); | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | buf->state = UVC_BUF_STATE_ACTIVE; | ||
68 | } | ||
69 | |||
70 | /* Mark the buffer as done if we're at the beginning of a new frame. | ||
71 | * | ||
72 | * Empty buffers (bytesused == 0) don't trigger end of frame detection | ||
73 | * as it doesn't make sense to return an empty buffer. | ||
74 | */ | ||
75 | if (is_header && buf->buf.bytesused != 0) { | ||
76 | buf->state = UVC_BUF_STATE_DONE; | ||
77 | return -EAGAIN; | ||
78 | } | ||
79 | |||
80 | /* Copy the video data to the buffer. Skip header packets, as they | ||
81 | * contain no data. | ||
82 | */ | ||
83 | if (!is_header) { | ||
84 | maxlen = buf->buf.length - buf->buf.bytesused; | ||
85 | mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused; | ||
86 | nbytes = min(len, maxlen); | ||
87 | memcpy(mem, data, nbytes); | ||
88 | buf->buf.bytesused += nbytes; | ||
89 | |||
90 | if (len > maxlen || buf->buf.bytesused == buf->buf.length) { | ||
91 | uvc_trace(UVC_TRACE_FRAME, "Frame complete " | ||
92 | "(overflow).\n"); | ||
93 | buf->state = UVC_BUF_STATE_DONE; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video, | ||
101 | struct uvc_buffer *buf) | ||
102 | { | ||
103 | int ret, i; | ||
104 | |||
105 | for (i = 0; i < urb->number_of_packets; ++i) { | ||
106 | if (urb->iso_frame_desc[i].status < 0) { | ||
107 | uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame " | ||
108 | "lost (%d).\n", | ||
109 | urb->iso_frame_desc[i].status); | ||
110 | } | ||
111 | |||
112 | /* Decode the payload packet. | ||
113 | * uvc_video_decode is entered twice when a frame transition | ||
114 | * has been detected because the end of frame can only be | ||
115 | * reliably detected when the first packet of the new frame | ||
116 | * is processed. The first pass detects the transition and | ||
117 | * closes the previous frame's buffer, the second pass | ||
118 | * processes the data of the first payload of the new frame. | ||
119 | */ | ||
120 | do { | ||
121 | ret = isight_decode(&video->queue, buf, | ||
122 | urb->transfer_buffer + | ||
123 | urb->iso_frame_desc[i].offset, | ||
124 | urb->iso_frame_desc[i].actual_length); | ||
125 | |||
126 | if (buf == NULL) | ||
127 | break; | ||
128 | |||
129 | if (buf->state == UVC_BUF_STATE_DONE || | ||
130 | buf->state == UVC_BUF_STATE_ERROR) | ||
131 | buf = uvc_queue_next_buffer(&video->queue, buf); | ||
132 | } while (ret == -EAGAIN); | ||
133 | } | ||
134 | } | ||
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c new file mode 100644 index 000000000000..0923f0e3b3d4 --- /dev/null +++ b/drivers/media/video/uvc/uvc_queue.c | |||
@@ -0,0 +1,477 @@ | |||
1 | /* | ||
2 | * uvc_queue.c -- USB Video Class driver - Buffers management | ||
3 | * | ||
4 | * Copyright (C) 2005-2008 | ||
5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | ||
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/version.h> | ||
16 | #include <linux/list.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/usb.h> | ||
19 | #include <linux/videodev2.h> | ||
20 | #include <linux/vmalloc.h> | ||
21 | #include <linux/wait.h> | ||
22 | #include <asm/atomic.h> | ||
23 | |||
24 | #include "uvcvideo.h" | ||
25 | |||
26 | /* ------------------------------------------------------------------------ | ||
27 | * Video buffers queue management. | ||
28 | * | ||
29 | * Video queues is initialized by uvc_queue_init(). The function performs | ||
30 | * basic initialization of the uvc_video_queue struct and never fails. | ||
31 | * | ||
32 | * Video buffer allocation and freeing are performed by uvc_alloc_buffers and | ||
33 | * uvc_free_buffers respectively. The former acquires the video queue lock, | ||
34 | * while the later must be called with the lock held (so that allocation can | ||
35 | * free previously allocated buffers). Trying to free buffers that are mapped | ||
36 | * to user space will return -EBUSY. | ||
37 | * | ||
38 | * Video buffers are managed using two queues. However, unlike most USB video | ||
39 | * drivers which use an in queue and an out queue, we use a main queue which | ||
40 | * holds all queued buffers (both 'empty' and 'done' buffers), and an irq | ||
41 | * queue which holds empty buffers. This design (copied from video-buf) | ||
42 | * minimizes locking in interrupt, as only one queue is shared between | ||
43 | * interrupt and user contexts. | ||
44 | * | ||
45 | * Use cases | ||
46 | * --------- | ||
47 | * | ||
48 | * Unless stated otherwise, all operations which modify the irq buffers queue | ||
49 | * are protected by the irq spinlock. | ||
50 | * | ||
51 | * 1. The user queues the buffers, starts streaming and dequeues a buffer. | ||
52 | * | ||
53 | * The buffers are added to the main and irq queues. Both operations are | ||
54 | * protected by the queue lock, and the latert is protected by the irq | ||
55 | * spinlock as well. | ||
56 | * | ||
57 | * The completion handler fetches a buffer from the irq queue and fills it | ||
58 | * with video data. If no buffer is available (irq queue empty), the handler | ||
59 | * returns immediately. | ||
60 | * | ||
61 | * When the buffer is full, the completion handler removes it from the irq | ||
62 | * queue, marks it as ready (UVC_BUF_STATE_DONE) and wake its wait queue. | ||
63 | * At that point, any process waiting on the buffer will be woken up. If a | ||
64 | * process tries to dequeue a buffer after it has been marked ready, the | ||
65 | * dequeing will succeed immediately. | ||
66 | * | ||
67 | * 2. Buffers are queued, user is waiting on a buffer and the device gets | ||
68 | * disconnected. | ||
69 | * | ||
70 | * When the device is disconnected, the kernel calls the completion handler | ||
71 | * with an appropriate status code. The handler marks all buffers in the | ||
72 | * irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so | ||
73 | * that any process waiting on a buffer gets woken up. | ||
74 | * | ||
75 | * Waking up up the first buffer on the irq list is not enough, as the | ||
76 | * process waiting on the buffer might restart the dequeue operation | ||
77 | * immediately. | ||
78 | * | ||
79 | */ | ||
80 | |||
81 | void uvc_queue_init(struct uvc_video_queue *queue) | ||
82 | { | ||
83 | mutex_init(&queue->mutex); | ||
84 | spin_lock_init(&queue->irqlock); | ||
85 | INIT_LIST_HEAD(&queue->mainqueue); | ||
86 | INIT_LIST_HEAD(&queue->irqqueue); | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * Allocate the video buffers. | ||
91 | * | ||
92 | * Pages are reserved to make sure they will not be swaped, as they will be | ||
93 | * filled in URB completion handler. | ||
94 | * | ||
95 | * Buffers will be individually mapped, so they must all be page aligned. | ||
96 | */ | ||
97 | int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, | ||
98 | unsigned int buflength) | ||
99 | { | ||
100 | unsigned int bufsize = PAGE_ALIGN(buflength); | ||
101 | unsigned int i; | ||
102 | void *mem = NULL; | ||
103 | int ret; | ||
104 | |||
105 | if (nbuffers > UVC_MAX_VIDEO_BUFFERS) | ||
106 | nbuffers = UVC_MAX_VIDEO_BUFFERS; | ||
107 | |||
108 | mutex_lock(&queue->mutex); | ||
109 | |||
110 | if ((ret = uvc_free_buffers(queue)) < 0) | ||
111 | goto done; | ||
112 | |||
113 | /* Bail out if no buffers should be allocated. */ | ||
114 | if (nbuffers == 0) | ||
115 | goto done; | ||
116 | |||
117 | /* Decrement the number of buffers until allocation succeeds. */ | ||
118 | for (; nbuffers > 0; --nbuffers) { | ||
119 | mem = vmalloc_32(nbuffers * bufsize); | ||
120 | if (mem != NULL) | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | if (mem == NULL) { | ||
125 | ret = -ENOMEM; | ||
126 | goto done; | ||
127 | } | ||
128 | |||
129 | for (i = 0; i < nbuffers; ++i) { | ||
130 | memset(&queue->buffer[i], 0, sizeof queue->buffer[i]); | ||
131 | queue->buffer[i].buf.index = i; | ||
132 | queue->buffer[i].buf.m.offset = i * bufsize; | ||
133 | queue->buffer[i].buf.length = buflength; | ||
134 | queue->buffer[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
135 | queue->buffer[i].buf.sequence = 0; | ||
136 | queue->buffer[i].buf.field = V4L2_FIELD_NONE; | ||
137 | queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP; | ||
138 | queue->buffer[i].buf.flags = 0; | ||
139 | init_waitqueue_head(&queue->buffer[i].wait); | ||
140 | } | ||
141 | |||
142 | queue->mem = mem; | ||
143 | queue->count = nbuffers; | ||
144 | queue->buf_size = bufsize; | ||
145 | ret = nbuffers; | ||
146 | |||
147 | done: | ||
148 | mutex_unlock(&queue->mutex); | ||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * Free the video buffers. | ||
154 | * | ||
155 | * This function must be called with the queue lock held. | ||
156 | */ | ||
157 | int uvc_free_buffers(struct uvc_video_queue *queue) | ||
158 | { | ||
159 | unsigned int i; | ||
160 | |||
161 | for (i = 0; i < queue->count; ++i) { | ||
162 | if (queue->buffer[i].vma_use_count != 0) | ||
163 | return -EBUSY; | ||
164 | } | ||
165 | |||
166 | if (queue->count) { | ||
167 | vfree(queue->mem); | ||
168 | queue->count = 0; | ||
169 | } | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static void __uvc_query_buffer(struct uvc_buffer *buf, | ||
175 | struct v4l2_buffer *v4l2_buf) | ||
176 | { | ||
177 | memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf); | ||
178 | |||
179 | if (buf->vma_use_count) | ||
180 | v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED; | ||
181 | |||
182 | switch (buf->state) { | ||
183 | case UVC_BUF_STATE_ERROR: | ||
184 | case UVC_BUF_STATE_DONE: | ||
185 | v4l2_buf->flags |= V4L2_BUF_FLAG_DONE; | ||
186 | break; | ||
187 | case UVC_BUF_STATE_QUEUED: | ||
188 | case UVC_BUF_STATE_ACTIVE: | ||
189 | v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED; | ||
190 | break; | ||
191 | case UVC_BUF_STATE_IDLE: | ||
192 | default: | ||
193 | break; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | int uvc_query_buffer(struct uvc_video_queue *queue, | ||
198 | struct v4l2_buffer *v4l2_buf) | ||
199 | { | ||
200 | int ret = 0; | ||
201 | |||
202 | mutex_lock(&queue->mutex); | ||
203 | if (v4l2_buf->index >= queue->count) { | ||
204 | ret = -EINVAL; | ||
205 | goto done; | ||
206 | } | ||
207 | |||
208 | __uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf); | ||
209 | |||
210 | done: | ||
211 | mutex_unlock(&queue->mutex); | ||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | /* | ||
216 | * Queue a video buffer. Attempting to queue a buffer that has already been | ||
217 | * queued will return -EINVAL. | ||
218 | */ | ||
219 | int uvc_queue_buffer(struct uvc_video_queue *queue, | ||
220 | struct v4l2_buffer *v4l2_buf) | ||
221 | { | ||
222 | struct uvc_buffer *buf; | ||
223 | unsigned long flags; | ||
224 | int ret = 0; | ||
225 | |||
226 | uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index); | ||
227 | |||
228 | if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
229 | v4l2_buf->memory != V4L2_MEMORY_MMAP) { | ||
230 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " | ||
231 | "and/or memory (%u).\n", v4l2_buf->type, | ||
232 | v4l2_buf->memory); | ||
233 | return -EINVAL; | ||
234 | } | ||
235 | |||
236 | mutex_lock(&queue->mutex); | ||
237 | if (v4l2_buf->index >= queue->count) { | ||
238 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n"); | ||
239 | ret = -EINVAL; | ||
240 | goto done; | ||
241 | } | ||
242 | |||
243 | buf = &queue->buffer[v4l2_buf->index]; | ||
244 | if (buf->state != UVC_BUF_STATE_IDLE) { | ||
245 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state " | ||
246 | "(%u).\n", buf->state); | ||
247 | ret = -EINVAL; | ||
248 | goto done; | ||
249 | } | ||
250 | |||
251 | spin_lock_irqsave(&queue->irqlock, flags); | ||
252 | if (queue->flags & UVC_QUEUE_DISCONNECTED) { | ||
253 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
254 | ret = -ENODEV; | ||
255 | goto done; | ||
256 | } | ||
257 | buf->state = UVC_BUF_STATE_QUEUED; | ||
258 | buf->buf.bytesused = 0; | ||
259 | list_add_tail(&buf->stream, &queue->mainqueue); | ||
260 | list_add_tail(&buf->queue, &queue->irqqueue); | ||
261 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
262 | |||
263 | done: | ||
264 | mutex_unlock(&queue->mutex); | ||
265 | return ret; | ||
266 | } | ||
267 | |||
268 | static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking) | ||
269 | { | ||
270 | if (nonblocking) { | ||
271 | return (buf->state != UVC_BUF_STATE_QUEUED && | ||
272 | buf->state != UVC_BUF_STATE_ACTIVE) | ||
273 | ? 0 : -EAGAIN; | ||
274 | } | ||
275 | |||
276 | return wait_event_interruptible(buf->wait, | ||
277 | buf->state != UVC_BUF_STATE_QUEUED && | ||
278 | buf->state != UVC_BUF_STATE_ACTIVE); | ||
279 | } | ||
280 | |||
281 | /* | ||
282 | * Dequeue a video buffer. If nonblocking is false, block until a buffer is | ||
283 | * available. | ||
284 | */ | ||
285 | int uvc_dequeue_buffer(struct uvc_video_queue *queue, | ||
286 | struct v4l2_buffer *v4l2_buf, int nonblocking) | ||
287 | { | ||
288 | struct uvc_buffer *buf; | ||
289 | int ret = 0; | ||
290 | |||
291 | if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
292 | v4l2_buf->memory != V4L2_MEMORY_MMAP) { | ||
293 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " | ||
294 | "and/or memory (%u).\n", v4l2_buf->type, | ||
295 | v4l2_buf->memory); | ||
296 | return -EINVAL; | ||
297 | } | ||
298 | |||
299 | mutex_lock(&queue->mutex); | ||
300 | if (list_empty(&queue->mainqueue)) { | ||
301 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n"); | ||
302 | ret = -EINVAL; | ||
303 | goto done; | ||
304 | } | ||
305 | |||
306 | buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream); | ||
307 | if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0) | ||
308 | goto done; | ||
309 | |||
310 | uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n", | ||
311 | buf->buf.index, buf->state, buf->buf.bytesused); | ||
312 | |||
313 | switch (buf->state) { | ||
314 | case UVC_BUF_STATE_ERROR: | ||
315 | uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data " | ||
316 | "(transmission error).\n"); | ||
317 | ret = -EIO; | ||
318 | case UVC_BUF_STATE_DONE: | ||
319 | buf->state = UVC_BUF_STATE_IDLE; | ||
320 | break; | ||
321 | |||
322 | case UVC_BUF_STATE_IDLE: | ||
323 | case UVC_BUF_STATE_QUEUED: | ||
324 | case UVC_BUF_STATE_ACTIVE: | ||
325 | default: | ||
326 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u " | ||
327 | "(driver bug?).\n", buf->state); | ||
328 | ret = -EINVAL; | ||
329 | goto done; | ||
330 | } | ||
331 | |||
332 | list_del(&buf->stream); | ||
333 | __uvc_query_buffer(buf, v4l2_buf); | ||
334 | |||
335 | done: | ||
336 | mutex_unlock(&queue->mutex); | ||
337 | return ret; | ||
338 | } | ||
339 | |||
340 | /* | ||
341 | * Poll the video queue. | ||
342 | * | ||
343 | * This function implements video queue polling and is intended to be used by | ||
344 | * the device poll handler. | ||
345 | */ | ||
346 | unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, | ||
347 | poll_table *wait) | ||
348 | { | ||
349 | struct uvc_buffer *buf; | ||
350 | unsigned int mask = 0; | ||
351 | |||
352 | mutex_lock(&queue->mutex); | ||
353 | if (list_empty(&queue->mainqueue)) { | ||
354 | mask |= POLLERR; | ||
355 | goto done; | ||
356 | } | ||
357 | buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream); | ||
358 | |||
359 | poll_wait(file, &buf->wait, wait); | ||
360 | if (buf->state == UVC_BUF_STATE_DONE || | ||
361 | buf->state == UVC_BUF_STATE_ERROR) | ||
362 | mask |= POLLIN | POLLRDNORM; | ||
363 | |||
364 | done: | ||
365 | mutex_unlock(&queue->mutex); | ||
366 | return mask; | ||
367 | } | ||
368 | |||
369 | /* | ||
370 | * Enable or disable the video buffers queue. | ||
371 | * | ||
372 | * The queue must be enabled before starting video acquisition and must be | ||
373 | * disabled after stopping it. This ensures that the video buffers queue | ||
374 | * state can be properly initialized before buffers are accessed from the | ||
375 | * interrupt handler. | ||
376 | * | ||
377 | * Enabling the video queue initializes parameters (such as sequence number, | ||
378 | * sync pattern, ...). If the queue is already enabled, return -EBUSY. | ||
379 | * | ||
380 | * Disabling the video queue cancels the queue and removes all buffers from | ||
381 | * the main queue. | ||
382 | * | ||
383 | * This function can't be called from interrupt context. Use | ||
384 | * uvc_queue_cancel() instead. | ||
385 | */ | ||
386 | int uvc_queue_enable(struct uvc_video_queue *queue, int enable) | ||
387 | { | ||
388 | unsigned int i; | ||
389 | int ret = 0; | ||
390 | |||
391 | mutex_lock(&queue->mutex); | ||
392 | if (enable) { | ||
393 | if (uvc_queue_streaming(queue)) { | ||
394 | ret = -EBUSY; | ||
395 | goto done; | ||
396 | } | ||
397 | queue->sequence = 0; | ||
398 | queue->flags |= UVC_QUEUE_STREAMING; | ||
399 | } else { | ||
400 | uvc_queue_cancel(queue, 0); | ||
401 | INIT_LIST_HEAD(&queue->mainqueue); | ||
402 | |||
403 | for (i = 0; i < queue->count; ++i) | ||
404 | queue->buffer[i].state = UVC_BUF_STATE_IDLE; | ||
405 | |||
406 | queue->flags &= ~UVC_QUEUE_STREAMING; | ||
407 | } | ||
408 | |||
409 | done: | ||
410 | mutex_unlock(&queue->mutex); | ||
411 | return ret; | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * Cancel the video buffers queue. | ||
416 | * | ||
417 | * Cancelling the queue marks all buffers on the irq queue as erroneous, | ||
418 | * wakes them up and remove them from the queue. | ||
419 | * | ||
420 | * If the disconnect parameter is set, further calls to uvc_queue_buffer will | ||
421 | * fail with -ENODEV. | ||
422 | * | ||
423 | * This function acquires the irq spinlock and can be called from interrupt | ||
424 | * context. | ||
425 | */ | ||
426 | void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect) | ||
427 | { | ||
428 | struct uvc_buffer *buf; | ||
429 | unsigned long flags; | ||
430 | |||
431 | spin_lock_irqsave(&queue->irqlock, flags); | ||
432 | while (!list_empty(&queue->irqqueue)) { | ||
433 | buf = list_first_entry(&queue->irqqueue, struct uvc_buffer, | ||
434 | queue); | ||
435 | list_del(&buf->queue); | ||
436 | buf->state = UVC_BUF_STATE_ERROR; | ||
437 | wake_up(&buf->wait); | ||
438 | } | ||
439 | /* This must be protected by the irqlock spinlock to avoid race | ||
440 | * conditions between uvc_queue_buffer and the disconnection event that | ||
441 | * could result in an interruptible wait in uvc_dequeue_buffer. Do not | ||
442 | * blindly replace this logic by checking for the UVC_DEV_DISCONNECTED | ||
443 | * state outside the queue code. | ||
444 | */ | ||
445 | if (disconnect) | ||
446 | queue->flags |= UVC_QUEUE_DISCONNECTED; | ||
447 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
448 | } | ||
449 | |||
450 | struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, | ||
451 | struct uvc_buffer *buf) | ||
452 | { | ||
453 | struct uvc_buffer *nextbuf; | ||
454 | unsigned long flags; | ||
455 | |||
456 | if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) && | ||
457 | buf->buf.length != buf->buf.bytesused) { | ||
458 | buf->state = UVC_BUF_STATE_QUEUED; | ||
459 | buf->buf.bytesused = 0; | ||
460 | return buf; | ||
461 | } | ||
462 | |||
463 | spin_lock_irqsave(&queue->irqlock, flags); | ||
464 | list_del(&buf->queue); | ||
465 | if (!list_empty(&queue->irqqueue)) | ||
466 | nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, | ||
467 | queue); | ||
468 | else | ||
469 | nextbuf = NULL; | ||
470 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
471 | |||
472 | buf->buf.sequence = queue->sequence++; | ||
473 | do_gettimeofday(&buf->buf.timestamp); | ||
474 | |||
475 | wake_up(&buf->wait); | ||
476 | return nextbuf; | ||
477 | } | ||
diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c new file mode 100644 index 000000000000..be9084e5eace --- /dev/null +++ b/drivers/media/video/uvc/uvc_status.c | |||
@@ -0,0 +1,207 @@ | |||
1 | /* | ||
2 | * uvc_status.c -- USB Video Class driver - Status endpoint | ||
3 | * | ||
4 | * Copyright (C) 2007-2008 | ||
5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | ||
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/version.h> | ||
16 | #include <linux/input.h> | ||
17 | #include <linux/usb.h> | ||
18 | #include <linux/usb/input.h> | ||
19 | |||
20 | #include "uvcvideo.h" | ||
21 | |||
22 | /* -------------------------------------------------------------------------- | ||
23 | * Input device | ||
24 | */ | ||
25 | static int uvc_input_init(struct uvc_device *dev) | ||
26 | { | ||
27 | struct usb_device *udev = dev->udev; | ||
28 | struct input_dev *input; | ||
29 | char *phys = NULL; | ||
30 | int ret; | ||
31 | |||
32 | input = input_allocate_device(); | ||
33 | if (input == NULL) | ||
34 | return -ENOMEM; | ||
35 | |||
36 | phys = kmalloc(6 + strlen(udev->bus->bus_name) + strlen(udev->devpath), | ||
37 | GFP_KERNEL); | ||
38 | if (phys == NULL) { | ||
39 | ret = -ENOMEM; | ||
40 | goto error; | ||
41 | } | ||
42 | sprintf(phys, "usb-%s-%s", udev->bus->bus_name, udev->devpath); | ||
43 | |||
44 | input->name = dev->name; | ||
45 | input->phys = phys; | ||
46 | usb_to_input_id(udev, &input->id); | ||
47 | input->dev.parent = &dev->intf->dev; | ||
48 | |||
49 | set_bit(EV_KEY, input->evbit); | ||
50 | set_bit(BTN_0, input->keybit); | ||
51 | |||
52 | if ((ret = input_register_device(input)) < 0) | ||
53 | goto error; | ||
54 | |||
55 | dev->input = input; | ||
56 | return 0; | ||
57 | |||
58 | error: | ||
59 | input_free_device(input); | ||
60 | kfree(phys); | ||
61 | return ret; | ||
62 | } | ||
63 | |||
64 | static void uvc_input_cleanup(struct uvc_device *dev) | ||
65 | { | ||
66 | if (dev->input) | ||
67 | input_unregister_device(dev->input); | ||
68 | } | ||
69 | |||
70 | /* -------------------------------------------------------------------------- | ||
71 | * Status interrupt endpoint | ||
72 | */ | ||
73 | static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len) | ||
74 | { | ||
75 | if (len < 3) { | ||
76 | uvc_trace(UVC_TRACE_STATUS, "Invalid streaming status event " | ||
77 | "received.\n"); | ||
78 | return; | ||
79 | } | ||
80 | |||
81 | if (data[2] == 0) { | ||
82 | if (len < 4) | ||
83 | return; | ||
84 | uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n", | ||
85 | data[1], data[3] ? "pressed" : "released", len); | ||
86 | if (dev->input) | ||
87 | input_report_key(dev->input, BTN_0, data[3]); | ||
88 | } else { | ||
89 | uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x " | ||
90 | "len %d.\n", data[1], data[2], data[3], len); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | static void uvc_event_control(struct uvc_device *dev, __u8 *data, int len) | ||
95 | { | ||
96 | char *attrs[3] = { "value", "info", "failure" }; | ||
97 | |||
98 | if (len < 6 || data[2] != 0 || data[4] > 2) { | ||
99 | uvc_trace(UVC_TRACE_STATUS, "Invalid control status event " | ||
100 | "received.\n"); | ||
101 | return; | ||
102 | } | ||
103 | |||
104 | uvc_trace(UVC_TRACE_STATUS, "Control %u/%u %s change len %d.\n", | ||
105 | data[1], data[3], attrs[data[4]], len); | ||
106 | } | ||
107 | |||
108 | static void uvc_status_complete(struct urb *urb) | ||
109 | { | ||
110 | struct uvc_device *dev = urb->context; | ||
111 | int len, ret; | ||
112 | |||
113 | switch (urb->status) { | ||
114 | case 0: | ||
115 | break; | ||
116 | |||
117 | case -ENOENT: /* usb_kill_urb() called. */ | ||
118 | case -ECONNRESET: /* usb_unlink_urb() called. */ | ||
119 | case -ESHUTDOWN: /* The endpoint is being disabled. */ | ||
120 | case -EPROTO: /* Device is disconnected (reported by some | ||
121 | * host controller). */ | ||
122 | return; | ||
123 | |||
124 | default: | ||
125 | uvc_printk(KERN_WARNING, "Non-zero status (%d) in status " | ||
126 | "completion handler.\n", urb->status); | ||
127 | return; | ||
128 | } | ||
129 | |||
130 | len = urb->actual_length; | ||
131 | if (len > 0) { | ||
132 | switch (dev->status[0] & 0x0f) { | ||
133 | case UVC_STATUS_TYPE_CONTROL: | ||
134 | uvc_event_control(dev, dev->status, len); | ||
135 | break; | ||
136 | |||
137 | case UVC_STATUS_TYPE_STREAMING: | ||
138 | uvc_event_streaming(dev, dev->status, len); | ||
139 | break; | ||
140 | |||
141 | default: | ||
142 | uvc_printk(KERN_INFO, "unknown event type %u.\n", | ||
143 | dev->status[0]); | ||
144 | break; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | /* Resubmit the URB. */ | ||
149 | urb->interval = dev->int_ep->desc.bInterval; | ||
150 | if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { | ||
151 | uvc_printk(KERN_ERR, "Failed to resubmit status URB (%d).\n", | ||
152 | ret); | ||
153 | } | ||
154 | } | ||
155 | |||
156 | int uvc_status_init(struct uvc_device *dev) | ||
157 | { | ||
158 | struct usb_host_endpoint *ep = dev->int_ep; | ||
159 | unsigned int pipe; | ||
160 | int interval; | ||
161 | |||
162 | if (ep == NULL) | ||
163 | return 0; | ||
164 | |||
165 | uvc_input_init(dev); | ||
166 | |||
167 | dev->int_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
168 | if (dev->int_urb == NULL) | ||
169 | return -ENOMEM; | ||
170 | |||
171 | pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); | ||
172 | |||
173 | /* For high-speed interrupt endpoints, the bInterval value is used as | ||
174 | * an exponent of two. Some developers forgot about it. | ||
175 | */ | ||
176 | interval = ep->desc.bInterval; | ||
177 | if (interval > 16 && dev->udev->speed == USB_SPEED_HIGH && | ||
178 | (dev->quirks & UVC_QUIRK_STATUS_INTERVAL)) | ||
179 | interval = fls(interval) - 1; | ||
180 | |||
181 | usb_fill_int_urb(dev->int_urb, dev->udev, pipe, | ||
182 | dev->status, sizeof dev->status, uvc_status_complete, | ||
183 | dev, interval); | ||
184 | |||
185 | return usb_submit_urb(dev->int_urb, GFP_KERNEL); | ||
186 | } | ||
187 | |||
188 | void uvc_status_cleanup(struct uvc_device *dev) | ||
189 | { | ||
190 | usb_kill_urb(dev->int_urb); | ||
191 | usb_free_urb(dev->int_urb); | ||
192 | uvc_input_cleanup(dev); | ||
193 | } | ||
194 | |||
195 | int uvc_status_suspend(struct uvc_device *dev) | ||
196 | { | ||
197 | usb_kill_urb(dev->int_urb); | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | int uvc_status_resume(struct uvc_device *dev) | ||
202 | { | ||
203 | if (dev->int_urb == NULL) | ||
204 | return 0; | ||
205 | |||
206 | return usb_submit_urb(dev->int_urb, GFP_KERNEL); | ||
207 | } | ||
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c new file mode 100644 index 000000000000..2e0a66575bb4 --- /dev/null +++ b/drivers/media/video/uvc/uvc_v4l2.c | |||
@@ -0,0 +1,1105 @@ | |||
1 | /* | ||
2 | * uvc_v4l2.c -- USB Video Class driver - V4L2 API | ||
3 | * | ||
4 | * Copyright (C) 2005-2008 | ||
5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | ||
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/version.h> | ||
16 | #include <linux/list.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/usb.h> | ||
19 | #include <linux/videodev2.h> | ||
20 | #include <linux/vmalloc.h> | ||
21 | #include <linux/mm.h> | ||
22 | #include <linux/wait.h> | ||
23 | #include <asm/atomic.h> | ||
24 | |||
25 | #include <media/v4l2-common.h> | ||
26 | |||
27 | #include "uvcvideo.h" | ||
28 | |||
29 | /* ------------------------------------------------------------------------ | ||
30 | * V4L2 interface | ||
31 | */ | ||
32 | |||
33 | /* | ||
34 | * Mapping V4L2 controls to UVC controls can be straighforward if done well. | ||
35 | * Most of the UVC controls exist in V4L2, and can be mapped directly. Some | ||
36 | * must be grouped (for instance the Red Balance, Blue Balance and Do White | ||
37 | * Balance V4L2 controls use the White Balance Component UVC control) or | ||
38 | * otherwise translated. The approach we take here is to use a translation | ||
39 | * table for the controls which can be mapped directly, and handle the others | ||
40 | * manually. | ||
41 | */ | ||
42 | static int uvc_v4l2_query_menu(struct uvc_video_device *video, | ||
43 | struct v4l2_querymenu *query_menu) | ||
44 | { | ||
45 | struct uvc_menu_info *menu_info; | ||
46 | struct uvc_control_mapping *mapping; | ||
47 | struct uvc_control *ctrl; | ||
48 | |||
49 | ctrl = uvc_find_control(video, query_menu->id, &mapping); | ||
50 | if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) | ||
51 | return -EINVAL; | ||
52 | |||
53 | if (query_menu->index >= mapping->menu_count) | ||
54 | return -EINVAL; | ||
55 | |||
56 | menu_info = &mapping->menu_info[query_menu->index]; | ||
57 | strncpy(query_menu->name, menu_info->name, 32); | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Find the frame interval closest to the requested frame interval for the | ||
63 | * given frame format and size. This should be done by the device as part of | ||
64 | * the Video Probe and Commit negotiation, but some hardware don't implement | ||
65 | * that feature. | ||
66 | */ | ||
67 | static __u32 uvc_try_frame_interval(struct uvc_frame *frame, __u32 interval) | ||
68 | { | ||
69 | unsigned int i; | ||
70 | |||
71 | if (frame->bFrameIntervalType) { | ||
72 | __u32 best = -1, dist; | ||
73 | |||
74 | for (i = 0; i < frame->bFrameIntervalType; ++i) { | ||
75 | dist = interval > frame->dwFrameInterval[i] | ||
76 | ? interval - frame->dwFrameInterval[i] | ||
77 | : frame->dwFrameInterval[i] - interval; | ||
78 | |||
79 | if (dist > best) | ||
80 | break; | ||
81 | |||
82 | best = dist; | ||
83 | } | ||
84 | |||
85 | interval = frame->dwFrameInterval[i-1]; | ||
86 | } else { | ||
87 | const __u32 min = frame->dwFrameInterval[0]; | ||
88 | const __u32 max = frame->dwFrameInterval[1]; | ||
89 | const __u32 step = frame->dwFrameInterval[2]; | ||
90 | |||
91 | interval = min + (interval - min + step/2) / step * step; | ||
92 | if (interval > max) | ||
93 | interval = max; | ||
94 | } | ||
95 | |||
96 | return interval; | ||
97 | } | ||
98 | |||
99 | static int uvc_v4l2_try_format(struct uvc_video_device *video, | ||
100 | struct v4l2_format *fmt, struct uvc_streaming_control *probe, | ||
101 | struct uvc_format **uvc_format, struct uvc_frame **uvc_frame) | ||
102 | { | ||
103 | struct uvc_format *format = NULL; | ||
104 | struct uvc_frame *frame = NULL; | ||
105 | __u16 rw, rh; | ||
106 | unsigned int d, maxd; | ||
107 | unsigned int i; | ||
108 | __u32 interval; | ||
109 | int ret = 0; | ||
110 | __u8 *fcc; | ||
111 | |||
112 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
113 | return -EINVAL; | ||
114 | |||
115 | fcc = (__u8 *)&fmt->fmt.pix.pixelformat; | ||
116 | uvc_trace(UVC_TRACE_FORMAT, "Trying format 0x%08x (%c%c%c%c): %ux%u.\n", | ||
117 | fmt->fmt.pix.pixelformat, | ||
118 | fcc[0], fcc[1], fcc[2], fcc[3], | ||
119 | fmt->fmt.pix.width, fmt->fmt.pix.height); | ||
120 | |||
121 | /* Check if the hardware supports the requested format. */ | ||
122 | for (i = 0; i < video->streaming->nformats; ++i) { | ||
123 | format = &video->streaming->format[i]; | ||
124 | if (format->fcc == fmt->fmt.pix.pixelformat) | ||
125 | break; | ||
126 | } | ||
127 | |||
128 | if (format == NULL || format->fcc != fmt->fmt.pix.pixelformat) { | ||
129 | uvc_trace(UVC_TRACE_FORMAT, "Unsupported format 0x%08x.\n", | ||
130 | fmt->fmt.pix.pixelformat); | ||
131 | return -EINVAL; | ||
132 | } | ||
133 | |||
134 | /* Find the closest image size. The distance between image sizes is | ||
135 | * the size in pixels of the non-overlapping regions between the | ||
136 | * requested size and the frame-specified size. | ||
137 | */ | ||
138 | rw = fmt->fmt.pix.width; | ||
139 | rh = fmt->fmt.pix.height; | ||
140 | maxd = (unsigned int)-1; | ||
141 | |||
142 | for (i = 0; i < format->nframes; ++i) { | ||
143 | __u16 w = format->frame[i].wWidth; | ||
144 | __u16 h = format->frame[i].wHeight; | ||
145 | |||
146 | d = min(w, rw) * min(h, rh); | ||
147 | d = w*h + rw*rh - 2*d; | ||
148 | if (d < maxd) { | ||
149 | maxd = d; | ||
150 | frame = &format->frame[i]; | ||
151 | } | ||
152 | |||
153 | if (maxd == 0) | ||
154 | break; | ||
155 | } | ||
156 | |||
157 | if (frame == NULL) { | ||
158 | uvc_trace(UVC_TRACE_FORMAT, "Unsupported size %ux%u.\n", | ||
159 | fmt->fmt.pix.width, fmt->fmt.pix.height); | ||
160 | return -EINVAL; | ||
161 | } | ||
162 | |||
163 | /* Use the default frame interval. */ | ||
164 | interval = frame->dwDefaultFrameInterval; | ||
165 | uvc_trace(UVC_TRACE_FORMAT, "Using default frame interval %u.%u us " | ||
166 | "(%u.%u fps).\n", interval/10, interval%10, 10000000/interval, | ||
167 | (100000000/interval)%10); | ||
168 | |||
169 | /* Set the format index, frame index and frame interval. */ | ||
170 | memset(probe, 0, sizeof *probe); | ||
171 | probe->bmHint = 1; /* dwFrameInterval */ | ||
172 | probe->bFormatIndex = format->index; | ||
173 | probe->bFrameIndex = frame->bFrameIndex; | ||
174 | probe->dwFrameInterval = uvc_try_frame_interval(frame, interval); | ||
175 | /* Some webcams stall the probe control set request when the | ||
176 | * dwMaxVideoFrameSize field is set to zero. The UVC specification | ||
177 | * clearly states that the field is read-only from the host, so this | ||
178 | * is a webcam bug. Set dwMaxVideoFrameSize to the value reported by | ||
179 | * the webcam to work around the problem. | ||
180 | * | ||
181 | * The workaround could probably be enabled for all webcams, so the | ||
182 | * quirk can be removed if needed. It's currently useful to detect | ||
183 | * webcam bugs and fix them before they hit the market (providing | ||
184 | * developers test their webcams with the Linux driver as well as with | ||
185 | * the Windows driver). | ||
186 | */ | ||
187 | if (video->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS) | ||
188 | probe->dwMaxVideoFrameSize = | ||
189 | video->streaming->ctrl.dwMaxVideoFrameSize; | ||
190 | |||
191 | /* Probe the device */ | ||
192 | if ((ret = uvc_probe_video(video, probe)) < 0) | ||
193 | goto done; | ||
194 | |||
195 | fmt->fmt.pix.width = frame->wWidth; | ||
196 | fmt->fmt.pix.height = frame->wHeight; | ||
197 | fmt->fmt.pix.field = V4L2_FIELD_NONE; | ||
198 | fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8; | ||
199 | fmt->fmt.pix.sizeimage = probe->dwMaxVideoFrameSize; | ||
200 | fmt->fmt.pix.colorspace = format->colorspace; | ||
201 | fmt->fmt.pix.priv = 0; | ||
202 | |||
203 | if (uvc_format != NULL) | ||
204 | *uvc_format = format; | ||
205 | if (uvc_frame != NULL) | ||
206 | *uvc_frame = frame; | ||
207 | |||
208 | done: | ||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | static int uvc_v4l2_get_format(struct uvc_video_device *video, | ||
213 | struct v4l2_format *fmt) | ||
214 | { | ||
215 | struct uvc_format *format = video->streaming->cur_format; | ||
216 | struct uvc_frame *frame = video->streaming->cur_frame; | ||
217 | |||
218 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
219 | return -EINVAL; | ||
220 | |||
221 | if (format == NULL || frame == NULL) | ||
222 | return -EINVAL; | ||
223 | |||
224 | fmt->fmt.pix.pixelformat = format->fcc; | ||
225 | fmt->fmt.pix.width = frame->wWidth; | ||
226 | fmt->fmt.pix.height = frame->wHeight; | ||
227 | fmt->fmt.pix.field = V4L2_FIELD_NONE; | ||
228 | fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8; | ||
229 | fmt->fmt.pix.sizeimage = video->streaming->ctrl.dwMaxVideoFrameSize; | ||
230 | fmt->fmt.pix.colorspace = format->colorspace; | ||
231 | fmt->fmt.pix.priv = 0; | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static int uvc_v4l2_set_format(struct uvc_video_device *video, | ||
237 | struct v4l2_format *fmt) | ||
238 | { | ||
239 | struct uvc_streaming_control probe; | ||
240 | struct uvc_format *format; | ||
241 | struct uvc_frame *frame; | ||
242 | int ret; | ||
243 | |||
244 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
245 | return -EINVAL; | ||
246 | |||
247 | if (uvc_queue_streaming(&video->queue)) | ||
248 | return -EBUSY; | ||
249 | |||
250 | ret = uvc_v4l2_try_format(video, fmt, &probe, &format, &frame); | ||
251 | if (ret < 0) | ||
252 | return ret; | ||
253 | |||
254 | if ((ret = uvc_set_video_ctrl(video, &probe, 0)) < 0) | ||
255 | return ret; | ||
256 | |||
257 | memcpy(&video->streaming->ctrl, &probe, sizeof probe); | ||
258 | video->streaming->cur_format = format; | ||
259 | video->streaming->cur_frame = frame; | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static int uvc_v4l2_get_streamparm(struct uvc_video_device *video, | ||
265 | struct v4l2_streamparm *parm) | ||
266 | { | ||
267 | uint32_t numerator, denominator; | ||
268 | |||
269 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
270 | return -EINVAL; | ||
271 | |||
272 | numerator = video->streaming->ctrl.dwFrameInterval; | ||
273 | denominator = 10000000; | ||
274 | uvc_simplify_fraction(&numerator, &denominator, 8, 333); | ||
275 | |||
276 | memset(parm, 0, sizeof *parm); | ||
277 | parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
278 | parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; | ||
279 | parm->parm.capture.capturemode = 0; | ||
280 | parm->parm.capture.timeperframe.numerator = numerator; | ||
281 | parm->parm.capture.timeperframe.denominator = denominator; | ||
282 | parm->parm.capture.extendedmode = 0; | ||
283 | parm->parm.capture.readbuffers = 0; | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static int uvc_v4l2_set_streamparm(struct uvc_video_device *video, | ||
289 | struct v4l2_streamparm *parm) | ||
290 | { | ||
291 | struct uvc_frame *frame = video->streaming->cur_frame; | ||
292 | struct uvc_streaming_control probe; | ||
293 | uint32_t interval; | ||
294 | int ret; | ||
295 | |||
296 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
297 | return -EINVAL; | ||
298 | |||
299 | if (uvc_queue_streaming(&video->queue)) | ||
300 | return -EBUSY; | ||
301 | |||
302 | memcpy(&probe, &video->streaming->ctrl, sizeof probe); | ||
303 | interval = uvc_fraction_to_interval( | ||
304 | parm->parm.capture.timeperframe.numerator, | ||
305 | parm->parm.capture.timeperframe.denominator); | ||
306 | |||
307 | uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n", | ||
308 | parm->parm.capture.timeperframe.numerator, | ||
309 | parm->parm.capture.timeperframe.denominator, | ||
310 | interval); | ||
311 | probe.dwFrameInterval = uvc_try_frame_interval(frame, interval); | ||
312 | |||
313 | /* Probe the device with the new settings. */ | ||
314 | if ((ret = uvc_probe_video(video, &probe)) < 0) | ||
315 | return ret; | ||
316 | |||
317 | /* Commit the new settings. */ | ||
318 | if ((ret = uvc_set_video_ctrl(video, &probe, 0)) < 0) | ||
319 | return ret; | ||
320 | |||
321 | memcpy(&video->streaming->ctrl, &probe, sizeof probe); | ||
322 | |||
323 | /* Return the actual frame period. */ | ||
324 | parm->parm.capture.timeperframe.numerator = probe.dwFrameInterval; | ||
325 | parm->parm.capture.timeperframe.denominator = 10000000; | ||
326 | uvc_simplify_fraction(&parm->parm.capture.timeperframe.numerator, | ||
327 | &parm->parm.capture.timeperframe.denominator, | ||
328 | 8, 333); | ||
329 | |||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | /* ------------------------------------------------------------------------ | ||
334 | * Privilege management | ||
335 | */ | ||
336 | |||
337 | /* | ||
338 | * Privilege management is the multiple-open implementation basis. The current | ||
339 | * implementation is completely transparent for the end-user and doesn't | ||
340 | * require explicit use of the VIDIOC_G_PRIORITY and VIDIOC_S_PRIORITY ioctls. | ||
341 | * Those ioctls enable finer control on the device (by making possible for a | ||
342 | * user to request exclusive access to a device), but are not mature yet. | ||
343 | * Switching to the V4L2 priority mechanism might be considered in the future | ||
344 | * if this situation changes. | ||
345 | * | ||
346 | * Each open instance of a UVC device can either be in a privileged or | ||
347 | * unprivileged state. Only a single instance can be in a privileged state at | ||
348 | * a given time. Trying to perform an operation which requires privileges will | ||
349 | * automatically acquire the required privileges if possible, or return -EBUSY | ||
350 | * otherwise. Privileges are dismissed when closing the instance. | ||
351 | * | ||
352 | * Operations which require privileges are: | ||
353 | * | ||
354 | * - VIDIOC_S_INPUT | ||
355 | * - VIDIOC_S_PARM | ||
356 | * - VIDIOC_S_FMT | ||
357 | * - VIDIOC_TRY_FMT | ||
358 | * - VIDIOC_REQBUFS | ||
359 | */ | ||
360 | static int uvc_acquire_privileges(struct uvc_fh *handle) | ||
361 | { | ||
362 | int ret = 0; | ||
363 | |||
364 | /* Always succeed if the handle is already privileged. */ | ||
365 | if (handle->state == UVC_HANDLE_ACTIVE) | ||
366 | return 0; | ||
367 | |||
368 | /* Check if the device already has a privileged handle. */ | ||
369 | mutex_lock(&uvc_driver.open_mutex); | ||
370 | if (atomic_inc_return(&handle->device->active) != 1) { | ||
371 | atomic_dec(&handle->device->active); | ||
372 | ret = -EBUSY; | ||
373 | goto done; | ||
374 | } | ||
375 | |||
376 | handle->state = UVC_HANDLE_ACTIVE; | ||
377 | |||
378 | done: | ||
379 | mutex_unlock(&uvc_driver.open_mutex); | ||
380 | return ret; | ||
381 | } | ||
382 | |||
383 | static void uvc_dismiss_privileges(struct uvc_fh *handle) | ||
384 | { | ||
385 | if (handle->state == UVC_HANDLE_ACTIVE) | ||
386 | atomic_dec(&handle->device->active); | ||
387 | |||
388 | handle->state = UVC_HANDLE_PASSIVE; | ||
389 | } | ||
390 | |||
391 | static int uvc_has_privileges(struct uvc_fh *handle) | ||
392 | { | ||
393 | return handle->state == UVC_HANDLE_ACTIVE; | ||
394 | } | ||
395 | |||
396 | /* ------------------------------------------------------------------------ | ||
397 | * V4L2 file operations | ||
398 | */ | ||
399 | |||
400 | static int uvc_v4l2_open(struct inode *inode, struct file *file) | ||
401 | { | ||
402 | struct video_device *vdev; | ||
403 | struct uvc_video_device *video; | ||
404 | struct uvc_fh *handle; | ||
405 | int ret = 0; | ||
406 | |||
407 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n"); | ||
408 | mutex_lock(&uvc_driver.open_mutex); | ||
409 | vdev = video_devdata(file); | ||
410 | video = video_get_drvdata(vdev); | ||
411 | |||
412 | if (video->dev->state & UVC_DEV_DISCONNECTED) { | ||
413 | ret = -ENODEV; | ||
414 | goto done; | ||
415 | } | ||
416 | |||
417 | ret = usb_autopm_get_interface(video->dev->intf); | ||
418 | if (ret < 0) | ||
419 | goto done; | ||
420 | |||
421 | /* Create the device handle. */ | ||
422 | handle = kzalloc(sizeof *handle, GFP_KERNEL); | ||
423 | if (handle == NULL) { | ||
424 | usb_autopm_put_interface(video->dev->intf); | ||
425 | ret = -ENOMEM; | ||
426 | goto done; | ||
427 | } | ||
428 | |||
429 | handle->device = video; | ||
430 | handle->state = UVC_HANDLE_PASSIVE; | ||
431 | file->private_data = handle; | ||
432 | |||
433 | kref_get(&video->dev->kref); | ||
434 | |||
435 | done: | ||
436 | mutex_unlock(&uvc_driver.open_mutex); | ||
437 | return ret; | ||
438 | } | ||
439 | |||
440 | static int uvc_v4l2_release(struct inode *inode, struct file *file) | ||
441 | { | ||
442 | struct video_device *vdev = video_devdata(file); | ||
443 | struct uvc_video_device *video = video_get_drvdata(vdev); | ||
444 | struct uvc_fh *handle = (struct uvc_fh *)file->private_data; | ||
445 | |||
446 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n"); | ||
447 | |||
448 | /* Only free resources if this is a privileged handle. */ | ||
449 | if (uvc_has_privileges(handle)) { | ||
450 | uvc_video_enable(video, 0); | ||
451 | |||
452 | mutex_lock(&video->queue.mutex); | ||
453 | if (uvc_free_buffers(&video->queue) < 0) | ||
454 | uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to " | ||
455 | "free buffers.\n"); | ||
456 | mutex_unlock(&video->queue.mutex); | ||
457 | } | ||
458 | |||
459 | /* Release the file handle. */ | ||
460 | uvc_dismiss_privileges(handle); | ||
461 | kfree(handle); | ||
462 | file->private_data = NULL; | ||
463 | |||
464 | usb_autopm_put_interface(video->dev->intf); | ||
465 | kref_put(&video->dev->kref, uvc_delete); | ||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file, | ||
470 | unsigned int cmd, void *arg) | ||
471 | { | ||
472 | struct video_device *vdev = video_devdata(file); | ||
473 | struct uvc_video_device *video = video_get_drvdata(vdev); | ||
474 | struct uvc_fh *handle = (struct uvc_fh *)file->private_data; | ||
475 | int ret = 0; | ||
476 | |||
477 | if (uvc_trace_param & UVC_TRACE_IOCTL) | ||
478 | v4l_printk_ioctl(cmd); | ||
479 | |||
480 | switch (cmd) { | ||
481 | /* Query capabilities */ | ||
482 | case VIDIOC_QUERYCAP: | ||
483 | { | ||
484 | struct v4l2_capability *cap = arg; | ||
485 | |||
486 | memset(cap, 0, sizeof *cap); | ||
487 | strncpy(cap->driver, "uvcvideo", sizeof cap->driver); | ||
488 | strncpy(cap->card, vdev->name, 32); | ||
489 | strncpy(cap->bus_info, video->dev->udev->bus->bus_name, | ||
490 | sizeof cap->bus_info); | ||
491 | cap->version = DRIVER_VERSION_NUMBER; | ||
492 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | ||
493 | | V4L2_CAP_STREAMING; | ||
494 | break; | ||
495 | } | ||
496 | |||
497 | /* Get, Set & Query control */ | ||
498 | case VIDIOC_QUERYCTRL: | ||
499 | return uvc_query_v4l2_ctrl(video, arg); | ||
500 | |||
501 | case VIDIOC_G_CTRL: | ||
502 | { | ||
503 | struct v4l2_control *ctrl = arg; | ||
504 | struct v4l2_ext_control xctrl; | ||
505 | |||
506 | memset(&xctrl, 0, sizeof xctrl); | ||
507 | xctrl.id = ctrl->id; | ||
508 | |||
509 | uvc_ctrl_begin(video); | ||
510 | ret = uvc_ctrl_get(video, &xctrl); | ||
511 | uvc_ctrl_rollback(video); | ||
512 | if (ret >= 0) | ||
513 | ctrl->value = xctrl.value; | ||
514 | break; | ||
515 | } | ||
516 | |||
517 | case VIDIOC_S_CTRL: | ||
518 | { | ||
519 | struct v4l2_control *ctrl = arg; | ||
520 | struct v4l2_ext_control xctrl; | ||
521 | |||
522 | memset(&xctrl, 0, sizeof xctrl); | ||
523 | xctrl.id = ctrl->id; | ||
524 | xctrl.value = ctrl->value; | ||
525 | |||
526 | uvc_ctrl_begin(video); | ||
527 | ret = uvc_ctrl_set(video, &xctrl); | ||
528 | if (ret < 0) { | ||
529 | uvc_ctrl_rollback(video); | ||
530 | return ret; | ||
531 | } | ||
532 | ret = uvc_ctrl_commit(video); | ||
533 | break; | ||
534 | } | ||
535 | |||
536 | case VIDIOC_QUERYMENU: | ||
537 | return uvc_v4l2_query_menu(video, arg); | ||
538 | |||
539 | case VIDIOC_G_EXT_CTRLS: | ||
540 | { | ||
541 | struct v4l2_ext_controls *ctrls = arg; | ||
542 | struct v4l2_ext_control *ctrl = ctrls->controls; | ||
543 | unsigned int i; | ||
544 | |||
545 | uvc_ctrl_begin(video); | ||
546 | for (i = 0; i < ctrls->count; ++ctrl, ++i) { | ||
547 | ret = uvc_ctrl_get(video, ctrl); | ||
548 | if (ret < 0) { | ||
549 | uvc_ctrl_rollback(video); | ||
550 | ctrls->error_idx = i; | ||
551 | return ret; | ||
552 | } | ||
553 | } | ||
554 | ctrls->error_idx = 0; | ||
555 | ret = uvc_ctrl_rollback(video); | ||
556 | break; | ||
557 | } | ||
558 | |||
559 | case VIDIOC_S_EXT_CTRLS: | ||
560 | case VIDIOC_TRY_EXT_CTRLS: | ||
561 | { | ||
562 | struct v4l2_ext_controls *ctrls = arg; | ||
563 | struct v4l2_ext_control *ctrl = ctrls->controls; | ||
564 | unsigned int i; | ||
565 | |||
566 | ret = uvc_ctrl_begin(video); | ||
567 | if (ret < 0) | ||
568 | return ret; | ||
569 | |||
570 | for (i = 0; i < ctrls->count; ++ctrl, ++i) { | ||
571 | ret = uvc_ctrl_set(video, ctrl); | ||
572 | if (ret < 0) { | ||
573 | uvc_ctrl_rollback(video); | ||
574 | ctrls->error_idx = i; | ||
575 | return ret; | ||
576 | } | ||
577 | } | ||
578 | |||
579 | ctrls->error_idx = 0; | ||
580 | |||
581 | if (cmd == VIDIOC_S_EXT_CTRLS) | ||
582 | ret = uvc_ctrl_commit(video); | ||
583 | else | ||
584 | ret = uvc_ctrl_rollback(video); | ||
585 | break; | ||
586 | } | ||
587 | |||
588 | /* Get, Set & Enum input */ | ||
589 | case VIDIOC_ENUMINPUT: | ||
590 | { | ||
591 | const struct uvc_entity *selector = video->selector; | ||
592 | struct v4l2_input *input = arg; | ||
593 | struct uvc_entity *iterm = NULL; | ||
594 | u32 index = input->index; | ||
595 | int pin = 0; | ||
596 | |||
597 | if (selector == NULL || | ||
598 | (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { | ||
599 | if (index != 0) | ||
600 | return -EINVAL; | ||
601 | iterm = list_first_entry(&video->iterms, | ||
602 | struct uvc_entity, chain); | ||
603 | pin = iterm->id; | ||
604 | } else if (pin < selector->selector.bNrInPins) { | ||
605 | pin = selector->selector.baSourceID[index]; | ||
606 | list_for_each_entry(iterm, video->iterms.next, chain) { | ||
607 | if (iterm->id == pin) | ||
608 | break; | ||
609 | } | ||
610 | } | ||
611 | |||
612 | if (iterm == NULL || iterm->id != pin) | ||
613 | return -EINVAL; | ||
614 | |||
615 | memset(input, 0, sizeof *input); | ||
616 | input->index = index; | ||
617 | strncpy(input->name, iterm->name, sizeof input->name); | ||
618 | if (UVC_ENTITY_TYPE(iterm) == ITT_CAMERA) | ||
619 | input->type = V4L2_INPUT_TYPE_CAMERA; | ||
620 | break; | ||
621 | } | ||
622 | |||
623 | case VIDIOC_G_INPUT: | ||
624 | { | ||
625 | u8 input; | ||
626 | |||
627 | if (video->selector == NULL || | ||
628 | (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { | ||
629 | *(int *)arg = 0; | ||
630 | break; | ||
631 | } | ||
632 | |||
633 | ret = uvc_query_ctrl(video->dev, GET_CUR, video->selector->id, | ||
634 | video->dev->intfnum, SU_INPUT_SELECT_CONTROL, | ||
635 | &input, 1); | ||
636 | if (ret < 0) | ||
637 | return ret; | ||
638 | |||
639 | *(int *)arg = input - 1; | ||
640 | break; | ||
641 | } | ||
642 | |||
643 | case VIDIOC_S_INPUT: | ||
644 | { | ||
645 | u8 input = *(u32 *)arg + 1; | ||
646 | |||
647 | if ((ret = uvc_acquire_privileges(handle)) < 0) | ||
648 | return ret; | ||
649 | |||
650 | if (video->selector == NULL || | ||
651 | (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { | ||
652 | if (input != 1) | ||
653 | return -EINVAL; | ||
654 | break; | ||
655 | } | ||
656 | |||
657 | if (input > video->selector->selector.bNrInPins) | ||
658 | return -EINVAL; | ||
659 | |||
660 | return uvc_query_ctrl(video->dev, SET_CUR, video->selector->id, | ||
661 | video->dev->intfnum, SU_INPUT_SELECT_CONTROL, | ||
662 | &input, 1); | ||
663 | } | ||
664 | |||
665 | /* Try, Get, Set & Enum format */ | ||
666 | case VIDIOC_ENUM_FMT: | ||
667 | { | ||
668 | struct v4l2_fmtdesc *fmt = arg; | ||
669 | struct uvc_format *format; | ||
670 | |||
671 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
672 | fmt->index >= video->streaming->nformats) | ||
673 | return -EINVAL; | ||
674 | |||
675 | format = &video->streaming->format[fmt->index]; | ||
676 | fmt->flags = 0; | ||
677 | if (format->flags & UVC_FMT_FLAG_COMPRESSED) | ||
678 | fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; | ||
679 | strncpy(fmt->description, format->name, | ||
680 | sizeof fmt->description); | ||
681 | fmt->description[sizeof fmt->description - 1] = 0; | ||
682 | fmt->pixelformat = format->fcc; | ||
683 | break; | ||
684 | } | ||
685 | |||
686 | case VIDIOC_TRY_FMT: | ||
687 | { | ||
688 | struct uvc_streaming_control probe; | ||
689 | |||
690 | if ((ret = uvc_acquire_privileges(handle)) < 0) | ||
691 | return ret; | ||
692 | |||
693 | return uvc_v4l2_try_format(video, arg, &probe, NULL, NULL); | ||
694 | } | ||
695 | |||
696 | case VIDIOC_S_FMT: | ||
697 | if ((ret = uvc_acquire_privileges(handle)) < 0) | ||
698 | return ret; | ||
699 | |||
700 | return uvc_v4l2_set_format(video, arg); | ||
701 | |||
702 | case VIDIOC_G_FMT: | ||
703 | return uvc_v4l2_get_format(video, arg); | ||
704 | |||
705 | /* Frame size enumeration */ | ||
706 | case VIDIOC_ENUM_FRAMESIZES: | ||
707 | { | ||
708 | struct v4l2_frmsizeenum *fsize = arg; | ||
709 | struct uvc_format *format = NULL; | ||
710 | struct uvc_frame *frame; | ||
711 | int i; | ||
712 | |||
713 | /* Look for the given pixel format */ | ||
714 | for (i = 0; i < video->streaming->nformats; i++) { | ||
715 | if (video->streaming->format[i].fcc == | ||
716 | fsize->pixel_format) { | ||
717 | format = &video->streaming->format[i]; | ||
718 | break; | ||
719 | } | ||
720 | } | ||
721 | if (format == NULL) | ||
722 | return -EINVAL; | ||
723 | |||
724 | if (fsize->index >= format->nframes) | ||
725 | return -EINVAL; | ||
726 | |||
727 | frame = &format->frame[fsize->index]; | ||
728 | fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; | ||
729 | fsize->discrete.width = frame->wWidth; | ||
730 | fsize->discrete.height = frame->wHeight; | ||
731 | break; | ||
732 | } | ||
733 | |||
734 | /* Frame interval enumeration */ | ||
735 | case VIDIOC_ENUM_FRAMEINTERVALS: | ||
736 | { | ||
737 | struct v4l2_frmivalenum *fival = arg; | ||
738 | struct uvc_format *format = NULL; | ||
739 | struct uvc_frame *frame = NULL; | ||
740 | int i; | ||
741 | |||
742 | /* Look for the given pixel format and frame size */ | ||
743 | for (i = 0; i < video->streaming->nformats; i++) { | ||
744 | if (video->streaming->format[i].fcc == | ||
745 | fival->pixel_format) { | ||
746 | format = &video->streaming->format[i]; | ||
747 | break; | ||
748 | } | ||
749 | } | ||
750 | if (format == NULL) | ||
751 | return -EINVAL; | ||
752 | |||
753 | for (i = 0; i < format->nframes; i++) { | ||
754 | if (format->frame[i].wWidth == fival->width && | ||
755 | format->frame[i].wHeight == fival->height) { | ||
756 | frame = &format->frame[i]; | ||
757 | break; | ||
758 | } | ||
759 | } | ||
760 | if (frame == NULL) | ||
761 | return -EINVAL; | ||
762 | |||
763 | if (frame->bFrameIntervalType) { | ||
764 | if (fival->index >= frame->bFrameIntervalType) | ||
765 | return -EINVAL; | ||
766 | |||
767 | fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; | ||
768 | fival->discrete.numerator = | ||
769 | frame->dwFrameInterval[fival->index]; | ||
770 | fival->discrete.denominator = 10000000; | ||
771 | uvc_simplify_fraction(&fival->discrete.numerator, | ||
772 | &fival->discrete.denominator, 8, 333); | ||
773 | } else { | ||
774 | fival->type = V4L2_FRMIVAL_TYPE_STEPWISE; | ||
775 | fival->stepwise.min.numerator = | ||
776 | frame->dwFrameInterval[0]; | ||
777 | fival->stepwise.min.denominator = 10000000; | ||
778 | fival->stepwise.max.numerator = | ||
779 | frame->dwFrameInterval[1]; | ||
780 | fival->stepwise.max.denominator = 10000000; | ||
781 | fival->stepwise.step.numerator = | ||
782 | frame->dwFrameInterval[2]; | ||
783 | fival->stepwise.step.denominator = 10000000; | ||
784 | uvc_simplify_fraction(&fival->stepwise.min.numerator, | ||
785 | &fival->stepwise.min.denominator, 8, 333); | ||
786 | uvc_simplify_fraction(&fival->stepwise.max.numerator, | ||
787 | &fival->stepwise.max.denominator, 8, 333); | ||
788 | uvc_simplify_fraction(&fival->stepwise.step.numerator, | ||
789 | &fival->stepwise.step.denominator, 8, 333); | ||
790 | } | ||
791 | break; | ||
792 | } | ||
793 | |||
794 | /* Get & Set streaming parameters */ | ||
795 | case VIDIOC_G_PARM: | ||
796 | return uvc_v4l2_get_streamparm(video, arg); | ||
797 | |||
798 | case VIDIOC_S_PARM: | ||
799 | if ((ret = uvc_acquire_privileges(handle)) < 0) | ||
800 | return ret; | ||
801 | |||
802 | return uvc_v4l2_set_streamparm(video, arg); | ||
803 | |||
804 | /* Cropping and scaling */ | ||
805 | case VIDIOC_CROPCAP: | ||
806 | { | ||
807 | struct v4l2_cropcap *ccap = arg; | ||
808 | struct uvc_frame *frame = video->streaming->cur_frame; | ||
809 | |||
810 | if (ccap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
811 | return -EINVAL; | ||
812 | |||
813 | ccap->bounds.left = 0; | ||
814 | ccap->bounds.top = 0; | ||
815 | ccap->bounds.width = frame->wWidth; | ||
816 | ccap->bounds.height = frame->wHeight; | ||
817 | |||
818 | ccap->defrect = ccap->bounds; | ||
819 | |||
820 | ccap->pixelaspect.numerator = 1; | ||
821 | ccap->pixelaspect.denominator = 1; | ||
822 | break; | ||
823 | } | ||
824 | |||
825 | case VIDIOC_G_CROP: | ||
826 | case VIDIOC_S_CROP: | ||
827 | return -EINVAL; | ||
828 | |||
829 | /* Buffers & streaming */ | ||
830 | case VIDIOC_REQBUFS: | ||
831 | { | ||
832 | struct v4l2_requestbuffers *rb = arg; | ||
833 | unsigned int bufsize = | ||
834 | video->streaming->ctrl.dwMaxVideoFrameSize; | ||
835 | |||
836 | if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
837 | rb->memory != V4L2_MEMORY_MMAP) | ||
838 | return -EINVAL; | ||
839 | |||
840 | if ((ret = uvc_acquire_privileges(handle)) < 0) | ||
841 | return ret; | ||
842 | |||
843 | ret = uvc_alloc_buffers(&video->queue, rb->count, bufsize); | ||
844 | if (ret < 0) | ||
845 | return ret; | ||
846 | |||
847 | if (!(video->streaming->cur_format->flags & | ||
848 | UVC_FMT_FLAG_COMPRESSED)) | ||
849 | video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; | ||
850 | |||
851 | rb->count = ret; | ||
852 | ret = 0; | ||
853 | break; | ||
854 | } | ||
855 | |||
856 | case VIDIOC_QUERYBUF: | ||
857 | { | ||
858 | struct v4l2_buffer *buf = arg; | ||
859 | |||
860 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
861 | return -EINVAL; | ||
862 | |||
863 | if (!uvc_has_privileges(handle)) | ||
864 | return -EBUSY; | ||
865 | |||
866 | return uvc_query_buffer(&video->queue, buf); | ||
867 | } | ||
868 | |||
869 | case VIDIOC_QBUF: | ||
870 | if (!uvc_has_privileges(handle)) | ||
871 | return -EBUSY; | ||
872 | |||
873 | return uvc_queue_buffer(&video->queue, arg); | ||
874 | |||
875 | case VIDIOC_DQBUF: | ||
876 | if (!uvc_has_privileges(handle)) | ||
877 | return -EBUSY; | ||
878 | |||
879 | return uvc_dequeue_buffer(&video->queue, arg, | ||
880 | file->f_flags & O_NONBLOCK); | ||
881 | |||
882 | case VIDIOC_STREAMON: | ||
883 | { | ||
884 | int *type = arg; | ||
885 | |||
886 | if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
887 | return -EINVAL; | ||
888 | |||
889 | if (!uvc_has_privileges(handle)) | ||
890 | return -EBUSY; | ||
891 | |||
892 | if ((ret = uvc_video_enable(video, 1)) < 0) | ||
893 | return ret; | ||
894 | break; | ||
895 | } | ||
896 | |||
897 | case VIDIOC_STREAMOFF: | ||
898 | { | ||
899 | int *type = arg; | ||
900 | |||
901 | if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
902 | return -EINVAL; | ||
903 | |||
904 | if (!uvc_has_privileges(handle)) | ||
905 | return -EBUSY; | ||
906 | |||
907 | return uvc_video_enable(video, 0); | ||
908 | } | ||
909 | |||
910 | /* Analog video standards make no sense for digital cameras. */ | ||
911 | case VIDIOC_ENUMSTD: | ||
912 | case VIDIOC_QUERYSTD: | ||
913 | case VIDIOC_G_STD: | ||
914 | case VIDIOC_S_STD: | ||
915 | |||
916 | case VIDIOC_OVERLAY: | ||
917 | |||
918 | case VIDIOC_ENUMAUDIO: | ||
919 | case VIDIOC_ENUMAUDOUT: | ||
920 | |||
921 | case VIDIOC_ENUMOUTPUT: | ||
922 | uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd); | ||
923 | return -EINVAL; | ||
924 | |||
925 | /* Dynamic controls. */ | ||
926 | case UVCIOC_CTRL_ADD: | ||
927 | { | ||
928 | struct uvc_xu_control_info *xinfo = arg; | ||
929 | struct uvc_control_info *info; | ||
930 | |||
931 | if (!capable(CAP_SYS_ADMIN)) | ||
932 | return -EPERM; | ||
933 | |||
934 | info = kmalloc(sizeof *info, GFP_KERNEL); | ||
935 | if (info == NULL) | ||
936 | return -ENOMEM; | ||
937 | |||
938 | memcpy(info->entity, xinfo->entity, sizeof info->entity); | ||
939 | info->index = xinfo->index; | ||
940 | info->selector = xinfo->selector; | ||
941 | info->size = xinfo->size; | ||
942 | info->flags = xinfo->flags; | ||
943 | |||
944 | info->flags |= UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | | ||
945 | UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF; | ||
946 | |||
947 | ret = uvc_ctrl_add_info(info); | ||
948 | if (ret < 0) | ||
949 | kfree(info); | ||
950 | break; | ||
951 | } | ||
952 | |||
953 | case UVCIOC_CTRL_MAP: | ||
954 | { | ||
955 | struct uvc_xu_control_mapping *xmap = arg; | ||
956 | struct uvc_control_mapping *map; | ||
957 | |||
958 | if (!capable(CAP_SYS_ADMIN)) | ||
959 | return -EPERM; | ||
960 | |||
961 | map = kmalloc(sizeof *map, GFP_KERNEL); | ||
962 | if (map == NULL) | ||
963 | return -ENOMEM; | ||
964 | |||
965 | map->id = xmap->id; | ||
966 | memcpy(map->name, xmap->name, sizeof map->name); | ||
967 | memcpy(map->entity, xmap->entity, sizeof map->entity); | ||
968 | map->selector = xmap->selector; | ||
969 | map->size = xmap->size; | ||
970 | map->offset = xmap->offset; | ||
971 | map->v4l2_type = xmap->v4l2_type; | ||
972 | map->data_type = xmap->data_type; | ||
973 | |||
974 | ret = uvc_ctrl_add_mapping(map); | ||
975 | if (ret < 0) | ||
976 | kfree(map); | ||
977 | break; | ||
978 | } | ||
979 | |||
980 | case UVCIOC_CTRL_GET: | ||
981 | return uvc_xu_ctrl_query(video, arg, 0); | ||
982 | |||
983 | case UVCIOC_CTRL_SET: | ||
984 | return uvc_xu_ctrl_query(video, arg, 1); | ||
985 | |||
986 | default: | ||
987 | if ((ret = v4l_compat_translate_ioctl(inode, file, cmd, arg, | ||
988 | uvc_v4l2_do_ioctl)) == -ENOIOCTLCMD) | ||
989 | uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", | ||
990 | cmd); | ||
991 | return ret; | ||
992 | } | ||
993 | |||
994 | return ret; | ||
995 | } | ||
996 | |||
997 | static int uvc_v4l2_ioctl(struct inode *inode, struct file *file, | ||
998 | unsigned int cmd, unsigned long arg) | ||
999 | { | ||
1000 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_ioctl\n"); | ||
1001 | return video_usercopy(inode, file, cmd, arg, uvc_v4l2_do_ioctl); | ||
1002 | } | ||
1003 | |||
1004 | static ssize_t uvc_v4l2_read(struct file *file, char __user *data, | ||
1005 | size_t count, loff_t *ppos) | ||
1006 | { | ||
1007 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_read: not implemented.\n"); | ||
1008 | return -ENODEV; | ||
1009 | } | ||
1010 | |||
1011 | /* | ||
1012 | * VMA operations. | ||
1013 | */ | ||
1014 | static void uvc_vm_open(struct vm_area_struct *vma) | ||
1015 | { | ||
1016 | struct uvc_buffer *buffer = vma->vm_private_data; | ||
1017 | buffer->vma_use_count++; | ||
1018 | } | ||
1019 | |||
1020 | static void uvc_vm_close(struct vm_area_struct *vma) | ||
1021 | { | ||
1022 | struct uvc_buffer *buffer = vma->vm_private_data; | ||
1023 | buffer->vma_use_count--; | ||
1024 | } | ||
1025 | |||
1026 | static struct vm_operations_struct uvc_vm_ops = { | ||
1027 | .open = uvc_vm_open, | ||
1028 | .close = uvc_vm_close, | ||
1029 | }; | ||
1030 | |||
1031 | static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | ||
1032 | { | ||
1033 | struct video_device *vdev = video_devdata(file); | ||
1034 | struct uvc_video_device *video = video_get_drvdata(vdev); | ||
1035 | struct uvc_buffer *buffer; | ||
1036 | struct page *page; | ||
1037 | unsigned long addr, start, size; | ||
1038 | unsigned int i; | ||
1039 | int ret = 0; | ||
1040 | |||
1041 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n"); | ||
1042 | |||
1043 | start = vma->vm_start; | ||
1044 | size = vma->vm_end - vma->vm_start; | ||
1045 | |||
1046 | mutex_lock(&video->queue.mutex); | ||
1047 | |||
1048 | for (i = 0; i < video->queue.count; ++i) { | ||
1049 | buffer = &video->queue.buffer[i]; | ||
1050 | if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) | ||
1051 | break; | ||
1052 | } | ||
1053 | |||
1054 | if (i == video->queue.count || size != video->queue.buf_size) { | ||
1055 | ret = -EINVAL; | ||
1056 | goto done; | ||
1057 | } | ||
1058 | |||
1059 | /* | ||
1060 | * VM_IO marks the area as being an mmaped region for I/O to a | ||
1061 | * device. It also prevents the region from being core dumped. | ||
1062 | */ | ||
1063 | vma->vm_flags |= VM_IO; | ||
1064 | |||
1065 | addr = (unsigned long)video->queue.mem + buffer->buf.m.offset; | ||
1066 | while (size > 0) { | ||
1067 | page = vmalloc_to_page((void *)addr); | ||
1068 | if ((ret = vm_insert_page(vma, start, page)) < 0) | ||
1069 | goto done; | ||
1070 | |||
1071 | start += PAGE_SIZE; | ||
1072 | addr += PAGE_SIZE; | ||
1073 | size -= PAGE_SIZE; | ||
1074 | } | ||
1075 | |||
1076 | vma->vm_ops = &uvc_vm_ops; | ||
1077 | vma->vm_private_data = buffer; | ||
1078 | uvc_vm_open(vma); | ||
1079 | |||
1080 | done: | ||
1081 | mutex_unlock(&video->queue.mutex); | ||
1082 | return ret; | ||
1083 | } | ||
1084 | |||
1085 | static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) | ||
1086 | { | ||
1087 | struct video_device *vdev = video_devdata(file); | ||
1088 | struct uvc_video_device *video = video_get_drvdata(vdev); | ||
1089 | |||
1090 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n"); | ||
1091 | |||
1092 | return uvc_queue_poll(&video->queue, file, wait); | ||
1093 | } | ||
1094 | |||
1095 | struct file_operations uvc_fops = { | ||
1096 | .owner = THIS_MODULE, | ||
1097 | .open = uvc_v4l2_open, | ||
1098 | .release = uvc_v4l2_release, | ||
1099 | .ioctl = uvc_v4l2_ioctl, | ||
1100 | .compat_ioctl = v4l_compat_ioctl32, | ||
1101 | .llseek = no_llseek, | ||
1102 | .read = uvc_v4l2_read, | ||
1103 | .mmap = uvc_v4l2_mmap, | ||
1104 | .poll = uvc_v4l2_poll, | ||
1105 | }; | ||
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c new file mode 100644 index 000000000000..6faf1fb21614 --- /dev/null +++ b/drivers/media/video/uvc/uvc_video.c | |||
@@ -0,0 +1,934 @@ | |||
1 | /* | ||
2 | * uvc_video.c -- USB Video Class driver - Video handling | ||
3 | * | ||
4 | * Copyright (C) 2005-2008 | ||
5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | ||
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/version.h> | ||
16 | #include <linux/list.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/usb.h> | ||
19 | #include <linux/videodev2.h> | ||
20 | #include <linux/vmalloc.h> | ||
21 | #include <linux/wait.h> | ||
22 | #include <asm/atomic.h> | ||
23 | #include <asm/unaligned.h> | ||
24 | |||
25 | #include <media/v4l2-common.h> | ||
26 | |||
27 | #include "uvcvideo.h" | ||
28 | |||
29 | /* ------------------------------------------------------------------------ | ||
30 | * UVC Controls | ||
31 | */ | ||
32 | |||
33 | static int __uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, | ||
34 | __u8 intfnum, __u8 cs, void *data, __u16 size, | ||
35 | int timeout) | ||
36 | { | ||
37 | __u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||
38 | unsigned int pipe; | ||
39 | int ret; | ||
40 | |||
41 | pipe = (query & 0x80) ? usb_rcvctrlpipe(dev->udev, 0) | ||
42 | : usb_sndctrlpipe(dev->udev, 0); | ||
43 | type |= (query & 0x80) ? USB_DIR_IN : USB_DIR_OUT; | ||
44 | |||
45 | ret = usb_control_msg(dev->udev, pipe, query, type, cs << 8, | ||
46 | unit << 8 | intfnum, data, size, timeout); | ||
47 | |||
48 | if (ret != size) { | ||
49 | uvc_printk(KERN_ERR, "Failed to query (%u) UVC control %u " | ||
50 | "(unit %u) : %d (exp. %u).\n", query, cs, unit, ret, | ||
51 | size); | ||
52 | return -EIO; | ||
53 | } | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, | ||
59 | __u8 intfnum, __u8 cs, void *data, __u16 size) | ||
60 | { | ||
61 | return __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size, | ||
62 | UVC_CTRL_CONTROL_TIMEOUT); | ||
63 | } | ||
64 | |||
65 | static void uvc_fixup_buffer_size(struct uvc_video_device *video, | ||
66 | struct uvc_streaming_control *ctrl) | ||
67 | { | ||
68 | struct uvc_format *format; | ||
69 | struct uvc_frame *frame; | ||
70 | |||
71 | if (ctrl->bFormatIndex <= 0 || | ||
72 | ctrl->bFormatIndex > video->streaming->nformats) | ||
73 | return; | ||
74 | |||
75 | format = &video->streaming->format[ctrl->bFormatIndex - 1]; | ||
76 | |||
77 | if (ctrl->bFrameIndex <= 0 || | ||
78 | ctrl->bFrameIndex > format->nframes) | ||
79 | return; | ||
80 | |||
81 | frame = &format->frame[ctrl->bFrameIndex - 1]; | ||
82 | |||
83 | if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) || | ||
84 | (ctrl->dwMaxVideoFrameSize == 0 && | ||
85 | video->dev->uvc_version < 0x0110)) | ||
86 | ctrl->dwMaxVideoFrameSize = | ||
87 | frame->dwMaxVideoFrameBufferSize; | ||
88 | } | ||
89 | |||
90 | static int uvc_get_video_ctrl(struct uvc_video_device *video, | ||
91 | struct uvc_streaming_control *ctrl, int probe, __u8 query) | ||
92 | { | ||
93 | __u8 data[34]; | ||
94 | __u8 size; | ||
95 | int ret; | ||
96 | |||
97 | size = video->dev->uvc_version >= 0x0110 ? 34 : 26; | ||
98 | ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum, | ||
99 | probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, &data, size, | ||
100 | UVC_CTRL_STREAMING_TIMEOUT); | ||
101 | |||
102 | if (ret < 0) | ||
103 | return ret; | ||
104 | |||
105 | ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]); | ||
106 | ctrl->bFormatIndex = data[2]; | ||
107 | ctrl->bFrameIndex = data[3]; | ||
108 | ctrl->dwFrameInterval = le32_to_cpup((__le32 *)&data[4]); | ||
109 | ctrl->wKeyFrameRate = le16_to_cpup((__le16 *)&data[8]); | ||
110 | ctrl->wPFrameRate = le16_to_cpup((__le16 *)&data[10]); | ||
111 | ctrl->wCompQuality = le16_to_cpup((__le16 *)&data[12]); | ||
112 | ctrl->wCompWindowSize = le16_to_cpup((__le16 *)&data[14]); | ||
113 | ctrl->wDelay = le16_to_cpup((__le16 *)&data[16]); | ||
114 | ctrl->dwMaxVideoFrameSize = | ||
115 | le32_to_cpu(get_unaligned((__le32 *)&data[18])); | ||
116 | ctrl->dwMaxPayloadTransferSize = | ||
117 | le32_to_cpu(get_unaligned((__le32 *)&data[22])); | ||
118 | |||
119 | if (size == 34) { | ||
120 | ctrl->dwClockFrequency = | ||
121 | le32_to_cpu(get_unaligned((__le32 *)&data[26])); | ||
122 | ctrl->bmFramingInfo = data[30]; | ||
123 | ctrl->bPreferedVersion = data[31]; | ||
124 | ctrl->bMinVersion = data[32]; | ||
125 | ctrl->bMaxVersion = data[33]; | ||
126 | } else { | ||
127 | ctrl->dwClockFrequency = video->dev->clock_frequency; | ||
128 | ctrl->bmFramingInfo = 0; | ||
129 | ctrl->bPreferedVersion = 0; | ||
130 | ctrl->bMinVersion = 0; | ||
131 | ctrl->bMaxVersion = 0; | ||
132 | } | ||
133 | |||
134 | /* Some broken devices return a null or wrong dwMaxVideoFrameSize. | ||
135 | * Try to get the value from the format and frame descriptor. | ||
136 | */ | ||
137 | uvc_fixup_buffer_size(video, ctrl); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | int uvc_set_video_ctrl(struct uvc_video_device *video, | ||
143 | struct uvc_streaming_control *ctrl, int probe) | ||
144 | { | ||
145 | __u8 data[34]; | ||
146 | __u8 size; | ||
147 | |||
148 | size = video->dev->uvc_version >= 0x0110 ? 34 : 26; | ||
149 | memset(data, 0, sizeof data); | ||
150 | |||
151 | *(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint); | ||
152 | data[2] = ctrl->bFormatIndex; | ||
153 | data[3] = ctrl->bFrameIndex; | ||
154 | *(__le32 *)&data[4] = cpu_to_le32(ctrl->dwFrameInterval); | ||
155 | *(__le16 *)&data[8] = cpu_to_le16(ctrl->wKeyFrameRate); | ||
156 | *(__le16 *)&data[10] = cpu_to_le16(ctrl->wPFrameRate); | ||
157 | *(__le16 *)&data[12] = cpu_to_le16(ctrl->wCompQuality); | ||
158 | *(__le16 *)&data[14] = cpu_to_le16(ctrl->wCompWindowSize); | ||
159 | *(__le16 *)&data[16] = cpu_to_le16(ctrl->wDelay); | ||
160 | /* Note: Some of the fields below are not required for IN devices (see | ||
161 | * UVC spec, 4.3.1.1), but we still copy them in case support for OUT | ||
162 | * devices is added in the future. */ | ||
163 | put_unaligned(cpu_to_le32(ctrl->dwMaxVideoFrameSize), | ||
164 | (__le32 *)&data[18]); | ||
165 | put_unaligned(cpu_to_le32(ctrl->dwMaxPayloadTransferSize), | ||
166 | (__le32 *)&data[22]); | ||
167 | |||
168 | if (size == 34) { | ||
169 | put_unaligned(cpu_to_le32(ctrl->dwClockFrequency), | ||
170 | (__le32 *)&data[26]); | ||
171 | data[30] = ctrl->bmFramingInfo; | ||
172 | data[31] = ctrl->bPreferedVersion; | ||
173 | data[32] = ctrl->bMinVersion; | ||
174 | data[33] = ctrl->bMaxVersion; | ||
175 | } | ||
176 | |||
177 | return __uvc_query_ctrl(video->dev, SET_CUR, 0, | ||
178 | video->streaming->intfnum, | ||
179 | probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, &data, size, | ||
180 | UVC_CTRL_STREAMING_TIMEOUT); | ||
181 | } | ||
182 | |||
183 | int uvc_probe_video(struct uvc_video_device *video, | ||
184 | struct uvc_streaming_control *probe) | ||
185 | { | ||
186 | struct uvc_streaming_control probe_min, probe_max; | ||
187 | __u16 bandwidth; | ||
188 | unsigned int i; | ||
189 | int ret; | ||
190 | |||
191 | mutex_lock(&video->streaming->mutex); | ||
192 | |||
193 | /* Perform probing. The device should adjust the requested values | ||
194 | * according to its capabilities. However, some devices, namely the | ||
195 | * first generation UVC Logitech webcams, don't implement the Video | ||
196 | * Probe control properly, and just return the needed bandwidth. For | ||
197 | * that reason, if the needed bandwidth exceeds the maximum available | ||
198 | * bandwidth, try to lower the quality. | ||
199 | */ | ||
200 | if ((ret = uvc_set_video_ctrl(video, probe, 1)) < 0) | ||
201 | goto done; | ||
202 | |||
203 | /* Get the minimum and maximum values for compression settings. */ | ||
204 | if (!(video->dev->quirks & UVC_QUIRK_PROBE_MINMAX)) { | ||
205 | ret = uvc_get_video_ctrl(video, &probe_min, 1, GET_MIN); | ||
206 | if (ret < 0) | ||
207 | goto done; | ||
208 | ret = uvc_get_video_ctrl(video, &probe_max, 1, GET_MAX); | ||
209 | if (ret < 0) | ||
210 | goto done; | ||
211 | |||
212 | probe->wCompQuality = probe_max.wCompQuality; | ||
213 | } | ||
214 | |||
215 | for (i = 0; i < 2; ++i) { | ||
216 | if ((ret = uvc_set_video_ctrl(video, probe, 1)) < 0 || | ||
217 | (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0) | ||
218 | goto done; | ||
219 | |||
220 | if (video->streaming->intf->num_altsetting == 1) | ||
221 | break; | ||
222 | |||
223 | bandwidth = probe->dwMaxPayloadTransferSize; | ||
224 | if (bandwidth <= video->streaming->maxpsize) | ||
225 | break; | ||
226 | |||
227 | if (video->dev->quirks & UVC_QUIRK_PROBE_MINMAX) { | ||
228 | ret = -ENOSPC; | ||
229 | goto done; | ||
230 | } | ||
231 | |||
232 | /* TODO: negotiate compression parameters */ | ||
233 | probe->wKeyFrameRate = probe_min.wKeyFrameRate; | ||
234 | probe->wPFrameRate = probe_min.wPFrameRate; | ||
235 | probe->wCompQuality = probe_max.wCompQuality; | ||
236 | probe->wCompWindowSize = probe_min.wCompWindowSize; | ||
237 | } | ||
238 | |||
239 | done: | ||
240 | mutex_unlock(&video->streaming->mutex); | ||
241 | return ret; | ||
242 | } | ||
243 | |||
244 | /* ------------------------------------------------------------------------ | ||
245 | * Video codecs | ||
246 | */ | ||
247 | |||
248 | /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ | ||
249 | #define UVC_STREAM_EOH (1 << 7) | ||
250 | #define UVC_STREAM_ERR (1 << 6) | ||
251 | #define UVC_STREAM_STI (1 << 5) | ||
252 | #define UVC_STREAM_RES (1 << 4) | ||
253 | #define UVC_STREAM_SCR (1 << 3) | ||
254 | #define UVC_STREAM_PTS (1 << 2) | ||
255 | #define UVC_STREAM_EOF (1 << 1) | ||
256 | #define UVC_STREAM_FID (1 << 0) | ||
257 | |||
258 | /* Video payload decoding is handled by uvc_video_decode_start(), | ||
259 | * uvc_video_decode_data() and uvc_video_decode_end(). | ||
260 | * | ||
261 | * uvc_video_decode_start is called with URB data at the start of a bulk or | ||
262 | * isochronous payload. It processes header data and returns the header size | ||
263 | * in bytes if successful. If an error occurs, it returns a negative error | ||
264 | * code. The following error codes have special meanings. | ||
265 | * | ||
266 | * - EAGAIN informs the caller that the current video buffer should be marked | ||
267 | * as done, and that the function should be called again with the same data | ||
268 | * and a new video buffer. This is used when end of frame conditions can be | ||
269 | * reliably detected at the beginning of the next frame only. | ||
270 | * | ||
271 | * If an error other than -EAGAIN is returned, the caller will drop the current | ||
272 | * payload. No call to uvc_video_decode_data and uvc_video_decode_end will be | ||
273 | * made until the next payload. -ENODATA can be used to drop the current | ||
274 | * payload if no other error code is appropriate. | ||
275 | * | ||
276 | * uvc_video_decode_data is called for every URB with URB data. It copies the | ||
277 | * data to the video buffer. | ||
278 | * | ||
279 | * uvc_video_decode_end is called with header data at the end of a bulk or | ||
280 | * isochronous payload. It performs any additional header data processing and | ||
281 | * returns 0 or a negative error code if an error occured. As header data have | ||
282 | * already been processed by uvc_video_decode_start, this functions isn't | ||
283 | * required to perform sanity checks a second time. | ||
284 | * | ||
285 | * For isochronous transfers where a payload is always transfered in a single | ||
286 | * URB, the three functions will be called in a row. | ||
287 | * | ||
288 | * To let the decoder process header data and update its internal state even | ||
289 | * when no video buffer is available, uvc_video_decode_start must be prepared | ||
290 | * to be called with a NULL buf parameter. uvc_video_decode_data and | ||
291 | * uvc_video_decode_end will never be called with a NULL buffer. | ||
292 | */ | ||
293 | static int uvc_video_decode_start(struct uvc_video_device *video, | ||
294 | struct uvc_buffer *buf, const __u8 *data, int len) | ||
295 | { | ||
296 | __u8 fid; | ||
297 | |||
298 | /* Sanity checks: | ||
299 | * - packet must be at least 2 bytes long | ||
300 | * - bHeaderLength value must be at least 2 bytes (see above) | ||
301 | * - bHeaderLength value can't be larger than the packet size. | ||
302 | */ | ||
303 | if (len < 2 || data[0] < 2 || data[0] > len) | ||
304 | return -EINVAL; | ||
305 | |||
306 | /* Skip payloads marked with the error bit ("error frames"). */ | ||
307 | if (data[1] & UVC_STREAM_ERR) { | ||
308 | uvc_trace(UVC_TRACE_FRAME, "Dropping payload (error bit " | ||
309 | "set).\n"); | ||
310 | return -ENODATA; | ||
311 | } | ||
312 | |||
313 | fid = data[1] & UVC_STREAM_FID; | ||
314 | |||
315 | /* Store the payload FID bit and return immediately when the buffer is | ||
316 | * NULL. | ||
317 | */ | ||
318 | if (buf == NULL) { | ||
319 | video->last_fid = fid; | ||
320 | return -ENODATA; | ||
321 | } | ||
322 | |||
323 | /* Synchronize to the input stream by waiting for the FID bit to be | ||
324 | * toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE. | ||
325 | * queue->last_fid is initialized to -1, so the first isochronous | ||
326 | * frame will always be in sync. | ||
327 | * | ||
328 | * If the device doesn't toggle the FID bit, invert video->last_fid | ||
329 | * when the EOF bit is set to force synchronisation on the next packet. | ||
330 | */ | ||
331 | if (buf->state != UVC_BUF_STATE_ACTIVE) { | ||
332 | if (fid == video->last_fid) { | ||
333 | uvc_trace(UVC_TRACE_FRAME, "Dropping payload (out of " | ||
334 | "sync).\n"); | ||
335 | if ((video->dev->quirks & UVC_QUIRK_STREAM_NO_FID) && | ||
336 | (data[1] & UVC_STREAM_EOF)) | ||
337 | video->last_fid ^= UVC_STREAM_FID; | ||
338 | return -ENODATA; | ||
339 | } | ||
340 | |||
341 | /* TODO: Handle PTS and SCR. */ | ||
342 | buf->state = UVC_BUF_STATE_ACTIVE; | ||
343 | } | ||
344 | |||
345 | /* Mark the buffer as done if we're at the beginning of a new frame. | ||
346 | * End of frame detection is better implemented by checking the EOF | ||
347 | * bit (FID bit toggling is delayed by one frame compared to the EOF | ||
348 | * bit), but some devices don't set the bit at end of frame (and the | ||
349 | * last payload can be lost anyway). We thus must check if the FID has | ||
350 | * been toggled. | ||
351 | * | ||
352 | * queue->last_fid is initialized to -1, so the first isochronous | ||
353 | * frame will never trigger an end of frame detection. | ||
354 | * | ||
355 | * Empty buffers (bytesused == 0) don't trigger end of frame detection | ||
356 | * as it doesn't make sense to return an empty buffer. This also | ||
357 | * avoids detecting and of frame conditions at FID toggling if the | ||
358 | * previous payload had the EOF bit set. | ||
359 | */ | ||
360 | if (fid != video->last_fid && buf->buf.bytesused != 0) { | ||
361 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit " | ||
362 | "toggled).\n"); | ||
363 | buf->state = UVC_BUF_STATE_DONE; | ||
364 | return -EAGAIN; | ||
365 | } | ||
366 | |||
367 | video->last_fid = fid; | ||
368 | |||
369 | return data[0]; | ||
370 | } | ||
371 | |||
372 | static void uvc_video_decode_data(struct uvc_video_device *video, | ||
373 | struct uvc_buffer *buf, const __u8 *data, int len) | ||
374 | { | ||
375 | struct uvc_video_queue *queue = &video->queue; | ||
376 | unsigned int maxlen, nbytes; | ||
377 | void *mem; | ||
378 | |||
379 | if (len <= 0) | ||
380 | return; | ||
381 | |||
382 | /* Copy the video data to the buffer. */ | ||
383 | maxlen = buf->buf.length - buf->buf.bytesused; | ||
384 | mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused; | ||
385 | nbytes = min((unsigned int)len, maxlen); | ||
386 | memcpy(mem, data, nbytes); | ||
387 | buf->buf.bytesused += nbytes; | ||
388 | |||
389 | /* Complete the current frame if the buffer size was exceeded. */ | ||
390 | if (len > maxlen) { | ||
391 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n"); | ||
392 | buf->state = UVC_BUF_STATE_DONE; | ||
393 | } | ||
394 | } | ||
395 | |||
396 | static void uvc_video_decode_end(struct uvc_video_device *video, | ||
397 | struct uvc_buffer *buf, const __u8 *data, int len) | ||
398 | { | ||
399 | /* Mark the buffer as done if the EOF marker is set. */ | ||
400 | if (data[1] & UVC_STREAM_EOF && buf->buf.bytesused != 0) { | ||
401 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); | ||
402 | if (data[0] == len) | ||
403 | uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n"); | ||
404 | buf->state = UVC_BUF_STATE_DONE; | ||
405 | if (video->dev->quirks & UVC_QUIRK_STREAM_NO_FID) | ||
406 | video->last_fid ^= UVC_STREAM_FID; | ||
407 | } | ||
408 | } | ||
409 | |||
410 | /* ------------------------------------------------------------------------ | ||
411 | * URB handling | ||
412 | */ | ||
413 | |||
414 | /* | ||
415 | * Completion handler for video URBs. | ||
416 | */ | ||
417 | static void uvc_video_decode_isoc(struct urb *urb, | ||
418 | struct uvc_video_device *video, struct uvc_buffer *buf) | ||
419 | { | ||
420 | u8 *mem; | ||
421 | int ret, i; | ||
422 | |||
423 | for (i = 0; i < urb->number_of_packets; ++i) { | ||
424 | if (urb->iso_frame_desc[i].status < 0) { | ||
425 | uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame " | ||
426 | "lost (%d).\n", urb->iso_frame_desc[i].status); | ||
427 | continue; | ||
428 | } | ||
429 | |||
430 | /* Decode the payload header. */ | ||
431 | mem = urb->transfer_buffer + urb->iso_frame_desc[i].offset; | ||
432 | do { | ||
433 | ret = uvc_video_decode_start(video, buf, mem, | ||
434 | urb->iso_frame_desc[i].actual_length); | ||
435 | if (ret == -EAGAIN) | ||
436 | buf = uvc_queue_next_buffer(&video->queue, buf); | ||
437 | } while (ret == -EAGAIN); | ||
438 | |||
439 | if (ret < 0) | ||
440 | continue; | ||
441 | |||
442 | /* Decode the payload data. */ | ||
443 | uvc_video_decode_data(video, buf, mem + ret, | ||
444 | urb->iso_frame_desc[i].actual_length - ret); | ||
445 | |||
446 | /* Process the header again. */ | ||
447 | uvc_video_decode_end(video, buf, mem, ret); | ||
448 | |||
449 | if (buf->state == UVC_BUF_STATE_DONE || | ||
450 | buf->state == UVC_BUF_STATE_ERROR) | ||
451 | buf = uvc_queue_next_buffer(&video->queue, buf); | ||
452 | } | ||
453 | } | ||
454 | |||
455 | static void uvc_video_decode_bulk(struct urb *urb, | ||
456 | struct uvc_video_device *video, struct uvc_buffer *buf) | ||
457 | { | ||
458 | u8 *mem; | ||
459 | int len, ret; | ||
460 | |||
461 | mem = urb->transfer_buffer; | ||
462 | len = urb->actual_length; | ||
463 | video->bulk.payload_size += len; | ||
464 | |||
465 | /* If the URB is the first of its payload, decode and save the | ||
466 | * header. | ||
467 | */ | ||
468 | if (video->bulk.header_size == 0) { | ||
469 | do { | ||
470 | ret = uvc_video_decode_start(video, buf, mem, len); | ||
471 | if (ret == -EAGAIN) | ||
472 | buf = uvc_queue_next_buffer(&video->queue, buf); | ||
473 | } while (ret == -EAGAIN); | ||
474 | |||
475 | /* If an error occured skip the rest of the payload. */ | ||
476 | if (ret < 0 || buf == NULL) { | ||
477 | video->bulk.skip_payload = 1; | ||
478 | return; | ||
479 | } | ||
480 | |||
481 | video->bulk.header_size = ret; | ||
482 | memcpy(video->bulk.header, mem, video->bulk.header_size); | ||
483 | |||
484 | mem += ret; | ||
485 | len -= ret; | ||
486 | } | ||
487 | |||
488 | /* The buffer queue might have been cancelled while a bulk transfer | ||
489 | * was in progress, so we can reach here with buf equal to NULL. Make | ||
490 | * sure buf is never dereferenced if NULL. | ||
491 | */ | ||
492 | |||
493 | /* Process video data. */ | ||
494 | if (!video->bulk.skip_payload && buf != NULL) | ||
495 | uvc_video_decode_data(video, buf, mem, len); | ||
496 | |||
497 | /* Detect the payload end by a URB smaller than the maximum size (or | ||
498 | * a payload size equal to the maximum) and process the header again. | ||
499 | */ | ||
500 | if (urb->actual_length < urb->transfer_buffer_length || | ||
501 | video->bulk.payload_size >= video->bulk.max_payload_size) { | ||
502 | if (!video->bulk.skip_payload && buf != NULL) { | ||
503 | uvc_video_decode_end(video, buf, video->bulk.header, | ||
504 | video->bulk.header_size); | ||
505 | if (buf->state == UVC_BUF_STATE_DONE || | ||
506 | buf->state == UVC_BUF_STATE_ERROR) | ||
507 | buf = uvc_queue_next_buffer(&video->queue, buf); | ||
508 | } | ||
509 | |||
510 | video->bulk.header_size = 0; | ||
511 | video->bulk.skip_payload = 0; | ||
512 | video->bulk.payload_size = 0; | ||
513 | } | ||
514 | } | ||
515 | |||
516 | static void uvc_video_complete(struct urb *urb) | ||
517 | { | ||
518 | struct uvc_video_device *video = urb->context; | ||
519 | struct uvc_video_queue *queue = &video->queue; | ||
520 | struct uvc_buffer *buf = NULL; | ||
521 | unsigned long flags; | ||
522 | int ret; | ||
523 | |||
524 | switch (urb->status) { | ||
525 | case 0: | ||
526 | break; | ||
527 | |||
528 | default: | ||
529 | uvc_printk(KERN_WARNING, "Non-zero status (%d) in video " | ||
530 | "completion handler.\n", urb->status); | ||
531 | |||
532 | case -ENOENT: /* usb_kill_urb() called. */ | ||
533 | if (video->frozen) | ||
534 | return; | ||
535 | |||
536 | case -ECONNRESET: /* usb_unlink_urb() called. */ | ||
537 | case -ESHUTDOWN: /* The endpoint is being disabled. */ | ||
538 | uvc_queue_cancel(queue, urb->status == -ESHUTDOWN); | ||
539 | return; | ||
540 | } | ||
541 | |||
542 | spin_lock_irqsave(&queue->irqlock, flags); | ||
543 | if (!list_empty(&queue->irqqueue)) | ||
544 | buf = list_first_entry(&queue->irqqueue, struct uvc_buffer, | ||
545 | queue); | ||
546 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
547 | |||
548 | video->decode(urb, video, buf); | ||
549 | |||
550 | if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { | ||
551 | uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n", | ||
552 | ret); | ||
553 | } | ||
554 | } | ||
555 | |||
556 | /* | ||
557 | * Uninitialize isochronous/bulk URBs and free transfer buffers. | ||
558 | */ | ||
559 | static void uvc_uninit_video(struct uvc_video_device *video) | ||
560 | { | ||
561 | struct urb *urb; | ||
562 | unsigned int i; | ||
563 | |||
564 | for (i = 0; i < UVC_URBS; ++i) { | ||
565 | if ((urb = video->urb[i]) == NULL) | ||
566 | continue; | ||
567 | |||
568 | usb_kill_urb(urb); | ||
569 | /* urb->transfer_buffer_length is not touched by USB core, so | ||
570 | * we can use it here as the buffer length. | ||
571 | */ | ||
572 | if (video->urb_buffer[i]) { | ||
573 | usb_buffer_free(video->dev->udev, | ||
574 | urb->transfer_buffer_length, | ||
575 | video->urb_buffer[i], urb->transfer_dma); | ||
576 | video->urb_buffer[i] = NULL; | ||
577 | } | ||
578 | |||
579 | usb_free_urb(urb); | ||
580 | video->urb[i] = NULL; | ||
581 | } | ||
582 | } | ||
583 | |||
584 | /* | ||
585 | * Initialize isochronous URBs and allocate transfer buffers. The packet size | ||
586 | * is given by the endpoint. | ||
587 | */ | ||
588 | static int uvc_init_video_isoc(struct uvc_video_device *video, | ||
589 | struct usb_host_endpoint *ep) | ||
590 | { | ||
591 | struct urb *urb; | ||
592 | unsigned int npackets, i, j; | ||
593 | __u16 psize; | ||
594 | __u32 size; | ||
595 | |||
596 | /* Compute the number of isochronous packets to allocate by dividing | ||
597 | * the maximum video frame size by the packet size. Limit the result | ||
598 | * to UVC_MAX_ISO_PACKETS. | ||
599 | */ | ||
600 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); | ||
601 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); | ||
602 | |||
603 | size = video->streaming->ctrl.dwMaxVideoFrameSize; | ||
604 | if (size > UVC_MAX_FRAME_SIZE) | ||
605 | return -EINVAL; | ||
606 | |||
607 | npackets = (size + psize - 1) / psize; | ||
608 | if (npackets > UVC_MAX_ISO_PACKETS) | ||
609 | npackets = UVC_MAX_ISO_PACKETS; | ||
610 | |||
611 | size = npackets * psize; | ||
612 | |||
613 | for (i = 0; i < UVC_URBS; ++i) { | ||
614 | urb = usb_alloc_urb(npackets, GFP_KERNEL); | ||
615 | if (urb == NULL) { | ||
616 | uvc_uninit_video(video); | ||
617 | return -ENOMEM; | ||
618 | } | ||
619 | |||
620 | video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev, | ||
621 | size, GFP_KERNEL, &urb->transfer_dma); | ||
622 | if (video->urb_buffer[i] == NULL) { | ||
623 | usb_free_urb(urb); | ||
624 | uvc_uninit_video(video); | ||
625 | return -ENOMEM; | ||
626 | } | ||
627 | |||
628 | urb->dev = video->dev->udev; | ||
629 | urb->context = video; | ||
630 | urb->pipe = usb_rcvisocpipe(video->dev->udev, | ||
631 | ep->desc.bEndpointAddress); | ||
632 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; | ||
633 | urb->interval = ep->desc.bInterval; | ||
634 | urb->transfer_buffer = video->urb_buffer[i]; | ||
635 | urb->complete = uvc_video_complete; | ||
636 | urb->number_of_packets = npackets; | ||
637 | urb->transfer_buffer_length = size; | ||
638 | |||
639 | for (j = 0; j < npackets; ++j) { | ||
640 | urb->iso_frame_desc[j].offset = j * psize; | ||
641 | urb->iso_frame_desc[j].length = psize; | ||
642 | } | ||
643 | |||
644 | video->urb[i] = urb; | ||
645 | } | ||
646 | |||
647 | return 0; | ||
648 | } | ||
649 | |||
650 | /* | ||
651 | * Initialize bulk URBs and allocate transfer buffers. The packet size is | ||
652 | * given by the endpoint. | ||
653 | */ | ||
654 | static int uvc_init_video_bulk(struct uvc_video_device *video, | ||
655 | struct usb_host_endpoint *ep) | ||
656 | { | ||
657 | struct urb *urb; | ||
658 | unsigned int pipe, i; | ||
659 | __u16 psize; | ||
660 | __u32 size; | ||
661 | |||
662 | /* Compute the bulk URB size. Some devices set the maximum payload | ||
663 | * size to a value too high for memory-constrained devices. We must | ||
664 | * then transfer the payload accross multiple URBs. To be consistant | ||
665 | * with isochronous mode, allocate maximum UVC_MAX_ISO_PACKETS per bulk | ||
666 | * URB. | ||
667 | */ | ||
668 | psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff; | ||
669 | size = video->streaming->ctrl.dwMaxPayloadTransferSize; | ||
670 | video->bulk.max_payload_size = size; | ||
671 | if (size > psize * UVC_MAX_ISO_PACKETS) | ||
672 | size = psize * UVC_MAX_ISO_PACKETS; | ||
673 | |||
674 | pipe = usb_rcvbulkpipe(video->dev->udev, ep->desc.bEndpointAddress); | ||
675 | |||
676 | for (i = 0; i < UVC_URBS; ++i) { | ||
677 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
678 | if (urb == NULL) { | ||
679 | uvc_uninit_video(video); | ||
680 | return -ENOMEM; | ||
681 | } | ||
682 | |||
683 | video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev, | ||
684 | size, GFP_KERNEL, &urb->transfer_dma); | ||
685 | if (video->urb_buffer[i] == NULL) { | ||
686 | usb_free_urb(urb); | ||
687 | uvc_uninit_video(video); | ||
688 | return -ENOMEM; | ||
689 | } | ||
690 | |||
691 | usb_fill_bulk_urb(urb, video->dev->udev, pipe, | ||
692 | video->urb_buffer[i], size, uvc_video_complete, | ||
693 | video); | ||
694 | urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
695 | |||
696 | video->urb[i] = urb; | ||
697 | } | ||
698 | |||
699 | return 0; | ||
700 | } | ||
701 | |||
702 | /* | ||
703 | * Initialize isochronous/bulk URBs and allocate transfer buffers. | ||
704 | */ | ||
705 | static int uvc_init_video(struct uvc_video_device *video) | ||
706 | { | ||
707 | struct usb_interface *intf = video->streaming->intf; | ||
708 | struct usb_host_interface *alts; | ||
709 | struct usb_host_endpoint *ep = NULL; | ||
710 | int intfnum = video->streaming->intfnum; | ||
711 | unsigned int bandwidth, psize, i; | ||
712 | int ret; | ||
713 | |||
714 | video->last_fid = -1; | ||
715 | video->bulk.header_size = 0; | ||
716 | video->bulk.skip_payload = 0; | ||
717 | video->bulk.payload_size = 0; | ||
718 | |||
719 | if (intf->num_altsetting > 1) { | ||
720 | /* Isochronous endpoint, select the alternate setting. */ | ||
721 | bandwidth = video->streaming->ctrl.dwMaxPayloadTransferSize; | ||
722 | |||
723 | if (bandwidth == 0) { | ||
724 | uvc_printk(KERN_WARNING, "device %s requested null " | ||
725 | "bandwidth, defaulting to lowest.\n", | ||
726 | video->vdev->name); | ||
727 | bandwidth = 1; | ||
728 | } | ||
729 | |||
730 | for (i = 0; i < intf->num_altsetting; ++i) { | ||
731 | alts = &intf->altsetting[i]; | ||
732 | ep = uvc_find_endpoint(alts, | ||
733 | video->streaming->header.bEndpointAddress); | ||
734 | if (ep == NULL) | ||
735 | continue; | ||
736 | |||
737 | /* Check if the bandwidth is high enough. */ | ||
738 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); | ||
739 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); | ||
740 | if (psize >= bandwidth) | ||
741 | break; | ||
742 | } | ||
743 | |||
744 | if (i >= intf->num_altsetting) | ||
745 | return -EIO; | ||
746 | |||
747 | if ((ret = usb_set_interface(video->dev->udev, intfnum, i)) < 0) | ||
748 | return ret; | ||
749 | |||
750 | ret = uvc_init_video_isoc(video, ep); | ||
751 | } else { | ||
752 | /* Bulk endpoint, proceed to URB initialization. */ | ||
753 | ep = uvc_find_endpoint(&intf->altsetting[0], | ||
754 | video->streaming->header.bEndpointAddress); | ||
755 | if (ep == NULL) | ||
756 | return -EIO; | ||
757 | |||
758 | ret = uvc_init_video_bulk(video, ep); | ||
759 | } | ||
760 | |||
761 | if (ret < 0) | ||
762 | return ret; | ||
763 | |||
764 | /* Submit the URBs. */ | ||
765 | for (i = 0; i < UVC_URBS; ++i) { | ||
766 | if ((ret = usb_submit_urb(video->urb[i], GFP_KERNEL)) < 0) { | ||
767 | uvc_printk(KERN_ERR, "Failed to submit URB %u " | ||
768 | "(%d).\n", i, ret); | ||
769 | uvc_uninit_video(video); | ||
770 | return ret; | ||
771 | } | ||
772 | } | ||
773 | |||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | /* -------------------------------------------------------------------------- | ||
778 | * Suspend/resume | ||
779 | */ | ||
780 | |||
781 | /* | ||
782 | * Stop streaming without disabling the video queue. | ||
783 | * | ||
784 | * To let userspace applications resume without trouble, we must not touch the | ||
785 | * video buffers in any way. We mark the device as frozen to make sure the URB | ||
786 | * completion handler won't try to cancel the queue when we kill the URBs. | ||
787 | */ | ||
788 | int uvc_video_suspend(struct uvc_video_device *video) | ||
789 | { | ||
790 | if (!uvc_queue_streaming(&video->queue)) | ||
791 | return 0; | ||
792 | |||
793 | video->frozen = 1; | ||
794 | uvc_uninit_video(video); | ||
795 | usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); | ||
796 | return 0; | ||
797 | } | ||
798 | |||
799 | /* | ||
800 | * Reconfigure the video interface and restart streaming if it was enable | ||
801 | * before suspend. | ||
802 | * | ||
803 | * If an error occurs, disable the video queue. This will wake all pending | ||
804 | * buffers, making sure userspace applications are notified of the problem | ||
805 | * instead of waiting forever. | ||
806 | */ | ||
807 | int uvc_video_resume(struct uvc_video_device *video) | ||
808 | { | ||
809 | int ret; | ||
810 | |||
811 | video->frozen = 0; | ||
812 | |||
813 | if ((ret = uvc_set_video_ctrl(video, &video->streaming->ctrl, 0)) < 0) { | ||
814 | uvc_queue_enable(&video->queue, 0); | ||
815 | return ret; | ||
816 | } | ||
817 | |||
818 | if (!uvc_queue_streaming(&video->queue)) | ||
819 | return 0; | ||
820 | |||
821 | if ((ret = uvc_init_video(video)) < 0) | ||
822 | uvc_queue_enable(&video->queue, 0); | ||
823 | |||
824 | return ret; | ||
825 | } | ||
826 | |||
827 | /* ------------------------------------------------------------------------ | ||
828 | * Video device | ||
829 | */ | ||
830 | |||
831 | /* | ||
832 | * Initialize the UVC video device by retrieving the default format and | ||
833 | * committing it. | ||
834 | * | ||
835 | * Some cameras (namely the Fuji Finepix) set the format and frame | ||
836 | * indexes to zero. The UVC standard doesn't clearly make this a spec | ||
837 | * violation, so try to silently fix the values if possible. | ||
838 | * | ||
839 | * This function is called before registering the device with V4L. | ||
840 | */ | ||
841 | int uvc_video_init(struct uvc_video_device *video) | ||
842 | { | ||
843 | struct uvc_streaming_control *probe = &video->streaming->ctrl; | ||
844 | struct uvc_format *format = NULL; | ||
845 | struct uvc_frame *frame = NULL; | ||
846 | unsigned int i; | ||
847 | int ret; | ||
848 | |||
849 | if (video->streaming->nformats == 0) { | ||
850 | uvc_printk(KERN_INFO, "No supported video formats found.\n"); | ||
851 | return -EINVAL; | ||
852 | } | ||
853 | |||
854 | /* Alternate setting 0 should be the default, yet the XBox Live Vision | ||
855 | * Cam (and possibly other devices) crash or otherwise misbehave if | ||
856 | * they don't receive a SET_INTERFACE request before any other video | ||
857 | * control request. | ||
858 | */ | ||
859 | usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); | ||
860 | |||
861 | /* Some webcams don't suport GET_DEF request on the probe control. We | ||
862 | * fall back to GET_CUR if GET_DEF fails. | ||
863 | */ | ||
864 | if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 && | ||
865 | (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0) | ||
866 | return ret; | ||
867 | |||
868 | /* Check if the default format descriptor exists. Use the first | ||
869 | * available format otherwise. | ||
870 | */ | ||
871 | for (i = video->streaming->nformats; i > 0; --i) { | ||
872 | format = &video->streaming->format[i-1]; | ||
873 | if (format->index == probe->bFormatIndex) | ||
874 | break; | ||
875 | } | ||
876 | |||
877 | if (format->nframes == 0) { | ||
878 | uvc_printk(KERN_INFO, "No frame descriptor found for the " | ||
879 | "default format.\n"); | ||
880 | return -EINVAL; | ||
881 | } | ||
882 | |||
883 | /* Zero bFrameIndex might be correct. Stream-based formats (including | ||
884 | * MPEG-2 TS and DV) do not support frames but have a dummy frame | ||
885 | * descriptor with bFrameIndex set to zero. If the default frame | ||
886 | * descriptor is not found, use the first avalable frame. | ||
887 | */ | ||
888 | for (i = format->nframes; i > 0; --i) { | ||
889 | frame = &format->frame[i-1]; | ||
890 | if (frame->bFrameIndex == probe->bFrameIndex) | ||
891 | break; | ||
892 | } | ||
893 | |||
894 | /* Commit the default settings. */ | ||
895 | probe->bFormatIndex = format->index; | ||
896 | probe->bFrameIndex = frame->bFrameIndex; | ||
897 | if ((ret = uvc_set_video_ctrl(video, probe, 0)) < 0) | ||
898 | return ret; | ||
899 | |||
900 | video->streaming->cur_format = format; | ||
901 | video->streaming->cur_frame = frame; | ||
902 | atomic_set(&video->active, 0); | ||
903 | |||
904 | /* Select the video decoding function */ | ||
905 | if (video->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT) | ||
906 | video->decode = uvc_video_decode_isight; | ||
907 | else if (video->streaming->intf->num_altsetting > 1) | ||
908 | video->decode = uvc_video_decode_isoc; | ||
909 | else | ||
910 | video->decode = uvc_video_decode_bulk; | ||
911 | |||
912 | return 0; | ||
913 | } | ||
914 | |||
915 | /* | ||
916 | * Enable or disable the video stream. | ||
917 | */ | ||
918 | int uvc_video_enable(struct uvc_video_device *video, int enable) | ||
919 | { | ||
920 | int ret; | ||
921 | |||
922 | if (!enable) { | ||
923 | uvc_uninit_video(video); | ||
924 | usb_set_interface(video->dev->udev, | ||
925 | video->streaming->intfnum, 0); | ||
926 | uvc_queue_enable(&video->queue, 0); | ||
927 | return 0; | ||
928 | } | ||
929 | |||
930 | if ((ret = uvc_queue_enable(&video->queue, 1)) < 0) | ||
931 | return ret; | ||
932 | |||
933 | return uvc_init_video(video); | ||
934 | } | ||
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h new file mode 100644 index 000000000000..a995a780db1c --- /dev/null +++ b/drivers/media/video/uvc/uvcvideo.h | |||
@@ -0,0 +1,796 @@ | |||
1 | #ifndef _USB_VIDEO_H_ | ||
2 | #define _USB_VIDEO_H_ | ||
3 | |||
4 | #include <linux/kernel.h> | ||
5 | #include <linux/videodev2.h> | ||
6 | |||
7 | |||
8 | /* | ||
9 | * Dynamic controls | ||
10 | */ | ||
11 | |||
12 | /* Data types for UVC control data */ | ||
13 | #define UVC_CTRL_DATA_TYPE_RAW 0 | ||
14 | #define UVC_CTRL_DATA_TYPE_SIGNED 1 | ||
15 | #define UVC_CTRL_DATA_TYPE_UNSIGNED 2 | ||
16 | #define UVC_CTRL_DATA_TYPE_BOOLEAN 3 | ||
17 | #define UVC_CTRL_DATA_TYPE_ENUM 4 | ||
18 | #define UVC_CTRL_DATA_TYPE_BITMASK 5 | ||
19 | |||
20 | /* Control flags */ | ||
21 | #define UVC_CONTROL_SET_CUR (1 << 0) | ||
22 | #define UVC_CONTROL_GET_CUR (1 << 1) | ||
23 | #define UVC_CONTROL_GET_MIN (1 << 2) | ||
24 | #define UVC_CONTROL_GET_MAX (1 << 3) | ||
25 | #define UVC_CONTROL_GET_RES (1 << 4) | ||
26 | #define UVC_CONTROL_GET_DEF (1 << 5) | ||
27 | /* Control should be saved at suspend and restored at resume. */ | ||
28 | #define UVC_CONTROL_RESTORE (1 << 6) | ||
29 | /* Control can be updated by the camera. */ | ||
30 | #define UVC_CONTROL_AUTO_UPDATE (1 << 7) | ||
31 | |||
32 | #define UVC_CONTROL_GET_RANGE (UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | \ | ||
33 | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | \ | ||
34 | UVC_CONTROL_GET_DEF) | ||
35 | |||
36 | struct uvc_xu_control_info { | ||
37 | __u8 entity[16]; | ||
38 | __u8 index; | ||
39 | __u8 selector; | ||
40 | __u16 size; | ||
41 | __u32 flags; | ||
42 | }; | ||
43 | |||
44 | struct uvc_xu_control_mapping { | ||
45 | __u32 id; | ||
46 | __u8 name[32]; | ||
47 | __u8 entity[16]; | ||
48 | __u8 selector; | ||
49 | |||
50 | __u8 size; | ||
51 | __u8 offset; | ||
52 | enum v4l2_ctrl_type v4l2_type; | ||
53 | __u32 data_type; | ||
54 | }; | ||
55 | |||
56 | struct uvc_xu_control { | ||
57 | __u8 unit; | ||
58 | __u8 selector; | ||
59 | __u16 size; | ||
60 | __u8 __user *data; | ||
61 | }; | ||
62 | |||
63 | #define UVCIOC_CTRL_ADD _IOW('U', 1, struct uvc_xu_control_info) | ||
64 | #define UVCIOC_CTRL_MAP _IOWR('U', 2, struct uvc_xu_control_mapping) | ||
65 | #define UVCIOC_CTRL_GET _IOWR('U', 3, struct uvc_xu_control) | ||
66 | #define UVCIOC_CTRL_SET _IOW('U', 4, struct uvc_xu_control) | ||
67 | |||
68 | #ifdef __KERNEL__ | ||
69 | |||
70 | #include <linux/poll.h> | ||
71 | |||
72 | /* -------------------------------------------------------------------------- | ||
73 | * UVC constants | ||
74 | */ | ||
75 | |||
76 | #define SC_UNDEFINED 0x00 | ||
77 | #define SC_VIDEOCONTROL 0x01 | ||
78 | #define SC_VIDEOSTREAMING 0x02 | ||
79 | #define SC_VIDEO_INTERFACE_COLLECTION 0x03 | ||
80 | |||
81 | #define PC_PROTOCOL_UNDEFINED 0x00 | ||
82 | |||
83 | #define CS_UNDEFINED 0x20 | ||
84 | #define CS_DEVICE 0x21 | ||
85 | #define CS_CONFIGURATION 0x22 | ||
86 | #define CS_STRING 0x23 | ||
87 | #define CS_INTERFACE 0x24 | ||
88 | #define CS_ENDPOINT 0x25 | ||
89 | |||
90 | /* VideoControl class specific interface descriptor */ | ||
91 | #define VC_DESCRIPTOR_UNDEFINED 0x00 | ||
92 | #define VC_HEADER 0x01 | ||
93 | #define VC_INPUT_TERMINAL 0x02 | ||
94 | #define VC_OUTPUT_TERMINAL 0x03 | ||
95 | #define VC_SELECTOR_UNIT 0x04 | ||
96 | #define VC_PROCESSING_UNIT 0x05 | ||
97 | #define VC_EXTENSION_UNIT 0x06 | ||
98 | |||
99 | /* VideoStreaming class specific interface descriptor */ | ||
100 | #define VS_UNDEFINED 0x00 | ||
101 | #define VS_INPUT_HEADER 0x01 | ||
102 | #define VS_OUTPUT_HEADER 0x02 | ||
103 | #define VS_STILL_IMAGE_FRAME 0x03 | ||
104 | #define VS_FORMAT_UNCOMPRESSED 0x04 | ||
105 | #define VS_FRAME_UNCOMPRESSED 0x05 | ||
106 | #define VS_FORMAT_MJPEG 0x06 | ||
107 | #define VS_FRAME_MJPEG 0x07 | ||
108 | #define VS_FORMAT_MPEG2TS 0x0a | ||
109 | #define VS_FORMAT_DV 0x0c | ||
110 | #define VS_COLORFORMAT 0x0d | ||
111 | #define VS_FORMAT_FRAME_BASED 0x10 | ||
112 | #define VS_FRAME_FRAME_BASED 0x11 | ||
113 | #define VS_FORMAT_STREAM_BASED 0x12 | ||
114 | |||
115 | /* Endpoint type */ | ||
116 | #define EP_UNDEFINED 0x00 | ||
117 | #define EP_GENERAL 0x01 | ||
118 | #define EP_ENDPOINT 0x02 | ||
119 | #define EP_INTERRUPT 0x03 | ||
120 | |||
121 | /* Request codes */ | ||
122 | #define RC_UNDEFINED 0x00 | ||
123 | #define SET_CUR 0x01 | ||
124 | #define GET_CUR 0x81 | ||
125 | #define GET_MIN 0x82 | ||
126 | #define GET_MAX 0x83 | ||
127 | #define GET_RES 0x84 | ||
128 | #define GET_LEN 0x85 | ||
129 | #define GET_INFO 0x86 | ||
130 | #define GET_DEF 0x87 | ||
131 | |||
132 | /* VideoControl interface controls */ | ||
133 | #define VC_CONTROL_UNDEFINED 0x00 | ||
134 | #define VC_VIDEO_POWER_MODE_CONTROL 0x01 | ||
135 | #define VC_REQUEST_ERROR_CODE_CONTROL 0x02 | ||
136 | |||
137 | /* Terminal controls */ | ||
138 | #define TE_CONTROL_UNDEFINED 0x00 | ||
139 | |||
140 | /* Selector Unit controls */ | ||
141 | #define SU_CONTROL_UNDEFINED 0x00 | ||
142 | #define SU_INPUT_SELECT_CONTROL 0x01 | ||
143 | |||
144 | /* Camera Terminal controls */ | ||
145 | #define CT_CONTROL_UNDEFINED 0x00 | ||
146 | #define CT_SCANNING_MODE_CONTROL 0x01 | ||
147 | #define CT_AE_MODE_CONTROL 0x02 | ||
148 | #define CT_AE_PRIORITY_CONTROL 0x03 | ||
149 | #define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 | ||
150 | #define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 | ||
151 | #define CT_FOCUS_ABSOLUTE_CONTROL 0x06 | ||
152 | #define CT_FOCUS_RELATIVE_CONTROL 0x07 | ||
153 | #define CT_FOCUS_AUTO_CONTROL 0x08 | ||
154 | #define CT_IRIS_ABSOLUTE_CONTROL 0x09 | ||
155 | #define CT_IRIS_RELATIVE_CONTROL 0x0a | ||
156 | #define CT_ZOOM_ABSOLUTE_CONTROL 0x0b | ||
157 | #define CT_ZOOM_RELATIVE_CONTROL 0x0c | ||
158 | #define CT_PANTILT_ABSOLUTE_CONTROL 0x0d | ||
159 | #define CT_PANTILT_RELATIVE_CONTROL 0x0e | ||
160 | #define CT_ROLL_ABSOLUTE_CONTROL 0x0f | ||
161 | #define CT_ROLL_RELATIVE_CONTROL 0x10 | ||
162 | #define CT_PRIVACY_CONTROL 0x11 | ||
163 | |||
164 | /* Processing Unit controls */ | ||
165 | #define PU_CONTROL_UNDEFINED 0x00 | ||
166 | #define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 | ||
167 | #define PU_BRIGHTNESS_CONTROL 0x02 | ||
168 | #define PU_CONTRAST_CONTROL 0x03 | ||
169 | #define PU_GAIN_CONTROL 0x04 | ||
170 | #define PU_POWER_LINE_FREQUENCY_CONTROL 0x05 | ||
171 | #define PU_HUE_CONTROL 0x06 | ||
172 | #define PU_SATURATION_CONTROL 0x07 | ||
173 | #define PU_SHARPNESS_CONTROL 0x08 | ||
174 | #define PU_GAMMA_CONTROL 0x09 | ||
175 | #define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a | ||
176 | #define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b | ||
177 | #define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c | ||
178 | #define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d | ||
179 | #define PU_DIGITAL_MULTIPLIER_CONTROL 0x0e | ||
180 | #define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f | ||
181 | #define PU_HUE_AUTO_CONTROL 0x10 | ||
182 | #define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 | ||
183 | #define PU_ANALOG_LOCK_STATUS_CONTROL 0x12 | ||
184 | |||
185 | #define LXU_MOTOR_PANTILT_RELATIVE_CONTROL 0x01 | ||
186 | #define LXU_MOTOR_PANTILT_RESET_CONTROL 0x02 | ||
187 | #define LXU_MOTOR_FOCUS_MOTOR_CONTROL 0x03 | ||
188 | |||
189 | /* VideoStreaming interface controls */ | ||
190 | #define VS_CONTROL_UNDEFINED 0x00 | ||
191 | #define VS_PROBE_CONTROL 0x01 | ||
192 | #define VS_COMMIT_CONTROL 0x02 | ||
193 | #define VS_STILL_PROBE_CONTROL 0x03 | ||
194 | #define VS_STILL_COMMIT_CONTROL 0x04 | ||
195 | #define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 | ||
196 | #define VS_STREAM_ERROR_CODE_CONTROL 0x06 | ||
197 | #define VS_GENERATE_KEY_FRAME_CONTROL 0x07 | ||
198 | #define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 | ||
199 | #define VS_SYNC_DELAY_CONTROL 0x09 | ||
200 | |||
201 | #define TT_VENDOR_SPECIFIC 0x0100 | ||
202 | #define TT_STREAMING 0x0101 | ||
203 | |||
204 | /* Input Terminal types */ | ||
205 | #define ITT_VENDOR_SPECIFIC 0x0200 | ||
206 | #define ITT_CAMERA 0x0201 | ||
207 | #define ITT_MEDIA_TRANSPORT_INPUT 0x0202 | ||
208 | |||
209 | /* Output Terminal types */ | ||
210 | #define OTT_VENDOR_SPECIFIC 0x0300 | ||
211 | #define OTT_DISPLAY 0x0301 | ||
212 | #define OTT_MEDIA_TRANSPORT_OUTPUT 0x0302 | ||
213 | |||
214 | /* External Terminal types */ | ||
215 | #define EXTERNAL_VENDOR_SPECIFIC 0x0400 | ||
216 | #define COMPOSITE_CONNECTOR 0x0401 | ||
217 | #define SVIDEO_CONNECTOR 0x0402 | ||
218 | #define COMPONENT_CONNECTOR 0x0403 | ||
219 | |||
220 | #define UVC_TERM_INPUT 0x0000 | ||
221 | #define UVC_TERM_OUTPUT 0x8000 | ||
222 | |||
223 | #define UVC_ENTITY_TYPE(entity) ((entity)->type & 0x7fff) | ||
224 | #define UVC_ENTITY_IS_UNIT(entity) (((entity)->type & 0xff00) == 0) | ||
225 | #define UVC_ENTITY_IS_TERM(entity) (((entity)->type & 0xff00) != 0) | ||
226 | #define UVC_ENTITY_IS_ITERM(entity) \ | ||
227 | (((entity)->type & 0x8000) == UVC_TERM_INPUT) | ||
228 | #define UVC_ENTITY_IS_OTERM(entity) \ | ||
229 | (((entity)->type & 0x8000) == UVC_TERM_OUTPUT) | ||
230 | |||
231 | #define UVC_STATUS_TYPE_CONTROL 1 | ||
232 | #define UVC_STATUS_TYPE_STREAMING 2 | ||
233 | |||
234 | /* ------------------------------------------------------------------------ | ||
235 | * GUIDs | ||
236 | */ | ||
237 | #define UVC_GUID_UVC_CAMERA \ | ||
238 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ | ||
239 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01} | ||
240 | #define UVC_GUID_UVC_OUTPUT \ | ||
241 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ | ||
242 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02} | ||
243 | #define UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT \ | ||
244 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ | ||
245 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03} | ||
246 | #define UVC_GUID_UVC_PROCESSING \ | ||
247 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ | ||
248 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01} | ||
249 | #define UVC_GUID_UVC_SELECTOR \ | ||
250 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ | ||
251 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02} | ||
252 | |||
253 | #define UVC_GUID_LOGITECH_DEV_INFO \ | ||
254 | {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ | ||
255 | 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1e} | ||
256 | #define UVC_GUID_LOGITECH_USER_HW \ | ||
257 | {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ | ||
258 | 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1f} | ||
259 | #define UVC_GUID_LOGITECH_VIDEO \ | ||
260 | {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ | ||
261 | 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x50} | ||
262 | #define UVC_GUID_LOGITECH_MOTOR \ | ||
263 | {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ | ||
264 | 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x56} | ||
265 | |||
266 | #define UVC_GUID_FORMAT_MJPEG \ | ||
267 | { 'M', 'J', 'P', 'G', 0x00, 0x00, 0x10, 0x00, \ | ||
268 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
269 | #define UVC_GUID_FORMAT_YUY2 \ | ||
270 | { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, \ | ||
271 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
272 | #define UVC_GUID_FORMAT_NV12 \ | ||
273 | { 'N', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, \ | ||
274 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
275 | #define UVC_GUID_FORMAT_YV12 \ | ||
276 | { 'Y', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, \ | ||
277 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
278 | #define UVC_GUID_FORMAT_I420 \ | ||
279 | { 'I', '4', '2', '0', 0x00, 0x00, 0x10, 0x00, \ | ||
280 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
281 | #define UVC_GUID_FORMAT_UYVY \ | ||
282 | { 'U', 'Y', 'V', 'Y', 0x00, 0x00, 0x10, 0x00, \ | ||
283 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
284 | #define UVC_GUID_FORMAT_Y800 \ | ||
285 | { 'Y', '8', '0', '0', 0x00, 0x00, 0x10, 0x00, \ | ||
286 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
287 | #define UVC_GUID_FORMAT_BY8 \ | ||
288 | { 'B', 'Y', '8', ' ', 0x00, 0x00, 0x10, 0x00, \ | ||
289 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
290 | |||
291 | |||
292 | /* ------------------------------------------------------------------------ | ||
293 | * Driver specific constants. | ||
294 | */ | ||
295 | |||
296 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 0) | ||
297 | |||
298 | /* Number of isochronous URBs. */ | ||
299 | #define UVC_URBS 5 | ||
300 | /* Maximum number of packets per isochronous URB. */ | ||
301 | #define UVC_MAX_ISO_PACKETS 40 | ||
302 | /* Maximum frame size in bytes, for sanity checking. */ | ||
303 | #define UVC_MAX_FRAME_SIZE (16*1024*1024) | ||
304 | /* Maximum number of video buffers. */ | ||
305 | #define UVC_MAX_VIDEO_BUFFERS 32 | ||
306 | |||
307 | #define UVC_CTRL_CONTROL_TIMEOUT 300 | ||
308 | #define UVC_CTRL_STREAMING_TIMEOUT 1000 | ||
309 | |||
310 | /* Devices quirks */ | ||
311 | #define UVC_QUIRK_STATUS_INTERVAL 0x00000001 | ||
312 | #define UVC_QUIRK_PROBE_MINMAX 0x00000002 | ||
313 | #define UVC_QUIRK_PROBE_EXTRAFIELDS 0x00000004 | ||
314 | #define UVC_QUIRK_BUILTIN_ISIGHT 0x00000008 | ||
315 | #define UVC_QUIRK_STREAM_NO_FID 0x00000010 | ||
316 | #define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020 | ||
317 | |||
318 | /* Format flags */ | ||
319 | #define UVC_FMT_FLAG_COMPRESSED 0x00000001 | ||
320 | #define UVC_FMT_FLAG_STREAM 0x00000002 | ||
321 | |||
322 | /* ------------------------------------------------------------------------ | ||
323 | * Structures. | ||
324 | */ | ||
325 | |||
326 | struct uvc_device; | ||
327 | |||
328 | /* TODO: Put the most frequently accessed fields at the beginning of | ||
329 | * structures to maximize cache efficiency. | ||
330 | */ | ||
331 | struct uvc_streaming_control { | ||
332 | __u16 bmHint; | ||
333 | __u8 bFormatIndex; | ||
334 | __u8 bFrameIndex; | ||
335 | __u32 dwFrameInterval; | ||
336 | __u16 wKeyFrameRate; | ||
337 | __u16 wPFrameRate; | ||
338 | __u16 wCompQuality; | ||
339 | __u16 wCompWindowSize; | ||
340 | __u16 wDelay; | ||
341 | __u32 dwMaxVideoFrameSize; | ||
342 | __u32 dwMaxPayloadTransferSize; | ||
343 | __u32 dwClockFrequency; | ||
344 | __u8 bmFramingInfo; | ||
345 | __u8 bPreferedVersion; | ||
346 | __u8 bMinVersion; | ||
347 | __u8 bMaxVersion; | ||
348 | }; | ||
349 | |||
350 | struct uvc_menu_info { | ||
351 | __u32 value; | ||
352 | __u8 name[32]; | ||
353 | }; | ||
354 | |||
355 | struct uvc_control_info { | ||
356 | struct list_head list; | ||
357 | struct list_head mappings; | ||
358 | |||
359 | __u8 entity[16]; | ||
360 | __u8 index; | ||
361 | __u8 selector; | ||
362 | |||
363 | __u16 size; | ||
364 | __u32 flags; | ||
365 | }; | ||
366 | |||
367 | struct uvc_control_mapping { | ||
368 | struct list_head list; | ||
369 | |||
370 | struct uvc_control_info *ctrl; | ||
371 | |||
372 | __u32 id; | ||
373 | __u8 name[32]; | ||
374 | __u8 entity[16]; | ||
375 | __u8 selector; | ||
376 | |||
377 | __u8 size; | ||
378 | __u8 offset; | ||
379 | enum v4l2_ctrl_type v4l2_type; | ||
380 | __u32 data_type; | ||
381 | |||
382 | struct uvc_menu_info *menu_info; | ||
383 | __u32 menu_count; | ||
384 | }; | ||
385 | |||
386 | struct uvc_control { | ||
387 | struct uvc_entity *entity; | ||
388 | struct uvc_control_info *info; | ||
389 | |||
390 | __u8 index; /* Used to match the uvc_control entry with a | ||
391 | uvc_control_info. */ | ||
392 | __u8 dirty : 1, | ||
393 | loaded : 1, | ||
394 | modified : 1; | ||
395 | |||
396 | __u8 *data; | ||
397 | }; | ||
398 | |||
399 | struct uvc_format_desc { | ||
400 | char *name; | ||
401 | __u8 guid[16]; | ||
402 | __u32 fcc; | ||
403 | }; | ||
404 | |||
405 | /* The term 'entity' refers to both UVC units and UVC terminals. | ||
406 | * | ||
407 | * The type field is either the terminal type (wTerminalType in the terminal | ||
408 | * descriptor), or the unit type (bDescriptorSubtype in the unit descriptor). | ||
409 | * As the bDescriptorSubtype field is one byte long, the type value will | ||
410 | * always have a null MSB for units. All terminal types defined by the UVC | ||
411 | * specification have a non-null MSB, so it is safe to use the MSB to | ||
412 | * differentiate between units and terminals as long as the descriptor parsing | ||
413 | * code makes sure terminal types have a non-null MSB. | ||
414 | * | ||
415 | * For terminals, the type's most significant bit stores the terminal | ||
416 | * direction (either UVC_TERM_INPUT or UVC_TERM_OUTPUT). The type field should | ||
417 | * always be accessed with the UVC_ENTITY_* macros and never directly. | ||
418 | */ | ||
419 | |||
420 | struct uvc_entity { | ||
421 | struct list_head list; /* Entity as part of a UVC device. */ | ||
422 | struct list_head chain; /* Entity as part of a video device | ||
423 | * chain. */ | ||
424 | __u8 id; | ||
425 | __u16 type; | ||
426 | char name[64]; | ||
427 | |||
428 | union { | ||
429 | struct { | ||
430 | __u16 wObjectiveFocalLengthMin; | ||
431 | __u16 wObjectiveFocalLengthMax; | ||
432 | __u16 wOcularFocalLength; | ||
433 | __u8 bControlSize; | ||
434 | __u8 *bmControls; | ||
435 | } camera; | ||
436 | |||
437 | struct { | ||
438 | __u8 bControlSize; | ||
439 | __u8 *bmControls; | ||
440 | __u8 bTransportModeSize; | ||
441 | __u8 *bmTransportModes; | ||
442 | } media; | ||
443 | |||
444 | struct { | ||
445 | __u8 bSourceID; | ||
446 | } output; | ||
447 | |||
448 | struct { | ||
449 | __u8 bSourceID; | ||
450 | __u16 wMaxMultiplier; | ||
451 | __u8 bControlSize; | ||
452 | __u8 *bmControls; | ||
453 | __u8 bmVideoStandards; | ||
454 | } processing; | ||
455 | |||
456 | struct { | ||
457 | __u8 bNrInPins; | ||
458 | __u8 *baSourceID; | ||
459 | } selector; | ||
460 | |||
461 | struct { | ||
462 | __u8 guidExtensionCode[16]; | ||
463 | __u8 bNumControls; | ||
464 | __u8 bNrInPins; | ||
465 | __u8 *baSourceID; | ||
466 | __u8 bControlSize; | ||
467 | __u8 *bmControls; | ||
468 | __u8 *bmControlsType; | ||
469 | } extension; | ||
470 | }; | ||
471 | |||
472 | unsigned int ncontrols; | ||
473 | struct uvc_control *controls; | ||
474 | }; | ||
475 | |||
476 | struct uvc_frame { | ||
477 | __u8 bFrameIndex; | ||
478 | __u8 bmCapabilities; | ||
479 | __u16 wWidth; | ||
480 | __u16 wHeight; | ||
481 | __u32 dwMinBitRate; | ||
482 | __u32 dwMaxBitRate; | ||
483 | __u32 dwMaxVideoFrameBufferSize; | ||
484 | __u8 bFrameIntervalType; | ||
485 | __u32 dwDefaultFrameInterval; | ||
486 | __u32 *dwFrameInterval; | ||
487 | }; | ||
488 | |||
489 | struct uvc_format { | ||
490 | __u8 type; | ||
491 | __u8 index; | ||
492 | __u8 bpp; | ||
493 | __u8 colorspace; | ||
494 | __u32 fcc; | ||
495 | __u32 flags; | ||
496 | |||
497 | char name[32]; | ||
498 | |||
499 | unsigned int nframes; | ||
500 | struct uvc_frame *frame; | ||
501 | }; | ||
502 | |||
503 | struct uvc_streaming_header { | ||
504 | __u8 bNumFormats; | ||
505 | __u8 bEndpointAddress; | ||
506 | __u8 bTerminalLink; | ||
507 | __u8 bControlSize; | ||
508 | __u8 *bmaControls; | ||
509 | /* The following fields are used by input headers only. */ | ||
510 | __u8 bmInfo; | ||
511 | __u8 bStillCaptureMethod; | ||
512 | __u8 bTriggerSupport; | ||
513 | __u8 bTriggerUsage; | ||
514 | }; | ||
515 | |||
516 | struct uvc_streaming { | ||
517 | struct list_head list; | ||
518 | |||
519 | struct usb_interface *intf; | ||
520 | int intfnum; | ||
521 | __u16 maxpsize; | ||
522 | |||
523 | struct uvc_streaming_header header; | ||
524 | |||
525 | unsigned int nformats; | ||
526 | struct uvc_format *format; | ||
527 | |||
528 | struct uvc_streaming_control ctrl; | ||
529 | struct uvc_format *cur_format; | ||
530 | struct uvc_frame *cur_frame; | ||
531 | |||
532 | struct mutex mutex; | ||
533 | }; | ||
534 | |||
535 | enum uvc_buffer_state { | ||
536 | UVC_BUF_STATE_IDLE = 0, | ||
537 | UVC_BUF_STATE_QUEUED = 1, | ||
538 | UVC_BUF_STATE_ACTIVE = 2, | ||
539 | UVC_BUF_STATE_DONE = 3, | ||
540 | UVC_BUF_STATE_ERROR = 4, | ||
541 | }; | ||
542 | |||
543 | struct uvc_buffer { | ||
544 | unsigned long vma_use_count; | ||
545 | struct list_head stream; | ||
546 | |||
547 | /* Touched by interrupt handler. */ | ||
548 | struct v4l2_buffer buf; | ||
549 | struct list_head queue; | ||
550 | wait_queue_head_t wait; | ||
551 | enum uvc_buffer_state state; | ||
552 | }; | ||
553 | |||
554 | #define UVC_QUEUE_STREAMING (1 << 0) | ||
555 | #define UVC_QUEUE_DISCONNECTED (1 << 1) | ||
556 | #define UVC_QUEUE_DROP_INCOMPLETE (1 << 2) | ||
557 | |||
558 | struct uvc_video_queue { | ||
559 | void *mem; | ||
560 | unsigned int flags; | ||
561 | __u32 sequence; | ||
562 | |||
563 | unsigned int count; | ||
564 | unsigned int buf_size; | ||
565 | struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS]; | ||
566 | struct mutex mutex; /* protects buffers and mainqueue */ | ||
567 | spinlock_t irqlock; /* protects irqqueue */ | ||
568 | |||
569 | struct list_head mainqueue; | ||
570 | struct list_head irqqueue; | ||
571 | }; | ||
572 | |||
573 | struct uvc_video_device { | ||
574 | struct uvc_device *dev; | ||
575 | struct video_device *vdev; | ||
576 | atomic_t active; | ||
577 | unsigned int frozen : 1; | ||
578 | |||
579 | struct list_head iterms; | ||
580 | struct uvc_entity *oterm; | ||
581 | struct uvc_entity *processing; | ||
582 | struct uvc_entity *selector; | ||
583 | struct list_head extensions; | ||
584 | struct mutex ctrl_mutex; | ||
585 | |||
586 | struct uvc_video_queue queue; | ||
587 | |||
588 | /* Video streaming object, must always be non-NULL. */ | ||
589 | struct uvc_streaming *streaming; | ||
590 | |||
591 | void (*decode) (struct urb *urb, struct uvc_video_device *video, | ||
592 | struct uvc_buffer *buf); | ||
593 | |||
594 | /* Context data used by the bulk completion handler. */ | ||
595 | struct { | ||
596 | __u8 header[256]; | ||
597 | unsigned int header_size; | ||
598 | int skip_payload; | ||
599 | __u32 payload_size; | ||
600 | __u32 max_payload_size; | ||
601 | } bulk; | ||
602 | |||
603 | struct urb *urb[UVC_URBS]; | ||
604 | char *urb_buffer[UVC_URBS]; | ||
605 | |||
606 | __u8 last_fid; | ||
607 | }; | ||
608 | |||
609 | enum uvc_device_state { | ||
610 | UVC_DEV_DISCONNECTED = 1, | ||
611 | }; | ||
612 | |||
613 | struct uvc_device { | ||
614 | struct usb_device *udev; | ||
615 | struct usb_interface *intf; | ||
616 | __u32 quirks; | ||
617 | int intfnum; | ||
618 | char name[32]; | ||
619 | |||
620 | enum uvc_device_state state; | ||
621 | struct kref kref; | ||
622 | struct list_head list; | ||
623 | |||
624 | /* Video control interface */ | ||
625 | __u16 uvc_version; | ||
626 | __u32 clock_frequency; | ||
627 | |||
628 | struct list_head entities; | ||
629 | |||
630 | struct uvc_video_device video; | ||
631 | |||
632 | /* Status Interrupt Endpoint */ | ||
633 | struct usb_host_endpoint *int_ep; | ||
634 | struct urb *int_urb; | ||
635 | __u8 status[16]; | ||
636 | struct input_dev *input; | ||
637 | |||
638 | /* Video Streaming interfaces */ | ||
639 | struct list_head streaming; | ||
640 | }; | ||
641 | |||
642 | enum uvc_handle_state { | ||
643 | UVC_HANDLE_PASSIVE = 0, | ||
644 | UVC_HANDLE_ACTIVE = 1, | ||
645 | }; | ||
646 | |||
647 | struct uvc_fh { | ||
648 | struct uvc_video_device *device; | ||
649 | enum uvc_handle_state state; | ||
650 | }; | ||
651 | |||
652 | struct uvc_driver { | ||
653 | struct usb_driver driver; | ||
654 | |||
655 | struct mutex open_mutex; /* protects from open/disconnect race */ | ||
656 | |||
657 | struct list_head devices; /* struct uvc_device list */ | ||
658 | struct list_head controls; /* struct uvc_control_info list */ | ||
659 | struct mutex ctrl_mutex; /* protects controls and devices | ||
660 | lists */ | ||
661 | }; | ||
662 | |||
663 | /* ------------------------------------------------------------------------ | ||
664 | * Debugging, printing and logging | ||
665 | */ | ||
666 | |||
667 | #define UVC_TRACE_PROBE (1 << 0) | ||
668 | #define UVC_TRACE_DESCR (1 << 1) | ||
669 | #define UVC_TRACE_CONTROL (1 << 2) | ||
670 | #define UVC_TRACE_FORMAT (1 << 3) | ||
671 | #define UVC_TRACE_CAPTURE (1 << 4) | ||
672 | #define UVC_TRACE_CALLS (1 << 5) | ||
673 | #define UVC_TRACE_IOCTL (1 << 6) | ||
674 | #define UVC_TRACE_FRAME (1 << 7) | ||
675 | #define UVC_TRACE_SUSPEND (1 << 8) | ||
676 | #define UVC_TRACE_STATUS (1 << 9) | ||
677 | |||
678 | extern unsigned int uvc_trace_param; | ||
679 | |||
680 | #define uvc_trace(flag, msg...) \ | ||
681 | do { \ | ||
682 | if (uvc_trace_param & flag) \ | ||
683 | printk(KERN_DEBUG "uvcvideo: " msg); \ | ||
684 | } while (0) | ||
685 | |||
686 | #define uvc_printk(level, msg...) \ | ||
687 | printk(level "uvcvideo: " msg) | ||
688 | |||
689 | #define UVC_GUID_FORMAT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" \ | ||
690 | "%02x%02x%02x%02x%02x%02x" | ||
691 | #define UVC_GUID_ARGS(guid) \ | ||
692 | (guid)[3], (guid)[2], (guid)[1], (guid)[0], \ | ||
693 | (guid)[5], (guid)[4], \ | ||
694 | (guid)[7], (guid)[6], \ | ||
695 | (guid)[8], (guid)[9], \ | ||
696 | (guid)[10], (guid)[11], (guid)[12], \ | ||
697 | (guid)[13], (guid)[14], (guid)[15] | ||
698 | |||
699 | /* -------------------------------------------------------------------------- | ||
700 | * Internal functions. | ||
701 | */ | ||
702 | |||
703 | /* Core driver */ | ||
704 | extern struct uvc_driver uvc_driver; | ||
705 | extern void uvc_delete(struct kref *kref); | ||
706 | |||
707 | /* Video buffers queue management. */ | ||
708 | extern void uvc_queue_init(struct uvc_video_queue *queue); | ||
709 | extern int uvc_alloc_buffers(struct uvc_video_queue *queue, | ||
710 | unsigned int nbuffers, unsigned int buflength); | ||
711 | extern int uvc_free_buffers(struct uvc_video_queue *queue); | ||
712 | extern int uvc_query_buffer(struct uvc_video_queue *queue, | ||
713 | struct v4l2_buffer *v4l2_buf); | ||
714 | extern int uvc_queue_buffer(struct uvc_video_queue *queue, | ||
715 | struct v4l2_buffer *v4l2_buf); | ||
716 | extern int uvc_dequeue_buffer(struct uvc_video_queue *queue, | ||
717 | struct v4l2_buffer *v4l2_buf, int nonblocking); | ||
718 | extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable); | ||
719 | extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect); | ||
720 | extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, | ||
721 | struct uvc_buffer *buf); | ||
722 | extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, | ||
723 | struct file *file, poll_table *wait); | ||
724 | static inline int uvc_queue_streaming(struct uvc_video_queue *queue) | ||
725 | { | ||
726 | return queue->flags & UVC_QUEUE_STREAMING; | ||
727 | } | ||
728 | |||
729 | /* V4L2 interface */ | ||
730 | extern struct file_operations uvc_fops; | ||
731 | |||
732 | /* Video */ | ||
733 | extern int uvc_video_init(struct uvc_video_device *video); | ||
734 | extern int uvc_video_suspend(struct uvc_video_device *video); | ||
735 | extern int uvc_video_resume(struct uvc_video_device *video); | ||
736 | extern int uvc_video_enable(struct uvc_video_device *video, int enable); | ||
737 | extern int uvc_probe_video(struct uvc_video_device *video, | ||
738 | struct uvc_streaming_control *probe); | ||
739 | extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, | ||
740 | __u8 intfnum, __u8 cs, void *data, __u16 size); | ||
741 | extern int uvc_set_video_ctrl(struct uvc_video_device *video, | ||
742 | struct uvc_streaming_control *ctrl, int probe); | ||
743 | |||
744 | /* Status */ | ||
745 | extern int uvc_status_init(struct uvc_device *dev); | ||
746 | extern void uvc_status_cleanup(struct uvc_device *dev); | ||
747 | extern int uvc_status_suspend(struct uvc_device *dev); | ||
748 | extern int uvc_status_resume(struct uvc_device *dev); | ||
749 | |||
750 | /* Controls */ | ||
751 | extern struct uvc_control *uvc_find_control(struct uvc_video_device *video, | ||
752 | __u32 v4l2_id, struct uvc_control_mapping **mapping); | ||
753 | extern int uvc_query_v4l2_ctrl(struct uvc_video_device *video, | ||
754 | struct v4l2_queryctrl *v4l2_ctrl); | ||
755 | |||
756 | extern int uvc_ctrl_add_info(struct uvc_control_info *info); | ||
757 | extern int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping); | ||
758 | extern int uvc_ctrl_init_device(struct uvc_device *dev); | ||
759 | extern void uvc_ctrl_cleanup_device(struct uvc_device *dev); | ||
760 | extern int uvc_ctrl_resume_device(struct uvc_device *dev); | ||
761 | extern void uvc_ctrl_init(void); | ||
762 | |||
763 | extern int uvc_ctrl_begin(struct uvc_video_device *video); | ||
764 | extern int __uvc_ctrl_commit(struct uvc_video_device *video, int rollback); | ||
765 | static inline int uvc_ctrl_commit(struct uvc_video_device *video) | ||
766 | { | ||
767 | return __uvc_ctrl_commit(video, 0); | ||
768 | } | ||
769 | static inline int uvc_ctrl_rollback(struct uvc_video_device *video) | ||
770 | { | ||
771 | return __uvc_ctrl_commit(video, 1); | ||
772 | } | ||
773 | |||
774 | extern int uvc_ctrl_get(struct uvc_video_device *video, | ||
775 | struct v4l2_ext_control *xctrl); | ||
776 | extern int uvc_ctrl_set(struct uvc_video_device *video, | ||
777 | struct v4l2_ext_control *xctrl); | ||
778 | |||
779 | extern int uvc_xu_ctrl_query(struct uvc_video_device *video, | ||
780 | struct uvc_xu_control *ctrl, int set); | ||
781 | |||
782 | /* Utility functions */ | ||
783 | extern void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator, | ||
784 | unsigned int n_terms, unsigned int threshold); | ||
785 | extern uint32_t uvc_fraction_to_interval(uint32_t numerator, | ||
786 | uint32_t denominator); | ||
787 | extern struct usb_host_endpoint *uvc_find_endpoint( | ||
788 | struct usb_host_interface *alts, __u8 epaddr); | ||
789 | |||
790 | /* Quirks support */ | ||
791 | void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video, | ||
792 | struct uvc_buffer *buf); | ||
793 | |||
794 | #endif /* __KERNEL__ */ | ||
795 | |||
796 | #endif | ||
diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 982f4463896c..0a88c44ace00 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c | |||
@@ -331,7 +331,7 @@ int videobuf_mmap_free(struct videobuf_queue *q) | |||
331 | } | 331 | } |
332 | 332 | ||
333 | /* Locking: Caller holds q->vb_lock */ | 333 | /* Locking: Caller holds q->vb_lock */ |
334 | static int __videobuf_mmap_setup(struct videobuf_queue *q, | 334 | int __videobuf_mmap_setup(struct videobuf_queue *q, |
335 | unsigned int bcount, unsigned int bsize, | 335 | unsigned int bcount, unsigned int bsize, |
336 | enum v4l2_memory memory) | 336 | enum v4l2_memory memory) |
337 | { | 337 | { |
@@ -1129,6 +1129,7 @@ EXPORT_SYMBOL_GPL(videobuf_read_stream); | |||
1129 | EXPORT_SYMBOL_GPL(videobuf_read_one); | 1129 | EXPORT_SYMBOL_GPL(videobuf_read_one); |
1130 | EXPORT_SYMBOL_GPL(videobuf_poll_stream); | 1130 | EXPORT_SYMBOL_GPL(videobuf_poll_stream); |
1131 | 1131 | ||
1132 | EXPORT_SYMBOL_GPL(__videobuf_mmap_setup); | ||
1132 | EXPORT_SYMBOL_GPL(videobuf_mmap_setup); | 1133 | EXPORT_SYMBOL_GPL(videobuf_mmap_setup); |
1133 | EXPORT_SYMBOL_GPL(videobuf_mmap_free); | 1134 | EXPORT_SYMBOL_GPL(videobuf_mmap_free); |
1134 | EXPORT_SYMBOL_GPL(videobuf_mmap_mapper); | 1135 | EXPORT_SYMBOL_GPL(videobuf_mmap_mapper); |
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 31e8af0ba278..67a661cf5219 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c | |||
@@ -51,12 +51,51 @@ | |||
51 | #define VIDEO_NUM_DEVICES 256 | 51 | #define VIDEO_NUM_DEVICES 256 |
52 | #define VIDEO_NAME "video4linux" | 52 | #define VIDEO_NAME "video4linux" |
53 | 53 | ||
54 | struct std_descr { | ||
55 | v4l2_std_id std; | ||
56 | const char *descr; | ||
57 | }; | ||
58 | |||
59 | static const struct std_descr standards[] = { | ||
60 | { V4L2_STD_NTSC, "NTSC" }, | ||
61 | { V4L2_STD_NTSC_M, "NTSC-M" }, | ||
62 | { V4L2_STD_NTSC_M_JP, "NTSC-M-JP" }, | ||
63 | { V4L2_STD_NTSC_M_KR, "NTSC-M-KR" }, | ||
64 | { V4L2_STD_NTSC_443, "NTSC-443" }, | ||
65 | { V4L2_STD_PAL, "PAL" }, | ||
66 | { V4L2_STD_PAL_BG, "PAL-BG" }, | ||
67 | { V4L2_STD_PAL_B, "PAL-B" }, | ||
68 | { V4L2_STD_PAL_B1, "PAL-B1" }, | ||
69 | { V4L2_STD_PAL_G, "PAL-G" }, | ||
70 | { V4L2_STD_PAL_H, "PAL-H" }, | ||
71 | { V4L2_STD_PAL_I, "PAL-I" }, | ||
72 | { V4L2_STD_PAL_DK, "PAL-DK" }, | ||
73 | { V4L2_STD_PAL_D, "PAL-D" }, | ||
74 | { V4L2_STD_PAL_D1, "PAL-D1" }, | ||
75 | { V4L2_STD_PAL_K, "PAL-K" }, | ||
76 | { V4L2_STD_PAL_M, "PAL-M" }, | ||
77 | { V4L2_STD_PAL_N, "PAL-N" }, | ||
78 | { V4L2_STD_PAL_Nc, "PAL-Nc" }, | ||
79 | { V4L2_STD_PAL_60, "PAL-60" }, | ||
80 | { V4L2_STD_SECAM, "SECAM" }, | ||
81 | { V4L2_STD_SECAM_B, "SECAM-B" }, | ||
82 | { V4L2_STD_SECAM_G, "SECAM-G" }, | ||
83 | { V4L2_STD_SECAM_H, "SECAM-H" }, | ||
84 | { V4L2_STD_SECAM_DK, "SECAM-DK" }, | ||
85 | { V4L2_STD_SECAM_D, "SECAM-D" }, | ||
86 | { V4L2_STD_SECAM_K, "SECAM-K" }, | ||
87 | { V4L2_STD_SECAM_K1, "SECAM-K1" }, | ||
88 | { V4L2_STD_SECAM_L, "SECAM-L" }, | ||
89 | { V4L2_STD_SECAM_LC, "SECAM-Lc" }, | ||
90 | { 0, "Unknown" } | ||
91 | }; | ||
92 | |||
54 | /* video4linux standard ID conversion to standard name | 93 | /* video4linux standard ID conversion to standard name |
55 | */ | 94 | */ |
56 | char *v4l2_norm_to_name(v4l2_std_id id) | 95 | const char *v4l2_norm_to_name(v4l2_std_id id) |
57 | { | 96 | { |
58 | char *name; | ||
59 | u32 myid = id; | 97 | u32 myid = id; |
98 | int i; | ||
60 | 99 | ||
61 | /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle | 100 | /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle |
62 | 64 bit comparations. So, on that architecture, with some gcc | 101 | 64 bit comparations. So, on that architecture, with some gcc |
@@ -64,110 +103,17 @@ char *v4l2_norm_to_name(v4l2_std_id id) | |||
64 | */ | 103 | */ |
65 | BUG_ON(myid != id); | 104 | BUG_ON(myid != id); |
66 | 105 | ||
67 | switch (myid) { | 106 | for (i = 0; standards[i].std; i++) |
68 | case V4L2_STD_PAL: | 107 | if (myid == standards[i].std) |
69 | name = "PAL"; | 108 | break; |
70 | break; | 109 | return standards[i].descr; |
71 | case V4L2_STD_PAL_BG: | ||
72 | name = "PAL-BG"; | ||
73 | break; | ||
74 | case V4L2_STD_PAL_DK: | ||
75 | name = "PAL-DK"; | ||
76 | break; | ||
77 | case V4L2_STD_PAL_B: | ||
78 | name = "PAL-B"; | ||
79 | break; | ||
80 | case V4L2_STD_PAL_B1: | ||
81 | name = "PAL-B1"; | ||
82 | break; | ||
83 | case V4L2_STD_PAL_G: | ||
84 | name = "PAL-G"; | ||
85 | break; | ||
86 | case V4L2_STD_PAL_H: | ||
87 | name = "PAL-H"; | ||
88 | break; | ||
89 | case V4L2_STD_PAL_I: | ||
90 | name = "PAL-I"; | ||
91 | break; | ||
92 | case V4L2_STD_PAL_D: | ||
93 | name = "PAL-D"; | ||
94 | break; | ||
95 | case V4L2_STD_PAL_D1: | ||
96 | name = "PAL-D1"; | ||
97 | break; | ||
98 | case V4L2_STD_PAL_K: | ||
99 | name = "PAL-K"; | ||
100 | break; | ||
101 | case V4L2_STD_PAL_M: | ||
102 | name = "PAL-M"; | ||
103 | break; | ||
104 | case V4L2_STD_PAL_N: | ||
105 | name = "PAL-N"; | ||
106 | break; | ||
107 | case V4L2_STD_PAL_Nc: | ||
108 | name = "PAL-Nc"; | ||
109 | break; | ||
110 | case V4L2_STD_PAL_60: | ||
111 | name = "PAL-60"; | ||
112 | break; | ||
113 | case V4L2_STD_NTSC: | ||
114 | name = "NTSC"; | ||
115 | break; | ||
116 | case V4L2_STD_NTSC_M: | ||
117 | name = "NTSC-M"; | ||
118 | break; | ||
119 | case V4L2_STD_NTSC_M_JP: | ||
120 | name = "NTSC-M-JP"; | ||
121 | break; | ||
122 | case V4L2_STD_NTSC_443: | ||
123 | name = "NTSC-443"; | ||
124 | break; | ||
125 | case V4L2_STD_NTSC_M_KR: | ||
126 | name = "NTSC-M-KR"; | ||
127 | break; | ||
128 | case V4L2_STD_SECAM: | ||
129 | name = "SECAM"; | ||
130 | break; | ||
131 | case V4L2_STD_SECAM_DK: | ||
132 | name = "SECAM-DK"; | ||
133 | break; | ||
134 | case V4L2_STD_SECAM_B: | ||
135 | name = "SECAM-B"; | ||
136 | break; | ||
137 | case V4L2_STD_SECAM_D: | ||
138 | name = "SECAM-D"; | ||
139 | break; | ||
140 | case V4L2_STD_SECAM_G: | ||
141 | name = "SECAM-G"; | ||
142 | break; | ||
143 | case V4L2_STD_SECAM_H: | ||
144 | name = "SECAM-H"; | ||
145 | break; | ||
146 | case V4L2_STD_SECAM_K: | ||
147 | name = "SECAM-K"; | ||
148 | break; | ||
149 | case V4L2_STD_SECAM_K1: | ||
150 | name = "SECAM-K1"; | ||
151 | break; | ||
152 | case V4L2_STD_SECAM_L: | ||
153 | name = "SECAM-L"; | ||
154 | break; | ||
155 | case V4L2_STD_SECAM_LC: | ||
156 | name = "SECAM-LC"; | ||
157 | break; | ||
158 | default: | ||
159 | name = "Unknown"; | ||
160 | break; | ||
161 | } | ||
162 | |||
163 | return name; | ||
164 | } | 110 | } |
165 | EXPORT_SYMBOL(v4l2_norm_to_name); | 111 | EXPORT_SYMBOL(v4l2_norm_to_name); |
166 | 112 | ||
167 | /* Fill in the fields of a v4l2_standard structure according to the | 113 | /* Fill in the fields of a v4l2_standard structure according to the |
168 | 'id' and 'transmission' parameters. Returns negative on error. */ | 114 | 'id' and 'transmission' parameters. Returns negative on error. */ |
169 | int v4l2_video_std_construct(struct v4l2_standard *vs, | 115 | int v4l2_video_std_construct(struct v4l2_standard *vs, |
170 | int id, char *name) | 116 | int id, const char *name) |
171 | { | 117 | { |
172 | u32 index = vs->index; | 118 | u32 index = vs->index; |
173 | 119 | ||
@@ -1218,95 +1164,40 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
1218 | case VIDIOC_ENUMSTD: | 1164 | case VIDIOC_ENUMSTD: |
1219 | { | 1165 | { |
1220 | struct v4l2_standard *p = arg; | 1166 | struct v4l2_standard *p = arg; |
1221 | v4l2_std_id id = vfd->tvnorms,curr_id=0; | 1167 | v4l2_std_id id = vfd->tvnorms, curr_id = 0; |
1222 | unsigned int index = p->index,i; | 1168 | unsigned int index = p->index, i, j = 0; |
1223 | 1169 | const char *descr = ""; | |
1224 | if (index<0) { | 1170 | |
1225 | ret=-EINVAL; | 1171 | /* Return norm array in a canonical way */ |
1226 | break; | 1172 | for (i = 0; i <= index && id; i++) { |
1227 | } | 1173 | /* last std value in the standards array is 0, so this |
1228 | 1174 | while always ends there since (id & 0) == 0. */ | |
1229 | /* Return norm array on a canonical way */ | 1175 | while ((id & standards[j].std) != standards[j].std) |
1230 | for (i=0;i<= index && id; i++) { | 1176 | j++; |
1231 | if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) { | 1177 | curr_id = standards[j].std; |
1232 | curr_id = V4L2_STD_PAL; | 1178 | descr = standards[j].descr; |
1233 | } else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) { | 1179 | j++; |
1234 | curr_id = V4L2_STD_PAL_BG; | 1180 | if (curr_id == 0) |
1235 | } else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) { | ||
1236 | curr_id = V4L2_STD_PAL_DK; | ||
1237 | } else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) { | ||
1238 | curr_id = V4L2_STD_PAL_B; | ||
1239 | } else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) { | ||
1240 | curr_id = V4L2_STD_PAL_B1; | ||
1241 | } else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) { | ||
1242 | curr_id = V4L2_STD_PAL_G; | ||
1243 | } else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) { | ||
1244 | curr_id = V4L2_STD_PAL_H; | ||
1245 | } else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) { | ||
1246 | curr_id = V4L2_STD_PAL_I; | ||
1247 | } else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) { | ||
1248 | curr_id = V4L2_STD_PAL_D; | ||
1249 | } else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) { | ||
1250 | curr_id = V4L2_STD_PAL_D1; | ||
1251 | } else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) { | ||
1252 | curr_id = V4L2_STD_PAL_K; | ||
1253 | } else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) { | ||
1254 | curr_id = V4L2_STD_PAL_M; | ||
1255 | } else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) { | ||
1256 | curr_id = V4L2_STD_PAL_N; | ||
1257 | } else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) { | ||
1258 | curr_id = V4L2_STD_PAL_Nc; | ||
1259 | } else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) { | ||
1260 | curr_id = V4L2_STD_PAL_60; | ||
1261 | } else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) { | ||
1262 | curr_id = V4L2_STD_NTSC; | ||
1263 | } else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) { | ||
1264 | curr_id = V4L2_STD_NTSC_M; | ||
1265 | } else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) { | ||
1266 | curr_id = V4L2_STD_NTSC_M_JP; | ||
1267 | } else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) { | ||
1268 | curr_id = V4L2_STD_NTSC_443; | ||
1269 | } else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) { | ||
1270 | curr_id = V4L2_STD_NTSC_M_KR; | ||
1271 | } else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) { | ||
1272 | curr_id = V4L2_STD_SECAM; | ||
1273 | } else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) { | ||
1274 | curr_id = V4L2_STD_SECAM_DK; | ||
1275 | } else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) { | ||
1276 | curr_id = V4L2_STD_SECAM_B; | ||
1277 | } else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) { | ||
1278 | curr_id = V4L2_STD_SECAM_D; | ||
1279 | } else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) { | ||
1280 | curr_id = V4L2_STD_SECAM_G; | ||
1281 | } else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) { | ||
1282 | curr_id = V4L2_STD_SECAM_H; | ||
1283 | } else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) { | ||
1284 | curr_id = V4L2_STD_SECAM_K; | ||
1285 | } else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) { | ||
1286 | curr_id = V4L2_STD_SECAM_K1; | ||
1287 | } else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) { | ||
1288 | curr_id = V4L2_STD_SECAM_L; | ||
1289 | } else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) { | ||
1290 | curr_id = V4L2_STD_SECAM_LC; | ||
1291 | } else { | ||
1292 | break; | 1181 | break; |
1293 | } | 1182 | if (curr_id != V4L2_STD_PAL && |
1294 | id &= ~curr_id; | 1183 | curr_id != V4L2_STD_SECAM && |
1184 | curr_id != V4L2_STD_NTSC) | ||
1185 | id &= ~curr_id; | ||
1295 | } | 1186 | } |
1296 | if (i<=index) | 1187 | if (i <= index) |
1297 | return -EINVAL; | 1188 | return -EINVAL; |
1298 | 1189 | ||
1299 | v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id)); | 1190 | v4l2_video_std_construct(p, curr_id, descr); |
1300 | p->index = index; | 1191 | p->index = index; |
1301 | 1192 | ||
1302 | dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " | 1193 | dbgarg(cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " |
1303 | "framelines=%d\n", p->index, | 1194 | "framelines=%d\n", p->index, |
1304 | (unsigned long long)p->id, p->name, | 1195 | (unsigned long long)p->id, p->name, |
1305 | p->frameperiod.numerator, | 1196 | p->frameperiod.numerator, |
1306 | p->frameperiod.denominator, | 1197 | p->frameperiod.denominator, |
1307 | p->framelines); | 1198 | p->framelines); |
1308 | 1199 | ||
1309 | ret=0; | 1200 | ret = 0; |
1310 | break; | 1201 | break; |
1311 | } | 1202 | } |
1312 | case VIDIOC_G_STD: | 1203 | case VIDIOC_G_STD: |
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 845be1864f68..5ff9a58b6135 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
@@ -327,13 +327,14 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) | |||
327 | int hmax = buf->vb.height; | 327 | int hmax = buf->vb.height; |
328 | int wmax = buf->vb.width; | 328 | int wmax = buf->vb.width; |
329 | struct timeval ts; | 329 | struct timeval ts; |
330 | char *tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC); | 330 | char *tmpbuf; |
331 | void *vbuf = videobuf_to_vmalloc(&buf->vb); | 331 | void *vbuf = videobuf_to_vmalloc(&buf->vb); |
332 | 332 | ||
333 | if (!tmpbuf) | 333 | if (!vbuf) |
334 | return; | 334 | return; |
335 | 335 | ||
336 | if (!vbuf) | 336 | tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC); |
337 | if (!tmpbuf) | ||
337 | return; | 338 | return; |
338 | 339 | ||
339 | for (h = 0; h < hmax; h++) { | 340 | for (h = 0; h < hmax; h++) { |
diff --git a/drivers/media/video/vp27smpx.c b/drivers/media/video/vp27smpx.c index fac0deba24af..a1f76ee032e7 100644 --- a/drivers/media/video/vp27smpx.c +++ b/drivers/media/video/vp27smpx.c | |||
@@ -130,8 +130,6 @@ static int vp27smpx_probe(struct i2c_client *client, | |||
130 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 130 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
131 | return -EIO; | 131 | return -EIO; |
132 | 132 | ||
133 | snprintf(client->name, sizeof(client->name) - 1, "vp27smpx"); | ||
134 | |||
135 | v4l_info(client, "chip found @ 0x%x (%s)\n", | 133 | v4l_info(client, "chip found @ 0x%x (%s)\n", |
136 | client->addr << 1, client->adapter->name); | 134 | client->addr << 1, client->adapter->name); |
137 | 135 | ||
@@ -154,11 +152,18 @@ static int vp27smpx_remove(struct i2c_client *client) | |||
154 | 152 | ||
155 | /* ----------------------------------------------------------------------- */ | 153 | /* ----------------------------------------------------------------------- */ |
156 | 154 | ||
155 | static const struct i2c_device_id vp27smpx_id[] = { | ||
156 | { "vp27smpx", 0 }, | ||
157 | { } | ||
158 | }; | ||
159 | MODULE_DEVICE_TABLE(i2c, vp27smpx_id); | ||
160 | |||
157 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 161 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
158 | .name = "vp27smpx", | 162 | .name = "vp27smpx", |
159 | .driverid = I2C_DRIVERID_VP27SMPX, | 163 | .driverid = I2C_DRIVERID_VP27SMPX, |
160 | .command = vp27smpx_command, | 164 | .command = vp27smpx_command, |
161 | .probe = vp27smpx_probe, | 165 | .probe = vp27smpx_probe, |
162 | .remove = vp27smpx_remove, | 166 | .remove = vp27smpx_remove, |
167 | .id_table = vp27smpx_id, | ||
163 | }; | 168 | }; |
164 | 169 | ||
diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c index 0f8ed8461fba..fc50299caa36 100644 --- a/drivers/media/video/wm8739.c +++ b/drivers/media/video/wm8739.c | |||
@@ -313,11 +313,18 @@ static int wm8739_remove(struct i2c_client *client) | |||
313 | return 0; | 313 | return 0; |
314 | } | 314 | } |
315 | 315 | ||
316 | static const struct i2c_device_id wm8739_id[] = { | ||
317 | { "wm8739", 0 }, | ||
318 | { } | ||
319 | }; | ||
320 | MODULE_DEVICE_TABLE(i2c, wm8739_id); | ||
321 | |||
316 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 322 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
317 | .name = "wm8739", | 323 | .name = "wm8739", |
318 | .driverid = I2C_DRIVERID_WM8739, | 324 | .driverid = I2C_DRIVERID_WM8739, |
319 | .command = wm8739_command, | 325 | .command = wm8739_command, |
320 | .probe = wm8739_probe, | 326 | .probe = wm8739_probe, |
321 | .remove = wm8739_remove, | 327 | .remove = wm8739_remove, |
328 | .id_table = wm8739_id, | ||
322 | }; | 329 | }; |
323 | 330 | ||
diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 67a409e60c46..506378a508b9 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c | |||
@@ -216,11 +216,18 @@ static int wm8775_remove(struct i2c_client *client) | |||
216 | return 0; | 216 | return 0; |
217 | } | 217 | } |
218 | 218 | ||
219 | static const struct i2c_device_id wm8775_id[] = { | ||
220 | { "wm8775", 0 }, | ||
221 | { } | ||
222 | }; | ||
223 | MODULE_DEVICE_TABLE(i2c, wm8775_id); | ||
224 | |||
219 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { | 225 | static struct v4l2_i2c_driver_data v4l2_i2c_data = { |
220 | .name = "wm8775", | 226 | .name = "wm8775", |
221 | .driverid = I2C_DRIVERID_WM8775, | 227 | .driverid = I2C_DRIVERID_WM8775, |
222 | .command = wm8775_command, | 228 | .command = wm8775_command, |
223 | .probe = wm8775_probe, | 229 | .probe = wm8775_probe, |
224 | .remove = wm8775_remove, | 230 | .remove = wm8775_remove, |
231 | .id_table = wm8775_id, | ||
225 | }; | 232 | }; |
226 | 233 | ||
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 363dd2b9475c..e5c4e9f5193f 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include <linux/mm.h> | 38 | #include <linux/mm.h> |
39 | #include <linux/vmalloc.h> | 39 | #include <linux/vmalloc.h> |
40 | #include <linux/page-flags.h> | 40 | #include <linux/page-flags.h> |
41 | #include <linux/byteorder/generic.h> | 41 | #include <asm/byteorder.h> |
42 | #include <asm/page.h> | 42 | #include <asm/page.h> |
43 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
44 | 44 | ||
diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h index 81cc3b00a079..46b7ad477ceb 100644 --- a/drivers/media/video/zoran.h +++ b/drivers/media/video/zoran.h | |||
@@ -285,7 +285,7 @@ struct zoran_mapping { | |||
285 | 285 | ||
286 | struct zoran_jpg_buffer { | 286 | struct zoran_jpg_buffer { |
287 | struct zoran_mapping *map; | 287 | struct zoran_mapping *map; |
288 | u32 *frag_tab; /* addresses of frag table */ | 288 | __le32 *frag_tab; /* addresses of frag table */ |
289 | u32 frag_tab_bus; /* same value cached to save time in ISR */ | 289 | u32 frag_tab_bus; /* same value cached to save time in ISR */ |
290 | enum zoran_buffer_state state; /* non-zero if corresponding buffer is in use in grab queue */ | 290 | enum zoran_buffer_state state; /* non-zero if corresponding buffer is in use in grab queue */ |
291 | struct zoran_sync bs; /* DONE: info to return to application */ | 291 | struct zoran_sync bs; /* DONE: info to return to application */ |
@@ -450,7 +450,7 @@ struct zoran { | |||
450 | unsigned long jpg_queued_num; /* count of frames queued since grab/play started */ | 450 | unsigned long jpg_queued_num; /* count of frames queued since grab/play started */ |
451 | 451 | ||
452 | /* zr36057's code buffer table */ | 452 | /* zr36057's code buffer table */ |
453 | u32 *stat_com; /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */ | 453 | __le32 *stat_com; /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */ |
454 | 454 | ||
455 | /* (value & BUZ_MASK_FRAME) corresponds to index in pend[] queue */ | 455 | /* (value & BUZ_MASK_FRAME) corresponds to index in pend[] queue */ |
456 | int jpg_pend[BUZ_MAX_FRAME]; | 456 | int jpg_pend[BUZ_MAX_FRAME]; |
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index 7b60533efe45..88d369708e4c 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/vmalloc.h> | 33 | #include <linux/vmalloc.h> |
34 | #include <linux/byteorder/generic.h> | ||
35 | 34 | ||
36 | #include <linux/interrupt.h> | 35 | #include <linux/interrupt.h> |
37 | #include <linux/proc_fs.h> | 36 | #include <linux/proc_fs.h> |
@@ -47,6 +46,7 @@ | |||
47 | #include <linux/delay.h> | 46 | #include <linux/delay.h> |
48 | #include <linux/wait.h> | 47 | #include <linux/wait.h> |
49 | 48 | ||
49 | #include <asm/byteorder.h> | ||
50 | #include <asm/io.h> | 50 | #include <asm/io.h> |
51 | 51 | ||
52 | #include "videocodec.h" | 52 | #include "videocodec.h" |
@@ -1320,7 +1320,7 @@ error_handler (struct zoran *zr, | |||
1320 | if (i) { | 1320 | if (i) { |
1321 | /* Rotate stat_comm entries to make current entry first */ | 1321 | /* Rotate stat_comm entries to make current entry first */ |
1322 | int j; | 1322 | int j; |
1323 | u32 bus_addr[BUZ_NUM_STAT_COM]; | 1323 | __le32 bus_addr[BUZ_NUM_STAT_COM]; |
1324 | 1324 | ||
1325 | /* Here we are copying the stat_com array, which | 1325 | /* Here we are copying the stat_com array, which |
1326 | * is already in little endian format, so | 1326 | * is already in little endian format, so |
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 0134bec1e399..5394d7a5cfee 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c | |||
@@ -52,7 +52,6 @@ | |||
52 | #include <linux/pci.h> | 52 | #include <linux/pci.h> |
53 | #include <linux/vmalloc.h> | 53 | #include <linux/vmalloc.h> |
54 | #include <linux/wait.h> | 54 | #include <linux/wait.h> |
55 | #include <linux/byteorder/generic.h> | ||
56 | 55 | ||
57 | #include <linux/interrupt.h> | 56 | #include <linux/interrupt.h> |
58 | #include <linux/i2c.h> | 57 | #include <linux/i2c.h> |
@@ -74,6 +73,7 @@ | |||
74 | #include <media/v4l2-common.h> | 73 | #include <media/v4l2-common.h> |
75 | #include "videocodec.h" | 74 | #include "videocodec.h" |
76 | 75 | ||
76 | #include <asm/byteorder.h> | ||
77 | #include <asm/io.h> | 77 | #include <asm/io.h> |
78 | #include <asm/uaccess.h> | 78 | #include <asm/uaccess.h> |
79 | #include <linux/proc_fs.h> | 79 | #include <linux/proc_fs.h> |
@@ -495,7 +495,7 @@ jpg_fbuffer_alloc (struct file *file) | |||
495 | jpg_fbuffer_free(file); | 495 | jpg_fbuffer_free(file); |
496 | return -ENOBUFS; | 496 | return -ENOBUFS; |
497 | } | 497 | } |
498 | fh->jpg_buffers.buffer[i].frag_tab = (u32 *) mem; | 498 | fh->jpg_buffers.buffer[i].frag_tab = (__le32 *) mem; |
499 | fh->jpg_buffers.buffer[i].frag_tab_bus = | 499 | fh->jpg_buffers.buffer[i].frag_tab_bus = |
500 | virt_to_bus((void *) mem); | 500 | virt_to_bus((void *) mem); |
501 | 501 | ||
@@ -1167,7 +1167,7 @@ zoran_close_end_session (struct file *file) | |||
1167 | 1167 | ||
1168 | /* v4l capture */ | 1168 | /* v4l capture */ |
1169 | if (fh->v4l_buffers.active != ZORAN_FREE) { | 1169 | if (fh->v4l_buffers.active != ZORAN_FREE) { |
1170 | long flags; | 1170 | unsigned long flags; |
1171 | 1171 | ||
1172 | spin_lock_irqsave(&zr->spinlock, flags); | 1172 | spin_lock_irqsave(&zr->spinlock, flags); |
1173 | zr36057_set_memgrab(zr, 0); | 1173 | zr36057_set_memgrab(zr, 0); |
@@ -3436,7 +3436,7 @@ zoran_do_ioctl (struct inode *inode, | |||
3436 | 3436 | ||
3437 | /* unload capture */ | 3437 | /* unload capture */ |
3438 | if (zr->v4l_memgrab_active) { | 3438 | if (zr->v4l_memgrab_active) { |
3439 | long flags; | 3439 | unsigned long flags; |
3440 | 3440 | ||
3441 | spin_lock_irqsave(&zr->spinlock, flags); | 3441 | spin_lock_irqsave(&zr->spinlock, flags); |
3442 | zr36057_set_memgrab(zr, 0); | 3442 | zr36057_set_memgrab(zr, 0); |
@@ -4375,7 +4375,7 @@ zoran_vm_close (struct vm_area_struct *vma) | |||
4375 | mutex_lock(&zr->resource_lock); | 4375 | mutex_lock(&zr->resource_lock); |
4376 | 4376 | ||
4377 | if (fh->v4l_buffers.active != ZORAN_FREE) { | 4377 | if (fh->v4l_buffers.active != ZORAN_FREE) { |
4378 | long flags; | 4378 | unsigned long flags; |
4379 | 4379 | ||
4380 | spin_lock_irqsave(&zr->spinlock, flags); | 4380 | spin_lock_irqsave(&zr->spinlock, flags); |
4381 | zr36057_set_memgrab(zr, 0); | 4381 | zr36057_set_memgrab(zr, 0); |
@@ -4506,7 +4506,7 @@ zoran_mmap (struct file *file, | |||
4506 | if (todo > fraglen) | 4506 | if (todo > fraglen) |
4507 | todo = fraglen; | 4507 | todo = fraglen; |
4508 | pos = | 4508 | pos = |
4509 | le32_to_cpu((unsigned long) fh->jpg_buffers. | 4509 | le32_to_cpu(fh->jpg_buffers. |
4510 | buffer[i].frag_tab[2 * j]); | 4510 | buffer[i].frag_tab[2 * j]); |
4511 | /* should just be pos on i386 */ | 4511 | /* should just be pos on i386 */ |
4512 | page = virt_to_phys(bus_to_virt(pos)) | 4512 | page = virt_to_phys(bus_to_virt(pos)) |