Просмотр исходного кода

Merge branch 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb

* 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb: (44 commits)
  V4L/DVB (5571): V4l1-compat:  Make VIDIOCSPICT return errors in a useful way
  V4L/DVB (5624): Radio-maestro.c cleanup
  V4L/DVB (5623): Dsbr100.c Replace usb_dsbr100_do_ioctl to use video_ioctl2
  V4L/DVB (5622): Radio-zoltrix.c cleanup
  V4L/DVB (5621): Radio-cadet.c Replace cadet_do_ioctl to use video_ioctl2
  V4L/DVB (5619): Dvb-usb: fix typo
  V4L/DVB (5618): Cx88: Drop the generic i2c client from cx88-vp3054-i2c
  V4L/DVB (5617): V4L2: videodev, allow debugging
  V4L/DVB (5614): M920x: Disable second adapter on LifeView TV Walker Twin
  V4L/DVB (5613): M920x: loosen up 80-col limit
  V4L/DVB (5612): M920x: rename function prefixes from m9206_foo to m920x_foo
  V4L/DVB (5611): M920x: replace deb_rc with deb
  V4L/DVB (5610): M920x: remove duplicated code
  V4L/DVB (5609): M920x: group like functions together
  V4L/DVB (5608): M920x: various whitespace cleanups
  V4L/DVB (5607): M920x: Initial support for devices likely manufactured by Dposh
  V4L/DVB (5606): M920x: add "c-basic-offset: 8" to help emacs to enforce tabbing
  V4L/DVB (5605): M920x: Add support for LifeView TV Walker Twin
  V4L/DVB (5603): V4L: Prevent queueing queued buffers.
  V4L/DVB (5602): Enable DiSEqC in Starbox II (vp7021a)
  ...
Linus Torvalds 18 лет назад
Родитель
Сommit
57a44415be
65 измененных файлов с 1580 добавлено и 842 удалено
  1. 4 1
      Documentation/video4linux/CARDLIST.saa7134
  2. 10 8
      Documentation/video4linux/sn9c102.txt
  3. 9 0
      drivers/media/Kconfig
  4. 1 1
      drivers/media/Makefile
  5. 35 19
      drivers/media/common/saa7146_core.c
  6. 0 1
      drivers/media/common/saa7146_fops.c
  7. 8 16
      drivers/media/dvb/Kconfig
  8. 12 2
      drivers/media/dvb/dvb-core/Kconfig
  9. 5 0
      drivers/media/dvb/dvb-usb/dvb-usb-ids.h
  10. 1 1
      drivers/media/dvb/dvb-usb/dvb-usb.h
  11. 417 148
      drivers/media/dvb/dvb-usb/m920x.c
  12. 11 2
      drivers/media/dvb/dvb-usb/m920x.h
  13. 7 7
      drivers/media/dvb/dvb-usb/vp702x-fe.c
  14. 8 0
      drivers/media/dvb/pluto2/pluto2.c
  15. 6 3
      drivers/media/dvb/ttpci/av7110.c
  16. 1 1
      drivers/media/dvb/ttpci/budget-ci.c
  17. 20 17
      drivers/media/dvb/ttpci/budget-core.c
  18. 9 2
      drivers/media/radio/Kconfig
  19. 186 159
      drivers/media/radio/dsbr100.c
  20. 179 118
      drivers/media/radio/radio-cadet.c
  21. 0 3
      drivers/media/radio/radio-maestro.c
  22. 0 1
      drivers/media/radio/radio-zoltrix.c
  23. 27 18
      drivers/media/video/Kconfig
  24. 2 2
      drivers/media/video/cx25840/cx25840-core.c
  25. 3 2
      drivers/media/video/cx88/cx88-mpeg.c
  26. 1 0
      drivers/media/video/cx88/cx88-video.c
  27. 0 7
      drivers/media/video/cx88/cx88-vp3054-i2c.c
  28. 0 1
      drivers/media/video/cx88/cx88-vp3054-i2c.h
  29. 1 1
      drivers/media/video/em28xx/Kconfig
  30. 1 1
      drivers/media/video/et61x251/Kconfig
  31. 1 1
      drivers/media/video/ivtv/ivtv-driver.c
  32. 1 1
      drivers/media/video/ivtv/ivtv-fileops.c
  33. 1 1
      drivers/media/video/pvrusb2/Kconfig
  34. 10 3
      drivers/media/video/pvrusb2/pvrusb2-encoder.c
  35. 5 5
      drivers/media/video/pvrusb2/pvrusb2-hdw.c
  36. 22 1
      drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
  37. 0 14
      drivers/media/video/pvrusb2/pvrusb2-sysfs.c
  38. 1 1
      drivers/media/video/pwc/Kconfig
  39. 122 1
      drivers/media/video/saa7134/saa7134-cards.c
  40. 17 0
      drivers/media/video/saa7134/saa7134-dvb.c
  41. 3 0
      drivers/media/video/saa7134/saa7134.h
  42. 1 1
      drivers/media/video/sn9c102/Kconfig
  43. 1 1
      drivers/media/video/sn9c102/sn9c102.h
  44. 43 48
      drivers/media/video/sn9c102/sn9c102_core.c
  45. 3 1
      drivers/media/video/sn9c102/sn9c102_devtable.h
  46. 2 4
      drivers/media/video/sn9c102/sn9c102_hv7131d.c
  47. 2 6
      drivers/media/video/sn9c102/sn9c102_hv7131r.c
  48. 24 27
      drivers/media/video/sn9c102/sn9c102_mi0343.c
  49. 167 53
      drivers/media/video/sn9c102/sn9c102_mi0360.c
  50. 10 15
      drivers/media/video/sn9c102/sn9c102_ov7630.c
  51. 43 20
      drivers/media/video/sn9c102/sn9c102_ov7660.c
  52. 6 8
      drivers/media/video/sn9c102/sn9c102_pas106b.c
  53. 23 25
      drivers/media/video/sn9c102/sn9c102_pas202bcb.c
  54. 18 15
      drivers/media/video/sn9c102/sn9c102_sensor.h
  55. 1 1
      drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
  56. 1 1
      drivers/media/video/sn9c102/sn9c102_tas5110d.c
  57. 1 1
      drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
  58. 4 4
      drivers/media/video/usbvideo/Kconfig
  59. 1 1
      drivers/media/video/usbvision/Kconfig
  60. 45 17
      drivers/media/video/v4l1-compat.c
  61. 1 3
      drivers/media/video/video-buf.c
  62. 31 19
      drivers/media/video/videodev.c
  63. 1 1
      drivers/media/video/zc0301/Kconfig
  64. 2 0
      include/media/saa7146.h
  65. 2 0
      include/media/saa7146_vv.h

+ 4 - 1
Documentation/video4linux/CARDLIST.saa7134

@@ -52,7 +52,7 @@
  51 -> ProVideo PV952                           [1540:9524]
  52 -> AverMedia AverTV/305                     [1461:2108]
  53 -> ASUS TV-FM 7135                          [1043:4845]
- 54 -> LifeView FlyTV Platinum FM / Gold        [5168:0214,1489:0214,5168:0304]
+ 54 -> LifeView FlyTV Platinum FM / Gold        [5168:0214,5168:5214,1489:0214,5168:0304]
  55 -> LifeView FlyDVB-T DUO / MSI TV@nywhere Duo [5168:0306,4E42:0306]
  56 -> Avermedia AVerTV 307                     [1461:a70a]
  57 -> Avermedia AVerTV GO 007 FM               [1461:f31f]
@@ -111,3 +111,6 @@
 110 -> Avermedia M102                           [1461:f31e]
 111 -> ASUS P7131 4871                          [1043:4871]
 112 -> ASUSTeK P7131 Hybrid                     [1043:4876]
+113 -> Elitegroup ECS TVP3XP FM1246 Tuner Card (PAL,FM) [1019:4cb6]
+114 -> KWorld DVB-T 210                         [17de:7250]
+115 -> Sabrent PCMCIA TV-PCB05                  [0919:2003]

+ 10 - 8
Documentation/video4linux/sn9c102.txt

@@ -355,6 +355,9 @@ devices assembling the SN9C1xx PC camera controllers:
 
 Vendor ID  Product ID
 ---------  ----------
+0x0458     0x7025
+0x045e     0x00f5
+0x045e     0x00f7
 0x0471     0x0327
 0x0471     0x0328
 0x0c45     0x6001
@@ -432,7 +435,7 @@ Image sensor / SN9C1xx bridge      | SN9C10[12]  SN9C103  SN9C105  SN9C120
 HV7131D    Hynix Semiconductor     | Yes         No       No       No
 HV7131R    Hynix Semiconductor     | No          Yes      Yes      Yes
 MI-0343    Micron Technology       | Yes         No       No       No
-MI-0360    Micron Technology       | No          Yes      No       No
+MI-0360    Micron Technology       | No          Yes      Yes      Yes
 OV7630     OmniVision Technologies | Yes         Yes      No       No
 OV7660     OmniVision Technologies | No          No       Yes      Yes
 PAS106B    PixArt Imaging          | Yes         No       No       No
@@ -478,13 +481,12 @@ scaling factor is restored to 1.
 This driver supports two different video formats: the first one is the "8-bit
 Sequential Bayer" format and can be used to obtain uncompressed video data
 from the device through the current I/O method, while the second one provides
-"raw" compressed video data (without frame headers not related to the
-compressed data). The compression quality may vary from 0 to 1 and can be
-selected or queried thanks to the VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2
-ioctl's. For maximum flexibility, both the default active video format and the
-default compression quality depend on how the image sensor being used is
-initialized (as described in the documentation of the API for the image sensors
-supplied by this driver).
+either "raw" compressed video data (without frame headers not related to the
+compressed data) or standard JPEG (with frame headers). The compression quality
+may vary from 0 to 1 and can be selected or queried thanks to the
+VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 ioctl's. For maximum flexibility,
+both the default active video format and the default compression quality
+depend on how the image sensor being used is initialized.
 
 
 11. Video frame formats [1]

+ 9 - 0
drivers/media/Kconfig

@@ -87,6 +87,14 @@ config VIDEO_TVEEPROM
 	tristate
 	depends on I2C
 
+config DAB
+	boolean "DAB adapters"
+	default y
+	---help---
+	  Allow selecting support for for Digital Audio Broadcasting (DAB)
+	  Receiver adapters.
+
+if DAB
 config USB_DABUSB
 	tristate "DABUSB driver"
 	depends on USB
@@ -100,5 +108,6 @@ config USB_DABUSB
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called dabusb.
+endif # DAB
 
 endmenu

+ 1 - 1
drivers/media/Makefile

@@ -5,4 +5,4 @@
 obj-y := common/
 obj-$(CONFIG_VIDEO_DEV) += video/
 obj-$(CONFIG_VIDEO_DEV) += radio/
-obj-$(CONFIG_DVB)       += dvb/
+obj-$(CONFIG_DVB_CORE)  += dvb/

+ 35 - 19
drivers/media/common/saa7146_core.c

@@ -136,28 +136,45 @@ char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa
 	char *mem = vmalloc_32(length);
 	int slen = 0;
 
-	if (NULL == mem) {
-		return NULL;
-	}
+	if (NULL == mem)
+		goto err_null;
 
-	if (!(pt->slist = vmalloc_to_sg(mem, pages))) {
-		vfree(mem);
-		return NULL;
-	}
+	if (!(pt->slist = vmalloc_to_sg(mem, pages)))
+		goto err_free_mem;
 
-	if (saa7146_pgtable_alloc(pci, pt)) {
-		kfree(pt->slist);
-		pt->slist = NULL;
-		vfree(mem);
-		return NULL;
-	}
+	if (saa7146_pgtable_alloc(pci, pt))
+		goto err_free_slist;
 
-	slen = pci_map_sg(pci,pt->slist,pages,PCI_DMA_FROMDEVICE);
-	if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) {
-		return NULL;
-	}
+	pt->nents = pages;
+	slen = pci_map_sg(pci,pt->slist,pt->nents,PCI_DMA_FROMDEVICE);
+	if (0 == slen)
+		goto err_free_pgtable;
+
+	if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen))
+		goto err_unmap_sg;
 
 	return mem;
+
+err_unmap_sg:
+	pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE);
+err_free_pgtable:
+	saa7146_pgtable_free(pci, pt);
+err_free_slist:
+	kfree(pt->slist);
+	pt->slist = NULL;
+err_free_mem:
+	vfree(mem);
+err_null:
+	return NULL;
+}
+
+void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, char *mem, struct saa7146_pgtable *pt)
+{
+	pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE);
+	saa7146_pgtable_free(pci, pt);
+	kfree(pt->slist);
+	pt->slist = NULL;
+	vfree(mem);
 }
 
 void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
@@ -166,8 +183,6 @@ void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
 		return;
 	pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
 	pt->cpu = NULL;
-	kfree(pt->slist);
-	pt->slist = NULL;
 }
 
 int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
@@ -528,6 +543,7 @@ EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc);
 EXPORT_SYMBOL_GPL(saa7146_pgtable_free);
 EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single);
 EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable);
+EXPORT_SYMBOL_GPL(saa7146_vfree_destroy_pgtable);
 EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done);
 
 EXPORT_SYMBOL_GPL(saa7146_setgpio);

+ 0 - 1
drivers/media/common/saa7146_fops.c

@@ -307,7 +307,6 @@ static int fops_release(struct inode *inode, struct file *file)
 	return 0;
 }
 
-int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg);
 static int fops_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
 /*

+ 8 - 16
drivers/media/dvb/Kconfig

@@ -2,24 +2,16 @@
 # Multimedia device configuration
 #
 
-menu "Digital Video Broadcasting Devices"
+source "drivers/media/dvb/dvb-core/Kconfig"
 
-config DVB
-	bool "DVB For Linux"
-	depends on NET && INET
+menuconfig DVB_CAPTURE_DRIVERS
+	bool "DVB/ATSC adapters"
+	depends on DVB_CORE
+	default y
 	---help---
-	  Support Digital Video Broadcasting hardware.  Enable this if you
-	  own a DVB adapter and want to use it or if you compile Linux for
-	  a digital SetTopBox.
-
-	  API specs and user tools are available from <http://www.linuxtv.org/>.
+	  Say Y to select Digital TV adapters
 
-	  Please report problems regarding this driver to the LinuxDVB
-	  mailing list.
-
-	  If unsure say N.
-
-source "drivers/media/dvb/dvb-core/Kconfig"
+if DVB_CAPTURE_DRIVERS
 
 comment "Supported SAA7146 based PCI Adapters"
 	depends on DVB_CORE && PCI && I2C
@@ -48,4 +40,4 @@ comment "Supported DVB Frontends"
 	depends on DVB_CORE
 source "drivers/media/dvb/frontends/Kconfig"
 
-endmenu
+endif # DVB_CAPTURE_DRIVERS

+ 12 - 2
drivers/media/dvb/dvb-core/Kconfig

@@ -1,12 +1,22 @@
 config DVB_CORE
-	tristate "DVB Core Support"
-	depends on DVB
+	tristate "DVB for Linux"
+	depends on NET && INET
 	select CRC32
 	help
+	  Support Digital Video Broadcasting hardware.  Enable this if you
+	  own a DVB adapter and want to use it or if you compile Linux for
+	  a digital SetTopBox.
+
 	  DVB core utility functions for device handling, software fallbacks etc.
 	  Say Y when you have a DVB card and want to use it. Say Y if your want
 	  to build your drivers outside the kernel, but need the DVB core. All
 	  in-kernel drivers will select this automatically if needed.
+
+	  API specs and user tools are available from <http://www.linuxtv.org/>.
+
+	  Please report problems regarding this driver to the LinuxDVB
+	  mailing list.
+
 	  If unsure say N.
 
 config DVB_CORE_ATTACH

+ 5 - 0
drivers/media/dvb/dvb-usb/dvb-usb-ids.h

@@ -19,6 +19,7 @@
 #define USB_VID_COMPRO_UNK			0x145f
 #define USB_VID_CYPRESS				0x04b4
 #define USB_VID_DIBCOM				0x10b8
+#define USB_VID_DPOSH				0x1498
 #define USB_VID_DVICO				0x0fe9
 #define USB_VID_EMPIA				0xeb1a
 #define USB_VID_GENPIX				0x09c0
@@ -61,6 +62,8 @@
 #define USB_PID_DIBCOM_STK7700P				0x1e14
 #define USB_PID_DIBCOM_STK7700P_PC			0x1e78
 #define USB_PID_DIBCOM_ANCHOR_2135_COLD			0x2131
+#define USB_PID_DPOSH_M9206_COLD			0x9206
+#define USB_PID_DPOSH_M9206_WARM			0xa090
 #define USB_PID_UNIWILL_STK7700P			0x6003
 #define USB_PID_GRANDTEC_DVBT_USB_COLD			0x0fa0
 #define USB_PID_GRANDTEC_DVBT_USB_WARM			0x0fa1
@@ -145,6 +148,8 @@
 #define USB_PID_MSI_DIGI_VOX_MINI_II			0x1513
 #define USB_PID_OPERA1_COLD				0x2830
 #define USB_PID_OPERA1_WARM				0x3829
+#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD		0x0514
+#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM		0x0513
 
 
 #endif

+ 1 - 1
drivers/media/dvb/dvb-usb/dvb-usb.h

@@ -119,7 +119,7 @@ struct usb_data_stream_properties {
  * @caps: capabilities of the DVB USB device.
  * @pid_filter_count: number of PID filter position in the optional hardware
  *  PID-filter.
- * @streaming_crtl: called to start and stop the MPEG2-TS streaming of the
+ * @streaming_ctrl: called to start and stop the MPEG2-TS streaming of the
  *  device (not URB submitting/killing).
  * @pid_filter_ctrl: called to en/disable the PID filter, if any.
  * @pid_filter: called to set/unset a PID for filtering.

+ 417 - 148
drivers/media/dvb/dvb-usb/m920x.c

@@ -3,8 +3,8 @@
  * Copyright (C) 2006 Aapo Tahkola (aet@rasterburn.org)
  *
  *	This program is free software; you can redistribute it and/or modify it
- *	under the terms of the GNU General Public License as published by the Free
- *	Software Foundation, version 2.
+ *	under the terms of the GNU General Public License as published by the
+ *	Free Software Foundation, version 2.
  *
  * see Documentation/dvb/README.dvb-usb for more information
  */
@@ -22,26 +22,7 @@ static int dvb_usb_m920x_debug;
 module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
 
-static struct dvb_usb_rc_key megasky_rc_keys [] = {
-	{ 0x0, 0x12, KEY_POWER },
-	{ 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */
-	{ 0x0, 0x02, KEY_CHANNELUP },
-	{ 0x0, 0x05, KEY_CHANNELDOWN },
-	{ 0x0, 0x03, KEY_VOLUMEUP },
-	{ 0x0, 0x06, KEY_VOLUMEDOWN },
-	{ 0x0, 0x04, KEY_MUTE },
-	{ 0x0, 0x07, KEY_OK }, /* TS */
-	{ 0x0, 0x08, KEY_STOP },
-	{ 0x0, 0x09, KEY_MENU }, /* swap */
-	{ 0x0, 0x0a, KEY_REWIND },
-	{ 0x0, 0x1b, KEY_PAUSE },
-	{ 0x0, 0x1f, KEY_FASTFORWARD },
-	{ 0x0, 0x0c, KEY_RECORD },
-	{ 0x0, 0x0d, KEY_CAMERA }, /* screenshot */
-	{ 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */
-};
-
-static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\
+static inline int m920x_read(struct usb_device *udev, u8 request, u16 value,
 			     u16 index, void *data, int size)
 {
 	int ret;
@@ -55,14 +36,14 @@ static inline int m9206_read(struct usb_device *udev, u8 request, u16 value,\
 	}
 
 	if (ret != size) {
-		deb_rc("m920x_read = no data\n");
+		deb("m920x_read = no data\n");
 		return -EIO;
 	}
 
 	return 0;
 }
 
-static inline int m9206_write(struct usb_device *udev, u8 request,
+static inline int m920x_write(struct usb_device *udev, u8 request,
 			      u16 value, u16 index)
 {
 	int ret;
@@ -74,32 +55,40 @@ static inline int m9206_write(struct usb_device *udev, u8 request,
 	return ret;
 }
 
-static int m9206_init(struct dvb_usb_device *d)
+static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq)
 {
 	int ret = 0;
 
 	/* Remote controller init. */
 	if (d->props.rc_query) {
-		if ((ret = m9206_write(d->udev, M9206_CORE, 0xa8, M9206_RC_INIT2)) != 0)
-			return ret;
+		deb("Initialising remote control\n");
+		while (rc_seq->address) {
+			if ((ret = m920x_write(d->udev, M9206_CORE,
+					       rc_seq->data,
+					       rc_seq->address)) != 0) {
+				deb("Initialising remote control failed\n");
+				return ret;
+			}
 
-		if ((ret = m9206_write(d->udev, M9206_CORE, 0x51, M9206_RC_INIT1)) != 0)
-			return ret;
+			rc_seq++;
+		}
+
+		deb("Initialising remote control success\n");
 	}
 
 	return ret;
 }
 
-static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
-	struct m9206_state *m = d->priv;
+	struct m920x_state *m = d->priv;
 	int i, ret = 0;
 	u8 rc_state[2];
 
-	if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0)
+	if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0)
 		goto unlock;
 
-	if ((ret = m9206_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
+	if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
 		goto unlock;
 
 	for (i = 0; i < d->props.rc_key_map_size; i++)
@@ -111,6 +100,14 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 				*state = REMOTE_NO_KEY_PRESSED;
 				goto unlock;
 
+			case 0x88: /* framing error or "invalid code" */
+			case 0x99:
+			case 0xc0:
+			case 0xd8:
+				*state = REMOTE_NO_KEY_PRESSED;
+				m->rep_count = 0;
+				goto unlock;
+
 			case 0x93:
 			case 0x92:
 				m->rep_count = 0;
@@ -118,31 +115,32 @@ static int m9206_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 				goto unlock;
 
 			case 0x91:
-				/* For comfort. */
+				/* prevent immediate auto-repeat */
 				if (++m->rep_count > 2)
 					*state = REMOTE_KEY_REPEAT;
+				else
+					*state = REMOTE_NO_KEY_PRESSED;
 				goto unlock;
 
 			default:
-				deb_rc("Unexpected rc response %x\n", rc_state[0]);
+				deb("Unexpected rc state %02x\n", rc_state[0]);
 				*state = REMOTE_NO_KEY_PRESSED;
 				goto unlock;
 			}
 		}
 
 	if (rc_state[1] != 0)
-		deb_rc("Unknown rc key %x\n", rc_state[1]);
+		deb("Unknown rc key %02x\n", rc_state[1]);
 
 	*state = REMOTE_NO_KEY_PRESSED;
 
-	unlock:
+ unlock:
 
 	return ret;
 }
 
 /* I2C */
-static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-			  int num)
+static int m920x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
 {
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
 	int i, j;
@@ -155,33 +153,40 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
 		return -EAGAIN;
 
 	for (i = 0; i < num; i++) {
-		if (msg[i].flags & (I2C_M_NO_RD_ACK|I2C_M_IGNORE_NAK|I2C_M_TEN) ||
-		    msg[i].len == 0) {
-			/* For a 0 byte message, I think sending the address to index 0x80|0x40
-			 * would be the correct thing to do.  However, zero byte messages are
-			 * only used for probing, and since we don't know how to get the slave's
-			 * ack, we can't probe. */
+		if (msg[i].flags & (I2C_M_NO_RD_ACK | I2C_M_IGNORE_NAK | I2C_M_TEN) || msg[i].len == 0) {
+			/* For a 0 byte message, I think sending the address
+			 * to index 0x80|0x40 would be the correct thing to
+			 * do.  However, zero byte messages are only used for
+			 * probing, and since we don't know how to get the
+			 * slave's ack, we can't probe. */
 			ret = -ENOTSUPP;
 			goto unlock;
 		}
 		/* Send START & address/RW bit */
 		if (!(msg[i].flags & I2C_M_NOSTART)) {
-			if ((ret = m9206_write(d->udev, M9206_I2C, (msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0), 0x80)) != 0)
+			if ((ret = m920x_write(d->udev, M9206_I2C,
+					(msg[i].addr << 1) |
+					(msg[i].flags & I2C_M_RD ? 0x01 : 0), 0x80)) != 0)
 				goto unlock;
 			/* Should check for ack here, if we knew how. */
 		}
 		if (msg[i].flags & I2C_M_RD) {
 			for (j = 0; j < msg[i].len; j++) {
-				/* Last byte of transaction? Send STOP, otherwise send ACK. */
-				int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x01;
-				if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x20|stop, &msg[i].buf[j], 1)) != 0)
+				/* Last byte of transaction?
+				 * Send STOP, otherwise send ACK. */
+				int stop = (i+1 == num && j+1 == msg[i].len) ? 0x40 : 0x01;
+
+				if ((ret = m920x_read(d->udev, M9206_I2C, 0x0,
+						      0x20 | stop,
+						      &msg[i].buf[j], 1)) != 0)
 					goto unlock;
 			}
 		} else {
 			for (j = 0; j < msg[i].len; j++) {
 				/* Last byte of transaction? Then send STOP. */
-				int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x00;
-				if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0)
+				int stop = (i+1 == num && j+1 == msg[i].len) ? 0x40 : 0x00;
+
+				if ((ret = m920x_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0)
 					goto unlock;
 				/* Should check for ack here too. */
 			}
@@ -189,25 +194,25 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
 	}
 	ret = num;
 
-unlock:
+ unlock:
 	mutex_unlock(&d->i2c_mutex);
 
 	return ret;
 }
 
-static u32 m9206_i2c_func(struct i2c_adapter *adapter)
+static u32 m920x_i2c_func(struct i2c_adapter *adapter)
 {
 	return I2C_FUNC_I2C;
 }
 
-static struct i2c_algorithm m9206_i2c_algo = {
-	.master_xfer   = m9206_i2c_xfer,
-	.functionality = m9206_i2c_func,
+static struct i2c_algorithm m920x_i2c_algo = {
+	.master_xfer   = m920x_i2c_xfer,
+	.functionality = m920x_i2c_func,
 };
 
-
-static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx,
-			    int pid)
+/* pid filter */
+static int m920x_set_filter(struct dvb_usb_adapter *adap,
+			    int type, int idx, int pid)
 {
 	int ret = 0;
 
@@ -216,18 +221,18 @@ static int m9206_set_filter(struct dvb_usb_adapter *adap, int type, int idx,
 
 	pid |= 0x8000;
 
-	if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0)
+	if ((ret = m920x_write(adap->dev->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0)
 		return ret;
 
-	if ((ret = m9206_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0)
+	if ((ret = m920x_write(adap->dev->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0)
 		return ret;
 
 	return ret;
 }
 
-static int m9206_update_filters(struct dvb_usb_adapter *adap)
+static int m920x_update_filters(struct dvb_usb_adapter *adap)
 {
-	struct m9206_state *m = adap->dev->priv;
+	struct m920x_state *m = adap->dev->priv;
 	int enabled = m->filtering_enabled;
 	int i, ret = 0, filter = 0;
 
@@ -236,14 +241,14 @@ static int m9206_update_filters(struct dvb_usb_adapter *adap)
 			enabled = 0;
 
 	/* Disable all filters */
-	if ((ret = m9206_set_filter(adap, 0x81, 1, enabled)) != 0)
+	if ((ret = m920x_set_filter(adap, 0x81, 1, enabled)) != 0)
 		return ret;
 
 	for (i = 0; i < M9206_MAX_FILTERS; i++)
-		if ((ret = m9206_set_filter(adap, 0x81, i + 2, 0)) != 0)
+		if ((ret = m920x_set_filter(adap, 0x81, i + 2, 0)) != 0)
 			return ret;
 
-	if ((ret = m9206_set_filter(adap, 0x82, 0, 0x0)) != 0)
+	if ((ret = m920x_set_filter(adap, 0x82, 0, 0x0)) != 0)
 		return ret;
 
 	/* Set */
@@ -252,40 +257,38 @@ static int m9206_update_filters(struct dvb_usb_adapter *adap)
 			if (m->filters[i] == 0)
 				continue;
 
-			if ((ret = m9206_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0)
+			if ((ret = m920x_set_filter(adap, 0x81, filter + 2, m->filters[i])) != 0)
 				return ret;
 
 			filter++;
 		}
 	}
 
-	if ((ret = m9206_set_filter(adap, 0x82, 0, 0x02f5)) != 0)
+	if ((ret = m920x_set_filter(adap, 0x82, 0, 0x02f5)) != 0)
 		return ret;
 
 	return ret;
 }
 
-static int m9206_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
+static int m920x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
-	struct m9206_state *m = adap->dev->priv;
+	struct m920x_state *m = adap->dev->priv;
 
 	m->filtering_enabled = onoff ? 1 : 0;
 
-	return m9206_update_filters(adap);
+	return m920x_update_filters(adap);
 }
 
-static int m9206_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
-			    int onoff)
+static int m920x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
 {
-	struct m9206_state *m = adap->dev->priv;
+	struct m920x_state *m = adap->dev->priv;
 
 	m->filters[index] = onoff ? pid : 0;
 
-	return m9206_update_filters(adap);
+	return m920x_update_filters(adap);
 }
 
-static int m9206_firmware_download(struct usb_device *udev,
-				   const struct firmware *fw)
+static int m920x_firmware_download(struct usb_device *udev, const struct firmware *fw)
 {
 	u16 value, index, size;
 	u8 read[4], *buff;
@@ -293,13 +296,13 @@ static int m9206_firmware_download(struct usb_device *udev,
 
 	buff = kmalloc(65536, GFP_KERNEL);
 
-	if ((ret = m9206_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0)
+	if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0)
 		goto done;
-	deb_rc("%x %x %x %x\n", read[0], read[1], read[2], read[3]);
+	deb("%x %x %x %x\n", read[0], read[1], read[2], read[3]);
 
-	if ((ret = m9206_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0)
+	if ((ret = m920x_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0)
 		goto done;
-	deb_rc("%x\n", read[0]);
+	deb("%x\n", read[0]);
 
 	for (pass = 0; pass < 2; pass++) {
 		for (i = 0; i + (sizeof(u16) * 3) < fw->size;) {
@@ -317,11 +320,11 @@ static int m9206_firmware_download(struct usb_device *udev,
 				memcpy(buff, fw->data + i, size);
 
 				ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
-					    M9206_FW,
-					    USB_TYPE_VENDOR | USB_DIR_OUT,
-					    value, index, buff, size, 20);
+						      M9206_FW,
+						      USB_TYPE_VENDOR | USB_DIR_OUT,
+						      value, index, buff, size, 20);
 				if (ret != size) {
-					deb_rc("error while uploading fw!\n");
+					deb("error while uploading fw!\n");
 					ret = -EIO;
 					goto done;
 				}
@@ -330,7 +333,7 @@ static int m9206_firmware_download(struct usb_device *udev,
 			i += size;
 		}
 		if (i != fw->size) {
-			deb_rc("bad firmware file!\n");
+			deb("bad firmware file!\n");
 			ret = -EINVAL;
 			goto done;
 		}
@@ -338,11 +341,11 @@ static int m9206_firmware_download(struct usb_device *udev,
 
 	msleep(36);
 
-	/* m9206 will disconnect itself from the bus after this. */
-	(void) m9206_write(udev, M9206_CORE, 0x01, M9206_FW_GO);
-	deb_rc("firmware uploaded!\n");
+	/* m920x will disconnect itself from the bus after this. */
+	(void) m920x_write(udev, M9206_CORE, 0x01, M9206_FW_GO);
+	deb("firmware uploaded!\n");
 
-	done:
+ done:
 	kfree(buff);
 
 	return ret;
@@ -362,7 +365,8 @@ static int m920x_identify_state(struct usb_device *udev,
 	return 0;
 }
 
-static int megasky_mt352_demod_init(struct dvb_frontend *fe)
+/* demod configurations */
+static int m920x_mt352_demod_init(struct dvb_frontend *fe)
 {
 	u8 config[] = { CONFIG, 0x3d };
 	u8 clock[] = { CLOCK_CTL, 0x30 };
@@ -382,74 +386,174 @@ static int megasky_mt352_demod_init(struct dvb_frontend *fe)
 	mt352_write(fe, unk1, ARRAY_SIZE(unk1));
 	mt352_write(fe, unk2, ARRAY_SIZE(unk2));
 
-	deb_rc("Demod init!\n");
+	deb("Demod init!\n");
 
 	return 0;
 }
 
-static struct mt352_config megasky_mt352_config = {
+static struct mt352_config m920x_mt352_config = {
 	.demod_address = 0x0f,
 	.no_tuner = 1,
-	.demod_init = megasky_mt352_demod_init,
+	.demod_init = m920x_mt352_demod_init,
+};
+
+static struct tda1004x_config m920x_tda10046_08_config = {
+	.demod_address = 0x08,
+	.invert = 0,
+	.invert_oclk = 0,
+	.ts_mode = TDA10046_TS_SERIAL,
+	.xtal_freq = TDA10046_XTAL_16M,
+	.if_freq = TDA10046_FREQ_045,
+	.agc_config = TDA10046_AGC_TDA827X,
+	.gpio_config = TDA10046_GPTRI,
+	.request_firmware = NULL,
+};
+
+static struct tda1004x_config m920x_tda10046_0b_config = {
+	.demod_address = 0x0b,
+	.invert = 0,
+	.invert_oclk = 0,
+	.ts_mode = TDA10046_TS_SERIAL,
+	.xtal_freq = TDA10046_XTAL_16M,
+	.if_freq = TDA10046_FREQ_045,
+	.agc_config = TDA10046_AGC_TDA827X,
+	.gpio_config = TDA10046_GPTRI,
+	.request_firmware = NULL, /* uses firmware EEPROM */
+};
+
+/* tuner configurations */
+static struct qt1010_config m920x_qt1010_config = {
+	.i2c_address = 0x62
 };
 
-static int megasky_mt352_frontend_attach(struct dvb_usb_adapter *adap)
+/* Callbacks for DVB USB */
+static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	deb_rc("megasky_frontend_attach!\n");
+	deb("%s\n",__FUNCTION__);
 
-	if ((adap->fe = dvb_attach(mt352_attach, &megasky_mt352_config, &adap->dev->i2c_adap)) == NULL)
+	if ((adap->fe = dvb_attach(mt352_attach,
+				   &m920x_mt352_config,
+				   &adap->dev->i2c_adap)) == NULL)
 		return -EIO;
 
 	return 0;
 }
 
-static struct qt1010_config megasky_qt1010_config = {
-	.i2c_address = 0x62
-};
-
-static int megasky_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
+static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap,
-		       &megasky_qt1010_config) == NULL)
-		return -ENODEV;
+	deb("%s\n",__FUNCTION__);
+
+	if ((adap->fe = dvb_attach(tda10046_attach,
+				   &m920x_tda10046_08_config,
+				   &adap->dev->i2c_adap)) == NULL)
+		return -EIO;
 
 	return 0;
 }
 
-static struct tda1004x_config digivox_tda10046_config = {
-	.demod_address = 0x08,
-	.invert = 0,
-	.invert_oclk = 0,
-	.ts_mode = TDA10046_TS_SERIAL,
-	.xtal_freq = TDA10046_XTAL_16M,
-	.if_freq = TDA10046_FREQ_045,
-	.agc_config = TDA10046_AGC_TDA827X,
-	.gpio_config = TDA10046_GPTRI,
-	.request_firmware = NULL,
-};
-
-static int digivox_tda10046_frontend_attach(struct dvb_usb_adapter *adap)
+static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	deb_rc("digivox_tda10046_frontend_attach!\n");
+	deb("%s\n",__FUNCTION__);
 
-	if ((adap->fe = dvb_attach(tda10046_attach, &digivox_tda10046_config,
+	if ((adap->fe = dvb_attach(tda10046_attach,
+				   &m920x_tda10046_0b_config,
 				   &adap->dev->i2c_adap)) == NULL)
 		return -EIO;
 
 	return 0;
 }
 
-static int digivox_tda8275_tuner_attach(struct dvb_usb_adapter *adap)
+static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap,
-		       NULL) == NULL)
+	deb("%s\n",__FUNCTION__);
+
+	if (dvb_attach(qt1010_attach, adap->fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
 		return -ENODEV;
+
 	return 0;
 }
 
+static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	deb("%s\n",__FUNCTION__);
+
+	if (dvb_attach(tda827x_attach, adap->fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	deb("%s\n",__FUNCTION__);
+
+	if (dvb_attach(tda827x_attach, adap->fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
+		return -ENODEV;
+
+	return 0;
+}
+
+/* device-specific initialization */
+static struct m920x_inits megasky_rc_init [] = {
+	{ M9206_RC_INIT2, 0xa8 },
+	{ M9206_RC_INIT1, 0x51 },
+	{ } /* terminating entry */
+};
+
+static struct m920x_inits tvwalkertwin_rc_init [] = {
+	{ M9206_RC_INIT2, 0x00 },
+	{ M9206_RC_INIT1, 0xef },
+	{ 0xff28,         0x00 },
+	{ 0xff23,         0x00 },
+	{ 0xff21,         0x30 },
+	{ } /* terminating entry */
+};
+
+/* ir keymaps */
+static struct dvb_usb_rc_key megasky_rc_keys [] = {
+	{ 0x0, 0x12, KEY_POWER },
+	{ 0x0, 0x1e, KEY_CYCLEWINDOWS }, /* min/max */
+	{ 0x0, 0x02, KEY_CHANNELUP },
+	{ 0x0, 0x05, KEY_CHANNELDOWN },
+	{ 0x0, 0x03, KEY_VOLUMEUP },
+	{ 0x0, 0x06, KEY_VOLUMEDOWN },
+	{ 0x0, 0x04, KEY_MUTE },
+	{ 0x0, 0x07, KEY_OK }, /* TS */
+	{ 0x0, 0x08, KEY_STOP },
+	{ 0x0, 0x09, KEY_MENU }, /* swap */
+	{ 0x0, 0x0a, KEY_REWIND },
+	{ 0x0, 0x1b, KEY_PAUSE },
+	{ 0x0, 0x1f, KEY_FASTFORWARD },
+	{ 0x0, 0x0c, KEY_RECORD },
+	{ 0x0, 0x0d, KEY_CAMERA }, /* screenshot */
+	{ 0x0, 0x0e, KEY_COFFEE }, /* "MTS" */
+};
+
+static struct dvb_usb_rc_key tvwalkertwin_rc_keys [] = {
+	{ 0x0, 0x01, KEY_ZOOM }, /* Full Screen */
+	{ 0x0, 0x02, KEY_CAMERA }, /* snapshot */
+	{ 0x0, 0x03, KEY_MUTE },
+	{ 0x0, 0x04, KEY_REWIND },
+	{ 0x0, 0x05, KEY_PLAYPAUSE }, /* Play/Pause */
+	{ 0x0, 0x06, KEY_FASTFORWARD },
+	{ 0x0, 0x07, KEY_RECORD },
+	{ 0x0, 0x08, KEY_STOP },
+	{ 0x0, 0x09, KEY_TIME }, /* Timeshift */
+	{ 0x0, 0x0c, KEY_COFFEE }, /* Recall */
+	{ 0x0, 0x0e, KEY_CHANNELUP },
+	{ 0x0, 0x12, KEY_POWER },
+	{ 0x0, 0x15, KEY_MENU }, /* source */
+	{ 0x0, 0x18, KEY_CYCLEWINDOWS }, /* TWIN PIP */
+	{ 0x0, 0x1a, KEY_CHANNELDOWN },
+	{ 0x0, 0x1b, KEY_VOLUMEDOWN },
+	{ 0x0, 0x1e, KEY_VOLUMEUP },
+};
+
 /* DVB USB Driver stuff */
 static struct dvb_usb_device_properties megasky_properties;
 static struct dvb_usb_device_properties digivox_mini_ii_properties;
+static struct dvb_usb_device_properties tvwalkertwin_properties;
+static struct dvb_usb_device_properties dposh_properties;
 
 static int m920x_probe(struct usb_interface *intf,
 		       const struct usb_device_id *id)
@@ -457,19 +561,57 @@ static int m920x_probe(struct usb_interface *intf,
 	struct dvb_usb_device *d;
 	struct usb_host_interface *alt;
 	int ret;
+	struct m920x_inits *rc_init_seq = NULL;
+	int bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber;
 
-	deb_rc("Probed!\n");
+	deb("Probing for m920x device at interface %d\n", bInterfaceNumber);
 
-	if (((ret = dvb_usb_device_init(intf, &megasky_properties, THIS_MODULE, &d)) == 0) ||
-	    ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties, THIS_MODULE, &d)) == 0))
-		goto found;
+	if (bInterfaceNumber == 0) {
+		/* Single-tuner device, or first interface on
+		 * multi-tuner device
+		 */
 
-	return ret;
+		if ((ret = dvb_usb_device_init(intf, &megasky_properties,
+					       THIS_MODULE, &d)) == 0) {
+			rc_init_seq = megasky_rc_init;
+			goto found;
+		}
+
+		if ((ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties,
+					       THIS_MODULE, &d)) == 0) {
+			/* No remote control, so no rc_init_seq */
+			goto found;
+		}
+
+		/* This configures both tuners on the TV Walker Twin */
+		if ((ret = dvb_usb_device_init(intf, &tvwalkertwin_properties,
+					       THIS_MODULE, &d)) == 0) {
+			rc_init_seq = tvwalkertwin_rc_init;
+			goto found;
+		}
+
+		if ((ret = dvb_usb_device_init(intf, &dposh_properties,
+					       THIS_MODULE, &d)) == 0) {
+			/* Remote controller not supported yet. */
+			goto found;
+		}
+
+		return ret;
+	} else {
+		/* Another interface on a multi-tuner device */
 
-found:
+		/* The LifeView TV Walker Twin gets here, but struct
+		 * tvwalkertwin_properties already configured both
+		 * tuners, so there is nothing for us to do here
+		 */
+
+		return -ENODEV;
+	}
+
+ found:
 	alt = usb_altnum_to_altsetting(intf, 1);
 	if (alt == NULL) {
-		deb_rc("No alt found!\n");
+		deb("No alt found!\n");
 		return -ENODEV;
 	}
 
@@ -478,7 +620,7 @@ found:
 	if (ret < 0)
 		return ret;
 
-	if ((ret = m9206_init(d)) != 0)
+	if ((ret = m920x_init(d, rc_init_seq)) != 0)
 		return ret;
 
 	return ret;
@@ -488,6 +630,12 @@ static struct usb_device_id m920x_table [] = {
 		{ USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) },
 		{ USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC,
 			     USB_PID_MSI_DIGI_VOX_MINI_II) },
+		{ USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC,
+			     USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD) },
+		{ USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC,
+			     USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM) },
+		{ USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_COLD) },
+		{ USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_WARM) },
 		{ }		/* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, m920x_table);
@@ -497,14 +645,14 @@ static struct dvb_usb_device_properties megasky_properties = {
 
 	.usb_ctrl = DEVICE_SPECIFIC,
 	.firmware = "dvb-usb-megasky-02.fw",
-	.download_firmware = m9206_firmware_download,
+	.download_firmware = m920x_firmware_download,
 
 	.rc_interval      = 100,
 	.rc_key_map       = megasky_rc_keys,
 	.rc_key_map_size  = ARRAY_SIZE(megasky_rc_keys),
-	.rc_query         = m9206_rc_query,
+	.rc_query         = m920x_rc_query,
 
-	.size_of_priv     = sizeof(struct m9206_state),
+	.size_of_priv     = sizeof(struct m920x_state),
 
 	.identify_state   = m920x_identify_state,
 	.num_adapters = 1,
@@ -513,11 +661,11 @@ static struct dvb_usb_device_properties megasky_properties = {
 			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
 		.pid_filter_count = 8,
-		.pid_filter       = m9206_pid_filter,
-		.pid_filter_ctrl  = m9206_pid_filter_ctrl,
+		.pid_filter       = m920x_pid_filter,
+		.pid_filter_ctrl  = m920x_pid_filter_ctrl,
 
-		.frontend_attach  = megasky_mt352_frontend_attach,
-		.tuner_attach     = megasky_qt1010_tuner_attach,
+		.frontend_attach  = m920x_mt352_frontend_attach,
+		.tuner_attach     = m920x_qt1010_tuner_attach,
 
 		.stream = {
 			.type = USB_BULK,
@@ -530,7 +678,7 @@ static struct dvb_usb_device_properties megasky_properties = {
 			}
 		},
 	}},
-	.i2c_algo         = &m9206_i2c_algo,
+	.i2c_algo         = &m920x_i2c_algo,
 
 	.num_device_descs = 1,
 	.devices = {
@@ -546,22 +694,22 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = {
 
 	.usb_ctrl = DEVICE_SPECIFIC,
 	.firmware = "dvb-usb-digivox-02.fw",
-	.download_firmware = m9206_firmware_download,
+	.download_firmware = m920x_firmware_download,
 
-	.size_of_priv     = sizeof(struct m9206_state),
+	.size_of_priv     = sizeof(struct m920x_state),
 
 	.identify_state   = m920x_identify_state,
 	.num_adapters = 1,
 	.adapter = {{
 		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
-		DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
 
 		.pid_filter_count = 8,
-		.pid_filter       = m9206_pid_filter,
-		.pid_filter_ctrl  = m9206_pid_filter_ctrl,
+		.pid_filter       = m920x_pid_filter,
+		.pid_filter_ctrl  = m920x_pid_filter_ctrl,
 
-		.frontend_attach  = digivox_tda10046_frontend_attach,
-		.tuner_attach     = digivox_tda8275_tuner_attach,
+		.frontend_attach  = m920x_tda10046_08_frontend_attach,
+		.tuner_attach     = m920x_tda8275_60_tuner_attach,
 
 		.stream = {
 			.type = USB_BULK,
@@ -574,7 +722,7 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = {
 			}
 		},
 	}},
-	.i2c_algo         = &m9206_i2c_algo,
+	.i2c_algo         = &m920x_i2c_algo,
 
 	.num_device_descs = 1,
 	.devices = {
@@ -585,6 +733,122 @@ static struct dvb_usb_device_properties digivox_mini_ii_properties = {
 	}
 };
 
+/* LifeView TV Walker Twin support by Nick Andrew <nick@nick-andrew.net>
+ *
+ * LifeView TV Walker Twin has 1 x M9206, 2 x TDA10046, 2 x TDA8275A
+ * TDA10046 #0 is located at i2c address 0x08
+ * TDA10046 #1 is located at i2c address 0x0b (presently disabled - not yet working)
+ * TDA8275A #0 is located at i2c address 0x60
+ * TDA8275A #1 is located at i2c address 0x61 (presently disabled - not yet working)
+ */
+static struct dvb_usb_device_properties tvwalkertwin_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+	.usb_ctrl = DEVICE_SPECIFIC,
+	.firmware = "dvb-usb-tvwalkert.fw",
+	.download_firmware = m920x_firmware_download,
+
+	.rc_interval      = 100,
+	.rc_key_map       = tvwalkertwin_rc_keys,
+	.rc_key_map_size  = ARRAY_SIZE(tvwalkertwin_rc_keys),
+	.rc_query         = m920x_rc_query,
+
+	.size_of_priv     = sizeof(struct m920x_state),
+
+	.identify_state   = m920x_identify_state,
+	.num_adapters = 1,
+	.adapter = {{
+		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
+			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+		.pid_filter_count = 8,
+		.pid_filter       = m920x_pid_filter,
+		.pid_filter_ctrl  = m920x_pid_filter_ctrl,
+
+		.frontend_attach  = m920x_tda10046_08_frontend_attach,
+		.tuner_attach     = m920x_tda8275_60_tuner_attach,
+
+		.stream = {
+			.type = USB_BULK,
+			.count = 8,
+			.endpoint = 0x81,
+			.u = {
+				 .bulk = {
+					 .buffersize = 512,
+				 }
+			}
+		}},{
+		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
+			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+
+		.pid_filter_count = 8,
+		.pid_filter       = m920x_pid_filter,
+		.pid_filter_ctrl  = m920x_pid_filter_ctrl,
+
+		.frontend_attach  = m920x_tda10046_0b_frontend_attach,
+		.tuner_attach     = m920x_tda8275_61_tuner_attach,
+
+		.stream = {
+			.type = USB_BULK,
+			.count = 8,
+			.endpoint = 0x82,
+			.u = {
+				 .bulk = {
+					 .buffersize = 512,
+				 }
+			}
+		},
+	}},
+	.i2c_algo         = &m920x_i2c_algo,
+
+	.num_device_descs = 1,
+	.devices = {
+		{   .name = "LifeView TV Walker Twin DVB-T USB2.0",
+		    .cold_ids = { &m920x_table[2], NULL },
+		    .warm_ids = { &m920x_table[3], NULL },
+		},
+	}
+};
+
+static struct dvb_usb_device_properties dposh_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+	.usb_ctrl = DEVICE_SPECIFIC,
+	.firmware = "dvb-usb-dposh-01.fw",
+	.download_firmware = m920x_firmware_download,
+
+	.size_of_priv     = sizeof(struct m920x_state),
+
+	.identify_state   = m920x_identify_state,
+	.num_adapters = 1,
+	.adapter = {{
+		/* Hardware pid filters don't work with this device/firmware */
+
+		.frontend_attach  = m920x_mt352_frontend_attach,
+		.tuner_attach     = m920x_qt1010_tuner_attach,
+
+		.stream = {
+			.type = USB_BULK,
+			.count = 8,
+			.endpoint = 0x81,
+			.u = {
+				 .bulk = {
+					 .buffersize = 512,
+				 }
+			}
+		},
+	}},
+	.i2c_algo         = &m920x_i2c_algo,
+
+	.num_device_descs = 1,
+	.devices = {
+		 {   .name = "Dposh DVB-T USB2.0",
+		     .cold_ids = { &m920x_table[4], NULL },
+		     .warm_ids = { &m920x_table[5], NULL },
+		 },
+	 }
+};
+
 static struct usb_driver m920x_driver = {
 	.name		= "dvb_usb_m920x",
 	.probe		= m920x_probe,
@@ -615,6 +879,11 @@ module_init (m920x_module_init);
 module_exit (m920x_module_exit);
 
 MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
-MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / Uli m920x");
+MODULE_DESCRIPTION("DVB Driver for ULI M920x");
 MODULE_VERSION("0.1");
 MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */

+ 11 - 2
drivers/media/dvb/dvb-usb/m920x.h

@@ -4,7 +4,7 @@
 #define DVB_USB_LOG_PREFIX "m920x"
 #include "dvb-usb.h"
 
-#define deb_rc(args...)   dprintk(dvb_usb_m920x_debug,0x01,args)
+#define deb(args...)   dprintk(dvb_usb_m920x_debug,0x01,args)
 
 #define M9206_CORE	0x22
 #define M9206_RC_STATE	0xff51
@@ -59,9 +59,18 @@ What any other bits might mean, or how to get the slave's ACK/NACK
 response to a write, is unknown.
 */
 
-struct m9206_state {
+struct m920x_state {
 	u16 filters[M9206_MAX_FILTERS];
 	int filtering_enabled;
 	int rep_count;
 };
+
+/* Initialisation data for the m920x
+ */
+
+struct m920x_inits {
+	u16 address;
+	u8  data;
+};
+
 #endif

+ 7 - 7
drivers/media/dvb/dvb-usb/vp702x-fe.c

@@ -204,8 +204,8 @@ static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
 static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
 				    struct dvb_diseqc_master_cmd *m)
 {
-	//struct vp702x_fe_state *st = fe->demodulator_priv;
-	u8 cmd[8];//,ibuf[10];
+	struct vp702x_fe_state *st = fe->demodulator_priv;
+	u8 cmd[8],ibuf[10];
 	memset(cmd,0,8);
 
 	deb_fe("%s\n",__FUNCTION__);
@@ -218,12 +218,12 @@ static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
 	memcpy(&cmd[3], m->msg, m->msg_len);
 	cmd[7] = vp702x_chksum(cmd,0,7);
 
-//	vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
+	vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
 
-//	if (ibuf[2] == 0 && ibuf[3] == 0)
-//		deb_fe("diseqc cmd failed.\n");
-//	else
-//		deb_fe("diseqc cmd succeeded.\n");
+	if (ibuf[2] == 0 && ibuf[3] == 0)
+		deb_fe("diseqc cmd failed.\n");
+	else
+		deb_fe("diseqc cmd succeeded.\n");
 
 	return 0;
 }

+ 8 - 0
drivers/media/dvb/pluto2/pluto2.c

@@ -293,12 +293,20 @@ static void pluto_dma_end(struct pluto *pluto, unsigned int nbpackets)
 	 *     but no packets have been transfered.
 	 * [2] Sometimes (actually very often) NBPACKETS stays at zero
 	 *     although one packet has been transfered.
+	 * [3] Sometimes (actually rarely), the card gets into an erroneous
+	 *     mode where it continuously generates interrupts, claiming it
+	 *     has recieved nbpackets>TS_DMA_PACKETS packets, but no packet
+	 *     has been transfered. Only a reset seems to solve this
 	 */
 	if ((nbpackets == 0) || (nbpackets > TS_DMA_PACKETS)) {
 		unsigned int i = 0;
 		while (pluto->dma_buf[i] == 0x47)
 			i += 188;
 		nbpackets = i / 188;
+		if (i == 0) {
+			pluto_reset_ts(pluto, 1);
+			dev_printk(KERN_DEBUG, &pluto->pdev->dev, "resetting TS because of invalid packet counter\n");
+		}
 	}
 
 	dvb_dmx_swfilter_packets(&pluto->demux, pluto->dma_buf, nbpackets);

+ 6 - 3
drivers/media/dvb/ttpci/av7110.c

@@ -1246,6 +1246,9 @@ static void vpeirq(unsigned long data)
 	if (!budget->feeding1 || (newdma == olddma))
 		return;
 
+	/* Ensure streamed PCI data is synced to CPU */
+	pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
+
 #if 0
 	/* track rps1 activity */
 	printk("vpeirq: %02x Event Counter 1 0x%04x\n",
@@ -2679,8 +2682,8 @@ err_iobuf_vfree_6:
 err_pci_free_5:
 	pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
 err_saa71466_vfree_4:
-	if (!av7110->grabbing)
-		saa7146_pgtable_free(pdev, &av7110->pt);
+	if (av7110->grabbing)
+		saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt);
 err_i2c_del_3:
 	i2c_del_adapter(&av7110->i2c_adap);
 err_dvb_unregister_adapter_2:
@@ -2710,7 +2713,7 @@ static int __devexit av7110_detach(struct saa7146_dev* saa)
 		SAA7146_ISR_CLEAR(saa, MASK_10);
 		msleep(50);
 		tasklet_kill(&av7110->vpe_tasklet);
-		saa7146_pgtable_free(saa->pci, &av7110->pt);
+		saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt);
 	}
 	av7110_exit_v4l(av7110);
 

+ 1 - 1
drivers/media/dvb/ttpci/budget-ci.c

@@ -904,7 +904,7 @@ static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struc
 		band = 1;
 	} else if (tuner_frequency < 200000000) {
 		cp = 6;
-		band = 2;
+		band = 1;
 	} else if (tuner_frequency < 290000000) {
 		cp = 3;
 		band = 2;

+ 20 - 17
drivers/media/dvb/ttpci/budget-core.c

@@ -195,6 +195,9 @@ static void vpeirq(unsigned long data)
 	u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
 	u32 count;
 
+	/* Ensure streamed PCI data is synced to CPU */
+	pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
+
 	/* nearest lower position divisible by 188 */
 	newdma -= newdma % 188;
 
@@ -504,16 +507,16 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
 	strcpy(budget->i2c_adap.name, budget->card->name);
 
 	if (i2c_add_adapter(&budget->i2c_adap) < 0) {
-		dvb_unregister_adapter(&budget->dvb_adapter);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err_dvb_unregister;
 	}
 
 	ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac);
 
-	if (NULL ==
-	    (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt))) {
+	budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt);
+	if (NULL == budget->grabbing) {
 		ret = -ENOMEM;
-		goto err;
+		goto err_del_i2c;
 	}
 
 	saa7146_write(dev, PCI_BT_V1, 0x001c0000);
@@ -526,14 +529,16 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
 	if (bi->type != BUDGET_FS_ACTIVY)
 		saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
 
-	if (budget_register(budget) == 0) {
-		return 0;
-	}
-err:
-	i2c_del_adapter(&budget->i2c_adap);
+	if (budget_register(budget) == 0)
+		return 0; /* Everything OK */
+
+	/* An error occurred, cleanup resources */
+	saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
 
-	vfree(budget->grabbing);
+err_del_i2c:
+	i2c_del_adapter(&budget->i2c_adap);
 
+err_dvb_unregister:
 	dvb_unregister_adapter(&budget->dvb_adapter);
 
 	return ret;
@@ -555,15 +560,13 @@ int ttpci_budget_deinit(struct budget *budget)
 
 	budget_unregister(budget);
 
-	i2c_del_adapter(&budget->i2c_adap);
-
-	dvb_unregister_adapter(&budget->dvb_adapter);
-
 	tasklet_kill(&budget->vpe_tasklet);
 
-	saa7146_pgtable_free(dev->pci, &budget->pt);
+	saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
 
-	vfree(budget->grabbing);
+	i2c_del_adapter(&budget->i2c_adap);
+
+	dvb_unregister_adapter(&budget->dvb_adapter);
 
 	return 0;
 }

+ 9 - 2
drivers/media/radio/Kconfig

@@ -2,8 +2,14 @@
 # Multimedia Video device configuration
 #
 
-menu "Radio Adapters"
+menuconfig RADIO_ADAPTERS
+	bool "Radio Adapters"
 	depends on VIDEO_DEV
+	default y
+	---help---
+	  Say Y here to enable selecting AM/FM radio adapters.
+
+if RADIO_ADAPTERS
 
 config RADIO_CADET
 	tristate "ADS Cadet AM/FM Tuner"
@@ -328,4 +334,5 @@ config USB_DSBR
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called dsbr100.
-endmenu
+
+endif # RADIO_ADAPTERS

+ 186 - 159
drivers/media/radio/dsbr100.c

@@ -33,6 +33,10 @@
 
  History:
 
+ Version 0.42:
+	Converted dsbr100 to use video_ioctl2
+	by Douglas Landgraf <dougsland@gmail.com>
+
  Version 0.41-ac1:
 	Alan Cox: Some cleanups and fixes
 
@@ -121,8 +125,6 @@ devices, that would be 76 and 91.  */
 static int usb_dsbr100_probe(struct usb_interface *intf,
 			     const struct usb_device_id *id);
 static void usb_dsbr100_disconnect(struct usb_interface *intf);
-static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
-			     unsigned int cmd, unsigned long arg);
 static int usb_dsbr100_open(struct inode *inode, struct file *file);
 static int usb_dsbr100_close(struct inode *inode, struct file *file);
 
@@ -142,26 +144,6 @@ struct dsbr100_device {
 };
 
 
-/* File system interface */
-static const struct file_operations usb_dsbr100_fops = {
-	.owner =	THIS_MODULE,
-	.open =		usb_dsbr100_open,
-	.release =     	usb_dsbr100_close,
-	.ioctl =        usb_dsbr100_ioctl,
-	.compat_ioctl = v4l_compat_ioctl32,
-	.llseek =       no_llseek,
-};
-
-/* V4L interface */
-static struct video_device dsbr100_videodev_template=
-{
-	.owner =	THIS_MODULE,
-	.name =		"D-Link DSB-R 100",
-	.type =		VID_TYPE_TUNER,
-	.fops =         &usb_dsbr100_fops,
-	.release = video_device_release,
-};
-
 static struct usb_device_id usb_dsbr100_device_table [] = {
 	{ USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
 	{ }						/* Terminating entry */
@@ -252,37 +234,6 @@ static void dsbr100_getstat(struct dsbr100_device *radio)
 
 /* USB subsystem interface begins here */
 
-/* check if the device is present and register with v4l and
-usb if it is */
-static int usb_dsbr100_probe(struct usb_interface *intf,
-			 const struct usb_device_id *id)
-{
-	struct dsbr100_device *radio;
-
-	if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL)))
-		return -ENOMEM;
-	if (!(radio->videodev = video_device_alloc())) {
-		kfree(radio);
-		return -ENOMEM;
-	}
-	memcpy(radio->videodev, &dsbr100_videodev_template,
-		sizeof(dsbr100_videodev_template));
-	radio->removed = 0;
-	radio->users = 0;
-	radio->usbdev = interface_to_usbdev(intf);
-	radio->curfreq = FREQ_MIN*FREQ_MUL;
-	video_set_drvdata(radio->videodev, radio);
-	if (video_register_device(radio->videodev, VFL_TYPE_RADIO,
-		radio_nr)) {
-		warn("Could not register video device");
-		video_device_release(radio->videodev);
-		kfree(radio);
-		return -EIO;
-	}
-	usb_set_intfdata(intf, radio);
-	return 0;
-}
-
 /* handle unplugging of the device, release data structures
 if nothing keeps us from doing it.  If something is still
 keeping us busy, the release callback of v4l will take care
@@ -307,133 +258,147 @@ static void usb_dsbr100_disconnect(struct usb_interface *intf)
 }
 
 
-/* Video for Linux interface */
+static int vidioc_querycap(struct file *file, void *priv,
+					struct v4l2_capability *v)
+{
+	strlcpy(v->driver, "dsbr100", sizeof(v->driver));
+	strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof(v->card));
+	sprintf(v->bus_info, "ISA");
+	v->version = RADIO_VERSION;
+	v->capabilities = V4L2_CAP_TUNER;
+	return 0;
+}
 
-static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file,
-				unsigned int cmd, void *arg)
+static int vidioc_g_tuner(struct file *file, void *priv,
+				struct v4l2_tuner *v)
 {
-	struct dsbr100_device *radio=video_get_drvdata(video_devdata(file));
+	struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
+
+	if (v->index > 0)
+		return -EINVAL;
+
+	dsbr100_getstat(radio);
+	strcpy(v->name, "FM");
+	v->type = V4L2_TUNER_RADIO;
+	v->rangelow = FREQ_MIN*FREQ_MUL;
+	v->rangehigh = FREQ_MAX*FREQ_MUL;
+	v->rxsubchans = V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
+	v->capability = V4L2_TUNER_CAP_LOW;
+	if(radio->stereo)
+		v->audmode = V4L2_TUNER_MODE_STEREO;
+	else
+		v->audmode = V4L2_TUNER_MODE_MONO;
+	v->signal = 0xffff;     /* We can't get the signal strength */
+	return 0;
+}
 
-	if (!radio)
-		return -EIO;
+static int vidioc_s_tuner(struct file *file, void *priv,
+				struct v4l2_tuner *v)
+{
+	if (v->index > 0)
+		return -EINVAL;
 
-	switch(cmd) {
-		case VIDIOC_QUERYCAP:
-		{
-			struct v4l2_capability *v = arg;
-			memset(v,0,sizeof(*v));
-			strlcpy(v->driver, "dsbr100", sizeof (v->driver));
-			strlcpy(v->card, "D-Link R-100 USB FM Radio", sizeof (v->card));
-			sprintf(v->bus_info,"ISA");
-			v->version = RADIO_VERSION;
-			v->capabilities = V4L2_CAP_TUNER;
+	return 0;
+}
 
-			return 0;
-		}
-		case VIDIOC_G_TUNER:
-		{
-			struct v4l2_tuner *v = arg;
+static int vidioc_s_frequency(struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
 
-			if (v->index > 0)
-				return -EINVAL;
+	radio->curfreq = f->frequency;
+	if (dsbr100_setfreq(radio, radio->curfreq)==-1)
+		warn("Set frequency failed");
+	return 0;
+}
 
-			dsbr100_getstat(radio);
+static int vidioc_g_frequency(struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
 
-			memset(v,0,sizeof(*v));
-			strcpy(v->name, "FM");
-			v->type = V4L2_TUNER_RADIO;
+	f->type = V4L2_TUNER_RADIO;
+	f->frequency = radio->curfreq;
+	return 0;
+}
 
-			v->rangelow = FREQ_MIN*FREQ_MUL;
-			v->rangehigh = FREQ_MAX*FREQ_MUL;
-			v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO;
-			v->capability=V4L2_TUNER_CAP_LOW;
-			if(radio->stereo)
-				v->audmode = V4L2_TUNER_MODE_STEREO;
-			else
-				v->audmode = V4L2_TUNER_MODE_MONO;
-			v->signal = 0xFFFF;     /* We can't get the signal strength */
+static int vidioc_queryctrl(struct file *file, void *priv,
+				struct v4l2_queryctrl *qc)
+{
+	int i;
 
+	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+		if (qc->id && qc->id == radio_qctrl[i].id) {
+			memcpy(qc, &(radio_qctrl[i]),
+						sizeof(*qc));
 			return 0;
 		}
-		case VIDIOC_S_TUNER:
-		{
-			struct v4l2_tuner *v = arg;
-
-			if (v->index > 0)
-				return -EINVAL;
+	}
+	return -EINVAL;
+}
 
-			return 0;
-		}
-		case VIDIOC_S_FREQUENCY:
-		{
-			struct v4l2_frequency *f = arg;
+static int vidioc_g_ctrl(struct file *file, void *priv,
+				struct v4l2_control *ctrl)
+{
+	struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
 
-			radio->curfreq = f->frequency;
-			if (dsbr100_setfreq(radio, radio->curfreq)==-1)
-				warn("Set frequency failed");
-			return 0;
-		}
-		case VIDIOC_G_FREQUENCY:
-		{
-			struct v4l2_frequency *f = arg;
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		ctrl->value = radio->muted;
+		return 0;
+	}
+	return -EINVAL;
+}
 
-			f->type = V4L2_TUNER_RADIO;
-			f->frequency = radio->curfreq;
+static int vidioc_s_ctrl(struct file *file, void *priv,
+				struct v4l2_control *ctrl)
+{
+	struct dsbr100_device *radio = video_get_drvdata(video_devdata(file));
 
-			return 0;
-		}
-		case VIDIOC_QUERYCTRL:
-		{
-			struct v4l2_queryctrl *qc = arg;
-			int i;
-
-			for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
-				if (qc->id && qc->id == radio_qctrl[i].id) {
-					memcpy(qc, &(radio_qctrl[i]),
-								sizeof(*qc));
-					return 0;
-				}
-			}
-			return -EINVAL;
-		}
-		case VIDIOC_G_CTRL:
-		{
-			struct v4l2_control *ctrl= arg;
-
-			switch (ctrl->id) {
-			case V4L2_CID_AUDIO_MUTE:
-				ctrl->value=radio->muted;
-				return 0;
-			}
-			return -EINVAL;
-		}
-		case VIDIOC_S_CTRL:
-		{
-			struct v4l2_control *ctrl= arg;
-
-			switch (ctrl->id) {
-			case V4L2_CID_AUDIO_MUTE:
-				if (ctrl->value) {
-					if (dsbr100_stop(radio)==-1)
-						warn("Radio did not respond properly");
-				} else {
-					if (dsbr100_start(radio)==-1)
-						warn("Radio did not respond properly");
-				}
-				return 0;
-			}
-			return -EINVAL;
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		if (ctrl->value) {
+			if (dsbr100_stop(radio)==-1)
+				warn("Radio did not respond properly");
+		} else {
+			if (dsbr100_start(radio)==-1)
+				warn("Radio did not respond properly");
 		}
-		default:
-			return v4l_compat_translate_ioctl(inode,file,cmd,arg,
-							  usb_dsbr100_do_ioctl);
+		return 0;
 	}
+	return -EINVAL;
 }
 
-static int usb_dsbr100_ioctl(struct inode *inode, struct file *file,
-			     unsigned int cmd, unsigned long arg)
+static int vidioc_g_audio(struct file *file, void *priv,
+				struct v4l2_audio *a)
 {
-	return video_usercopy(inode, file, cmd, arg, usb_dsbr100_do_ioctl);
+	if (a->index > 1)
+		return -EINVAL;
+
+	strcpy(a->name, "Radio");
+	a->capability = V4L2_AUDCAP_STEREO;
+	return 0;
+}
+
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+	*i = 0;
+	return 0;
+}
+
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+	if (i != 0)
+		return -EINVAL;
+	return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	if (a->index != 0)
+		return -EINVAL;
+	return 0;
 }
 
 static int usb_dsbr100_open(struct inode *inode, struct file *file)
@@ -465,6 +430,68 @@ static int usb_dsbr100_close(struct inode *inode, struct file *file)
 	return 0;
 }
 
+/* File system interface */
+static const struct file_operations usb_dsbr100_fops = {
+	.owner		= THIS_MODULE,
+	.open		= usb_dsbr100_open,
+	.release	= usb_dsbr100_close,
+	.ioctl		= video_ioctl2,
+	.compat_ioctl	= v4l_compat_ioctl32,
+	.llseek		= no_llseek,
+};
+
+/* V4L2 interface */
+static struct video_device dsbr100_videodev_template =
+{
+	.owner		= THIS_MODULE,
+	.name		= "D-Link DSB-R 100",
+	.type		= VID_TYPE_TUNER,
+	.fops		= &usb_dsbr100_fops,
+	.release	= video_device_release,
+	.vidioc_querycap    = vidioc_querycap,
+	.vidioc_g_tuner     = vidioc_g_tuner,
+	.vidioc_s_tuner     = vidioc_s_tuner,
+	.vidioc_g_frequency = vidioc_g_frequency,
+	.vidioc_s_frequency = vidioc_s_frequency,
+	.vidioc_queryctrl   = vidioc_queryctrl,
+	.vidioc_g_ctrl      = vidioc_g_ctrl,
+	.vidioc_s_ctrl      = vidioc_s_ctrl,
+	.vidioc_g_audio     = vidioc_g_audio,
+	.vidioc_s_audio     = vidioc_s_audio,
+	.vidioc_g_input     = vidioc_g_input,
+	.vidioc_s_input     = vidioc_s_input,
+};
+
+/* check if the device is present and register with v4l and
+usb if it is */
+static int usb_dsbr100_probe(struct usb_interface *intf,
+				const struct usb_device_id *id)
+{
+	struct dsbr100_device *radio;
+
+	if (!(radio = kmalloc(sizeof(struct dsbr100_device), GFP_KERNEL)))
+		return -ENOMEM;
+	if (!(radio->videodev = video_device_alloc())) {
+		kfree(radio);
+		return -ENOMEM;
+	}
+	memcpy(radio->videodev, &dsbr100_videodev_template,
+		sizeof(dsbr100_videodev_template));
+	radio->removed = 0;
+	radio->users = 0;
+	radio->usbdev = interface_to_usbdev(intf);
+	radio->curfreq = FREQ_MIN*FREQ_MUL;
+	video_set_drvdata(radio->videodev, radio);
+	if (video_register_device(radio->videodev, VFL_TYPE_RADIO,radio_nr)) {
+		warn("Could not register video device");
+		video_device_release(radio->videodev);
+		kfree(radio);
+		return -EIO;
+	}
+	usb_set_intfdata(intf, radio);
+	return 0;
+}
+
 static int __init dsbr100_init(void)
 {
 	int retval = usb_register(&usb_dsbr100_driver);

+ 179 - 118
drivers/media/radio/radio-cadet.c

@@ -48,6 +48,25 @@
 
 #define CADET_VERSION KERNEL_VERSION(0,3,3)
 
+static struct v4l2_queryctrl radio_qctrl[] = {
+	{
+		.id            = V4L2_CID_AUDIO_MUTE,
+		.name          = "Mute",
+		.minimum       = 0,
+		.maximum       = 1,
+		.default_value = 1,
+		.type          = V4L2_CTRL_TYPE_BOOLEAN,
+	},{
+		.id            = V4L2_CID_AUDIO_VOLUME,
+		.name          = "Volume",
+		.minimum       = 0,
+		.maximum       = 0xff,
+		.step          = 1,
+		.default_value = 0xff,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	}
+};
+
 static int io=-1;		/* default to isapnp activation */
 static int radio_nr = -1;
 static int users=0;
@@ -347,135 +366,165 @@ cadet_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 }
 
 
+static int vidioc_querycap(struct file *file, void *priv,
+				struct v4l2_capability *v)
+{
+	v->capabilities =
+		V4L2_CAP_TUNER |
+		V4L2_CAP_READWRITE;
+	v->version = CADET_VERSION;
+	strcpy(v->driver, "ADS Cadet");
+	strcpy(v->card, "ADS Cadet");
+	return 0;
+}
 
-static int cadet_do_ioctl(struct inode *inode, struct file *file,
-			  unsigned int cmd, void *arg)
+static int vidioc_g_tuner(struct file *file, void *priv,
+				struct v4l2_tuner *v)
 {
-	switch(cmd)
-	{
-		case VIDIOC_QUERYCAP:
-		{
-			struct v4l2_capability *cap = arg;
-			memset(cap,0,sizeof(*cap));
-			cap->capabilities =
-				V4L2_CAP_TUNER |
-				V4L2_CAP_READWRITE;
-			cap->version = CADET_VERSION;
-			strcpy(cap->driver, "ADS Cadet");
-			strcpy(cap->card, "ADS Cadet");
-			return 0;
+	v->type = V4L2_TUNER_RADIO;
+	switch (v->index) {
+	case 0:
+		strcpy(v->name, "FM");
+		v->capability = V4L2_TUNER_CAP_STEREO;
+		v->rangelow = 1400;     /* 87.5 MHz */
+		v->rangehigh = 1728;    /* 108.0 MHz */
+		v->rxsubchans=cadet_getstereo();
+		switch (v->rxsubchans){
+		case V4L2_TUNER_SUB_MONO:
+			v->audmode = V4L2_TUNER_MODE_MONO;
+			break;
+		case V4L2_TUNER_SUB_STEREO:
+			v->audmode = V4L2_TUNER_MODE_STEREO;
+			break;
+		default: ;
 		}
-		case VIDIOC_G_TUNER:
-		{
-			struct v4l2_tuner *t = arg;
-			memset(t,0,sizeof(*t));
-			t->type = V4L2_TUNER_RADIO;
-			switch (t->index)
-			{
-				case 0: strcpy(t->name, "FM");
-					t->capability = V4L2_TUNER_CAP_STEREO;
-					t->rangelow = 1400;     /* 87.5 MHz */
-					t->rangehigh = 1728;    /* 108.0 MHz */
-					t->rxsubchans=cadet_getstereo();
-					switch (t->rxsubchans){
-						case V4L2_TUNER_SUB_MONO:
-							t->audmode = V4L2_TUNER_MODE_MONO;
-							break;
-						case V4L2_TUNER_SUB_STEREO:
-							t->audmode = V4L2_TUNER_MODE_STEREO;
-							break;
-						default: ;
-					}
-					break;
-				case 1: strcpy(t->name, "AM");
-					t->capability = V4L2_TUNER_CAP_LOW;
-					t->rangelow = 8320;      /* 520 kHz */
-					t->rangehigh = 26400;    /* 1650 kHz */
-					t->rxsubchans = V4L2_TUNER_SUB_MONO;
-					t->audmode = V4L2_TUNER_MODE_MONO;
-					break;
-				default:
-					return -EINVAL;
-			}
+		break;
+	case 1:
+		strcpy(v->name, "AM");
+		v->capability = V4L2_TUNER_CAP_LOW;
+		v->rangelow = 8320;      /* 520 kHz */
+		v->rangehigh = 26400;    /* 1650 kHz */
+		v->rxsubchans = V4L2_TUNER_SUB_MONO;
+		v->audmode = V4L2_TUNER_MODE_MONO;
+		break;
+	default:
+		return -EINVAL;
+	}
+	v->signal = sigstrength; /* We might need to modify scaling of this */
+	return 0;
+}
 
-			t->signal = sigstrength; /* We might need to modify scaling of this */
-			return 0;
-		}
-		case VIDIOC_S_TUNER:
-		{
-			struct v4l2_tuner *t = arg;
-			if((t->index != 0)&&(t->index != 1))
-				return -EINVAL;
+static int vidioc_s_tuner(struct file *file, void *priv,
+				struct v4l2_tuner *v)
+{
+	if((v->index != 0)&&(v->index != 1))
+		return -EINVAL;
+	curtuner = v->index;
+	return 0;
+}
 
-			curtuner = t->index;
-			return 0;
-		}
-		case VIDIOC_G_FREQUENCY:
-		{
-			struct v4l2_frequency *f = arg;
-			memset(f,0,sizeof(*f));
-			f->tuner = curtuner;
-			f->type = V4L2_TUNER_RADIO;
-			f->frequency = cadet_getfreq();
-			return 0;
-		}
-		case VIDIOC_S_FREQUENCY:
-		{
-			struct v4l2_frequency *f = arg;
-			if (f->type != V4L2_TUNER_RADIO){
-				return -EINVAL;
-			}
-			if((curtuner==0)&&((f->frequency<1400)||(f->frequency>1728))) {
-				return -EINVAL;
-			}
-			if((curtuner==1)&&((f->frequency<8320)||(f->frequency>26400))) {
-				return -EINVAL;
-			}
-			cadet_setfreq(f->frequency);
-			return 0;
-		}
-		case VIDIOC_G_CTRL:
-		{
-			struct v4l2_control *c = arg;
-			switch (c->id){
-				case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */
-					c->value = (cadet_getvol() == 0);
-					break;
-				case V4L2_CID_AUDIO_VOLUME:
-					c->value = cadet_getvol();
-					break;
-				default:
-					return -EINVAL;
-			}
-			return 0;
-		}
-		case VIDIOC_S_CTRL:
-		{
-			struct v4l2_control *c = arg;
-			switch (c->id){
-				case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */
-					if (c->value) cadet_setvol(0);
-						else cadet_setvol(0xffff);
-					break;
-				case V4L2_CID_AUDIO_VOLUME:
-					cadet_setvol(c->value);
-					break;
-				default:
-					return -EINVAL;
-			}
+static int vidioc_g_frequency(struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	f->tuner = curtuner;
+	f->type = V4L2_TUNER_RADIO;
+	f->frequency = cadet_getfreq();
+	return 0;
+}
+
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	if (f->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
+	if((curtuner==0)&&((f->frequency<1400)||(f->frequency>1728)))
+		return -EINVAL;
+	if((curtuner==1)&&((f->frequency<8320)||(f->frequency>26400)))
+		return -EINVAL;
+	cadet_setfreq(f->frequency);
+	return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+				struct v4l2_queryctrl *qc)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
+		if (qc->id && qc->id == radio_qctrl[i].id) {
+			memcpy(qc, &(radio_qctrl[i]),
+						sizeof(*qc));
 			return 0;
 		}
+	}
+	return -EINVAL;
+}
 
-		default:
-			return -ENOIOCTLCMD;
+static int vidioc_g_ctrl(struct file *file, void *priv,
+				struct v4l2_control *ctrl)
+{
+	switch (ctrl->id){
+	case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */
+		ctrl->value = (cadet_getvol() == 0);
+		break;
+	case V4L2_CID_AUDIO_VOLUME:
+		ctrl->value = cadet_getvol();
+		break;
+	default:
+		return -EINVAL;
 	}
+	return 0;
 }
 
-static int
-cadet_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, unsigned long arg)
+static int vidioc_s_ctrl(struct file *file, void *priv,
+				struct v4l2_control *ctrl)
 {
-	return video_usercopy(inode, file, cmd, arg, cadet_do_ioctl);
+	switch (ctrl->id){
+	case V4L2_CID_AUDIO_MUTE: /* TODO: Handle this correctly */
+		if (ctrl->value)
+			cadet_setvol(0);
+		else
+			cadet_setvol(0xffff);
+		break;
+	case V4L2_CID_AUDIO_VOLUME:
+		cadet_setvol(ctrl->value);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv,
+				struct v4l2_audio *a)
+{
+	if (a->index > 1)
+		return -EINVAL;
+	strcpy(a->name, "Radio");
+	a->capability = V4L2_AUDCAP_STEREO;
+	return 0;
+}
+
+static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+	*i = 0;
+	return 0;
+}
+
+static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
+{
+	if (i != 0)
+		return -EINVAL;
+	return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *priv,
+				struct v4l2_audio *a)
+{
+	if (a->index != 0)
+		return -EINVAL;
+	return 0;
 }
 
 static int
@@ -512,7 +561,7 @@ static const struct file_operations cadet_fops = {
 	.open		= cadet_open,
 	.release       	= cadet_release,
 	.read		= cadet_read,
-	.ioctl		= cadet_ioctl,
+	.ioctl		= video_ioctl2,
 	.poll		= cadet_poll,
 	.compat_ioctl	= v4l_compat_ioctl32,
 	.llseek         = no_llseek,
@@ -524,6 +573,18 @@ static struct video_device cadet_radio=
 	.name		= "Cadet radio",
 	.type		= VID_TYPE_TUNER,
 	.fops           = &cadet_fops,
+	.vidioc_querycap    = vidioc_querycap,
+	.vidioc_g_tuner     = vidioc_g_tuner,
+	.vidioc_s_tuner     = vidioc_s_tuner,
+	.vidioc_g_frequency = vidioc_g_frequency,
+	.vidioc_s_frequency = vidioc_s_frequency,
+	.vidioc_queryctrl   = vidioc_queryctrl,
+	.vidioc_g_ctrl      = vidioc_g_ctrl,
+	.vidioc_s_ctrl      = vidioc_s_ctrl,
+	.vidioc_g_audio     = vidioc_g_audio,
+	.vidioc_s_audio     = vidioc_s_audio,
+	.vidioc_g_input     = vidioc_g_input,
+	.vidioc_s_input     = vidioc_s_input,
 };
 
 static struct pnp_device_id cadet_pnp_devices[] = {

+ 0 - 3
drivers/media/radio/radio-maestro.c

@@ -24,7 +24,6 @@
 #include <linux/delay.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <linux/mutex.h>
 #include <linux/pci.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
@@ -110,7 +109,6 @@ struct radio_device {
 		muted,	/* VIDEO_AUDIO_MUTE */
 		stereo,	/* VIDEO_TUNER_STEREO_ON */
 		tuned;	/* signal strength (0 or 0xffff) */
-	struct mutex lock;
 };
 
 static u32 radio_bits_get(struct radio_device *dev)
@@ -394,7 +392,6 @@ static int __devinit maestro_probe(struct pci_dev *pdev,
 	}
 
 	radio_unit->io = pci_resource_start(pdev, 0) + GPIO_DATA;
-	mutex_init(&radio_unit->lock);
 
 	maestro_radio_inst = video_device_alloc();
 	if (maestro_radio_inst == NULL) {

+ 0 - 1
drivers/media/radio/radio-zoltrix.c

@@ -410,7 +410,6 @@ static struct video_device zoltrix_radio =
 	.owner		= THIS_MODULE,
 	.name		= "Zoltrix Radio Plus",
 	.type		= VID_TYPE_TUNER,
-	.hardware	= 0,
 	.fops           = &zoltrix_fops,
 	.vidioc_querycap    = vidioc_querycap,
 	.vidioc_g_tuner     = vidioc_g_tuner,

+ 27 - 18
drivers/media/video/Kconfig

@@ -2,14 +2,19 @@
 # Multimedia Video device configuration
 #
 
-menu "Video Capture Adapters"
+menuconfig VIDEO_CAPTURE_DRIVERS
+	bool "Video capture adapters"
 	depends on VIDEO_DEV
+	default y
+	---help---
+	  Say Y here to enable selecting the video adapters for
+	  webcams, analog TV, and hybrid analog/digital TV.
+	  Some of those devices also supports FM radio.
 
-comment "Video Capture Adapters"
+if VIDEO_CAPTURE_DRIVERS
 
 config VIDEO_ADV_DEBUG
 	bool "Enable advanced debug functionality"
-	depends on VIDEO_DEV
 	default n
 	---help---
 	  Say Y here to enable advanced debugging functionality on some
@@ -34,7 +39,7 @@ config VIDEO_HELPER_CHIPS_AUTO
 #
 
 menu "Encoders/decoders and other helper chips"
-	depends on VIDEO_DEV && !VIDEO_HELPER_CHIPS_AUTO
+	depends on !VIDEO_HELPER_CHIPS_AUTO
 
 comment "Audio decoders"
 
@@ -61,7 +66,7 @@ config VIDEO_TDA7432
 
 config VIDEO_TDA9840
 	tristate "Philips TDA9840 audio processor"
-	depends on VIDEO_DEV && I2C
+	depends on I2C
 	---help---
 	  Support for tda9840 audio decoder chip found on some Zoran boards.
 
@@ -79,7 +84,7 @@ config VIDEO_TDA9875
 
 config VIDEO_TEA6415C
 	tristate "Philips TEA6415C audio processor"
-	depends on VIDEO_DEV && I2C
+	depends on I2C
 	---help---
 	  Support for tea6415c audio decoder chip found on some bt8xx boards.
 
@@ -88,7 +93,7 @@ config VIDEO_TEA6415C
 
 config VIDEO_TEA6420
 	tristate "Philips TEA6420 audio processor"
-	depends on VIDEO_DEV && I2C
+	depends on I2C
 	---help---
 	  Support for tea6420 audio decoder chip found on some bt8xx boards.
 
@@ -469,7 +474,7 @@ config VIDEO_SAA5246A
 
 config VIDEO_SAA5249
 	tristate "SAA5249 Teletext processor"
-	depends on VIDEO_DEV && I2C && VIDEO_V4L2
+	depends on I2C && VIDEO_V4L2
 	help
 	  Support for I2C bus based teletext using the SAA5249 chip. At the
 	  moment this is only useful on some European WinTV cards.
@@ -479,7 +484,7 @@ config VIDEO_SAA5249
 
 config TUNER_3036
 	tristate "SAB3036 tuner"
-	depends on VIDEO_DEV && I2C && VIDEO_V4L1
+	depends on I2C && VIDEO_V4L1
 	help
 	  Say Y here to include support for Philips SAB3036 compatible tuners.
 	  If in doubt, say N.
@@ -681,8 +686,12 @@ config VIDEO_CAFE_CCIC
 # USB Multimedia device configuration
 #
 
-menu "V4L USB devices"
-	depends on USB && VIDEO_DEV
+menuconfig V4L_USB_DRIVERS
+	bool "V4L USB devices"
+	depends on USB
+	default y
+
+if V4L_USB_DRIVERS
 
 source "drivers/media/video/pvrusb2/Kconfig"
 
@@ -707,7 +716,7 @@ config VIDEO_OVCAMCHIP
 
 config USB_W9968CF
 	tristate "USB W996[87]CF JPEG Dual Mode Camera support"
-	depends on USB && VIDEO_V4L1 && I2C
+	depends on VIDEO_V4L1 && I2C
 	select VIDEO_OVCAMCHIP
 	---help---
 	  Say Y here if you want support for cameras based on OV681 or
@@ -725,7 +734,7 @@ config USB_W9968CF
 
 config USB_OV511
 	tristate "USB OV511 Camera support"
-	depends on USB && VIDEO_V4L1
+	depends on VIDEO_V4L1
 	---help---
 	  Say Y here if you want to connect this type of camera to your
 	  computer's USB port. See <file:Documentation/video4linux/ov511.txt>
@@ -736,7 +745,7 @@ config USB_OV511
 
 config USB_SE401
 	tristate "USB SE401 Camera support"
-	depends on USB && VIDEO_V4L1
+	depends on VIDEO_V4L1
 	---help---
 	  Say Y here if you want to connect this type of camera to your
 	  computer's USB port. See <file:Documentation/video4linux/se401.txt>
@@ -749,7 +758,7 @@ source "drivers/media/video/sn9c102/Kconfig"
 
 config USB_STV680
 	tristate "USB STV680 (Pencam) Camera support"
-	depends on USB && VIDEO_V4L1
+	depends on VIDEO_V4L1
 	---help---
 	  Say Y here if you want to connect this type of camera to your
 	  computer's USB port. This includes the Pencam line of cameras.
@@ -765,7 +774,7 @@ source "drivers/media/video/pwc/Kconfig"
 
 config USB_ZR364XX
 	tristate "USB ZR364XX Camera support"
-	depends on USB && VIDEO_V4L2
+	depends on VIDEO_V4L2
 	---help---
 	  Say Y here if you want to connect this type of camera to your
 	  computer's USB port.
@@ -775,6 +784,6 @@ config USB_ZR364XX
 	  To compile this driver as a module, choose M here: the
 	  module will be called zr364xx.
 
-endmenu # V4L USB devices
+endif # V4L_USB_DRIVERS
 
-endmenu
+endif # VIDEO_CAPTURE_DRIVERS

+ 2 - 2
drivers/media/video/cx25840/cx25840-core.c

@@ -555,7 +555,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
 {
 	struct v4l2_pix_format *pix;
 	int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
-	int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC);
+	int is_50Hz = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
 
 	switch (fmt->type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -567,7 +567,7 @@ static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
 		Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
 		Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
 
-		Vlines = pix->height + (is_pal ? 4 : 7);
+		Vlines = pix->height + (is_50Hz ? 4 : 7);
 
 		if ((pix->width * 16 < Hsrc) || (Hsrc < pix->width) ||
 		    (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {

+ 3 - 2
drivers/media/video/cx88/cx88-mpeg.c

@@ -28,6 +28,7 @@
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
 #include <asm/delay.h>
 
 #include "cx88.h"
@@ -612,7 +613,7 @@ struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board
 }
 
 /* Driver asked for hardware access. */
-int cx8802_request_acquire(struct cx8802_driver *drv)
+static int cx8802_request_acquire(struct cx8802_driver *drv)
 {
 	struct cx88_core *core = drv->core;
 
@@ -632,7 +633,7 @@ int cx8802_request_acquire(struct cx8802_driver *drv)
 }
 
 /* Driver asked to release hardware. */
-int cx8802_request_release(struct cx8802_driver *drv)
+static int cx8802_request_release(struct cx8802_driver *drv)
 {
 	struct cx88_core *core = drv->core;
 

+ 1 - 0
drivers/media/video/cx88/cx88-video.c

@@ -36,6 +36,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
+#include <linux/dma-mapping.h>
 #include <asm/div64.h>
 
 #include "cx88.h"

+ 0 - 7
drivers/media/video/cx88/cx88-vp3054-i2c.c

@@ -111,10 +111,6 @@ static struct i2c_adapter vp3054_i2c_adap_template = {
 	.id                = I2C_HW_B_CX2388x,
 };
 
-static struct i2c_client vp3054_i2c_client_template = {
-	.name	= "VP-3054",
-};
-
 int vp3054_i2c_probe(struct cx8802_dev *dev)
 {
 	struct cx88_core *core = dev->core;
@@ -133,8 +129,6 @@ int vp3054_i2c_probe(struct cx8802_dev *dev)
 	       sizeof(vp3054_i2c->adap));
 	memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template,
 	       sizeof(vp3054_i2c->algo));
-	memcpy(&vp3054_i2c->client, &vp3054_i2c_client_template,
-	       sizeof(vp3054_i2c->client));
 
 	vp3054_i2c->adap.class |= I2C_CLASS_TV_DIGITAL;
 
@@ -144,7 +138,6 @@ int vp3054_i2c_probe(struct cx8802_dev *dev)
 	vp3054_i2c->algo.data = dev;
 	i2c_set_adapdata(&vp3054_i2c->adap, dev);
 	vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;
-	vp3054_i2c->client.adapter = &vp3054_i2c->adap;
 
 	vp3054_bit_setscl(dev,1);
 	vp3054_bit_setsda(dev,1);

+ 0 - 1
drivers/media/video/cx88/cx88-vp3054-i2c.h

@@ -26,7 +26,6 @@
 struct vp3054_i2c_state {
 	struct i2c_adapter         adap;
 	struct i2c_algo_bit_data   algo;
-	struct i2c_client          client;
 	u32                        state;
 };
 

+ 1 - 1
drivers/media/video/em28xx/Kconfig

@@ -1,6 +1,6 @@
 config VIDEO_EM28XX
 	tristate "Empia EM2800/2820/2840 USB video capture support"
-	depends on VIDEO_V4L1 && USB && I2C
+	depends on VIDEO_V4L1 && I2C
 	select VIDEO_BUF
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM

+ 1 - 1
drivers/media/video/et61x251/Kconfig

@@ -1,6 +1,6 @@
 config USB_ET61X251
 	tristate "USB ET61X[12]51 PC Camera Controller support"
-	depends on USB && VIDEO_V4L1
+	depends on VIDEO_V4L1
 	---help---
 	  Say Y here if you want support for cameras based on Etoms ET61X151
 	  or ET61X251 PC Camera Controllers.

+ 1 - 1
drivers/media/video/ivtv/ivtv-driver.c

@@ -74,7 +74,7 @@ int ivtv_first_minor = 0;
 struct ivtv *ivtv_cards[IVTV_MAX_CARDS];
 
 /* Protects ivtv_cards_active */
-spinlock_t ivtv_cards_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(ivtv_cards_lock);
 
 /* add your revision and whatnot here */
 static struct pci_device_id ivtv_pci_tbl[] __devinitdata = {

+ 1 - 1
drivers/media/video/ivtv/ivtv-fileops.c

@@ -804,7 +804,7 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp)
 	struct ivtv_open_id *item;
 	struct ivtv *itv = NULL;
 	struct ivtv_stream *s = NULL;
-	int minor = MINOR(inode->i_rdev);
+	int minor = iminor(inode);
 
 	/* Find which card this open was on */
 	spin_lock(&ivtv_cards_lock);

+ 1 - 1
drivers/media/video/pvrusb2/Kconfig

@@ -1,6 +1,6 @@
 config VIDEO_PVRUSB2
 	tristate "Hauppauge WinTV-PVR USB2 support"
-	depends on VIDEO_V4L2 && USB && I2C && EXPERIMENTAL
+	depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
 	select FW_LOADER
 	select VIDEO_TUNER
 	select VIDEO_TVEEPROM

+ 10 - 3
drivers/media/video/pvrusb2/pvrusb2-encoder.c

@@ -391,22 +391,29 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw)
 int pvr2_encoder_configure(struct pvr2_hdw *hdw)
 {
 	int ret;
+	int val;
 	pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure"
 		   " (cx2341x module)");
 	hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING;
 	hdw->enc_ctl_state.width = hdw->res_hor_val;
 	hdw->enc_ctl_state.height = hdw->res_ver_val;
-	hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur &
-				       (V4L2_STD_NTSC|V4L2_STD_PAL_M)) ?
+	hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & V4L2_STD_525_60) ?
 				      0 : 1);
 
 	ret = 0;
 
 	ret |= pvr2_encoder_prep_config(hdw);
 
+	/* saa7115: 0xf0 */
+	val = 0xf0;
+	if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
+		/* ivtv cx25840: 0x140 */
+		val = 0x140;
+	}
+
 	if (!ret) ret = pvr2_encoder_vcmd(
 		hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
-		0xf0, 0xf0);
+		val, val);
 
 	/* setup firmware to notify us about some events (don't know why...) */
 	if (!ret) ret = pvr2_encoder_vcmd(

+ 5 - 5
drivers/media/video/pvrusb2/pvrusb2-hdw.c

@@ -83,7 +83,7 @@ static struct pvr2_string_table pvr2_client_lists[] = {
 };
 
 static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
-static DECLARE_MUTEX(pvr2_unit_sem);
+static DEFINE_MUTEX(pvr2_unit_mtx);
 
 static int ctlchg = 0;
 static int initusbreset = 1;
@@ -2076,14 +2076,14 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
 	hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL);
 	if (!hdw->ctl_read_urb) goto fail;
 
-	down(&pvr2_unit_sem); do {
+	mutex_lock(&pvr2_unit_mtx); do {
 		for (idx = 0; idx < PVR_NUM; idx++) {
 			if (unit_pointers[idx]) continue;
 			hdw->unit_number = idx;
 			unit_pointers[idx] = hdw;
 			break;
 		}
-	} while (0); up(&pvr2_unit_sem);
+	} while (0); mutex_unlock(&pvr2_unit_mtx);
 
 	cnt1 = 0;
 	cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2");
@@ -2186,13 +2186,13 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
 	}
 	pvr2_i2c_core_done(hdw);
 	pvr2_hdw_remove_usb_stuff(hdw);
-	down(&pvr2_unit_sem); do {
+	mutex_lock(&pvr2_unit_mtx); do {
 		if ((hdw->unit_number >= 0) &&
 		    (hdw->unit_number < PVR_NUM) &&
 		    (unit_pointers[hdw->unit_number] == hdw)) {
 			unit_pointers[hdw->unit_number] = NULL;
 		}
-	} while (0); up(&pvr2_unit_sem);
+	} while (0); mutex_unlock(&pvr2_unit_mtx);
 	kfree(hdw->controls);
 	kfree(hdw->mpeg_ctrl_info);
 	kfree(hdw->std_defs);

+ 22 - 1
drivers/media/video/pvrusb2/pvrusb2-i2c-core.c

@@ -23,6 +23,7 @@
 #include "pvrusb2-hdw-internal.h"
 #include "pvrusb2-debug.h"
 #include "pvrusb2-fx2-cmd.h"
+#include "pvrusb2.h"
 
 #define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
 
@@ -38,6 +39,10 @@ static unsigned int i2c_scan = 0;
 module_param(i2c_scan, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
 
+static int ir_mode[PVR_NUM] = { [0 ... PVR_NUM-1] = 1 };
+module_param_array(ir_mode, int, NULL, 0444);
+MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR");
+
 static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
 					     unsigned int detail,
 					     char *buf,unsigned int maxlen);
@@ -273,6 +278,15 @@ static int i2c_hack_wm8775(struct pvr2_hdw *hdw,
 	return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen);
 }
 
+/* This is an entry point designed to always fail any attempt to perform a
+   transfer.  We use this to cause certain I2C addresses to not be
+   probed. */
+static int i2c_black_hole(struct pvr2_hdw *hdw,
+			   u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
+{
+	return -EIO;
+}
+
 /* This is a special entry point that is entered if an I2C operation is
    attempted to a cx25840 chip on model 24xxx hardware.  This chip can
    sometimes wedge itself.  Worse still, when this happens msp3400 can
@@ -994,10 +1008,17 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
 	}
 
 	/* However, deal with various special cases for 24xxx hardware. */
+	if (ir_mode[hdw->unit_number] == 0) {
+		printk(KERN_INFO "%s: IR disabled\n",hdw->name);
+		hdw->i2c_func[0x18] = i2c_black_hole;
+	} else if (ir_mode[hdw->unit_number] == 1) {
+		if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
+			hdw->i2c_func[0x18] = i2c_24xxx_ir;
+		}
+	}
 	if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
 		hdw->i2c_func[0x1b] = i2c_hack_wm8775;
 		hdw->i2c_func[0x44] = i2c_hack_cx25840;
-		hdw->i2c_func[0x18] = i2c_24xxx_ir;
 	}
 
 	// Configure the adapter and set up everything else related to it.

+ 0 - 14
drivers/media/video/pvrusb2/pvrusb2-sysfs.c

@@ -518,40 +518,32 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
 	}
 	sfp->item_last = cip;
 
-	cip->attr_name.attr.owner = THIS_MODULE;
 	cip->attr_name.attr.name = "name";
 	cip->attr_name.attr.mode = S_IRUGO;
 	cip->attr_name.show = fp->show_name;
 
-	cip->attr_type.attr.owner = THIS_MODULE;
 	cip->attr_type.attr.name = "type";
 	cip->attr_type.attr.mode = S_IRUGO;
 	cip->attr_type.show = fp->show_type;
 
-	cip->attr_min.attr.owner = THIS_MODULE;
 	cip->attr_min.attr.name = "min_val";
 	cip->attr_min.attr.mode = S_IRUGO;
 	cip->attr_min.show = fp->show_min;
 
-	cip->attr_max.attr.owner = THIS_MODULE;
 	cip->attr_max.attr.name = "max_val";
 	cip->attr_max.attr.mode = S_IRUGO;
 	cip->attr_max.show = fp->show_max;
 
-	cip->attr_val.attr.owner = THIS_MODULE;
 	cip->attr_val.attr.name = "cur_val";
 	cip->attr_val.attr.mode = S_IRUGO;
 
-	cip->attr_custom.attr.owner = THIS_MODULE;
 	cip->attr_custom.attr.name = "custom_val";
 	cip->attr_custom.attr.mode = S_IRUGO;
 
-	cip->attr_enum.attr.owner = THIS_MODULE;
 	cip->attr_enum.attr.name = "enum_val";
 	cip->attr_enum.attr.mode = S_IRUGO;
 	cip->attr_enum.show = fp->show_enum;
 
-	cip->attr_bits.attr.owner = THIS_MODULE;
 	cip->attr_bits.attr.name = "bit_val";
 	cip->attr_bits.attr.mode = S_IRUGO;
 	cip->attr_bits.show = fp->show_bits;
@@ -616,12 +608,10 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
 
 	dip = kzalloc(sizeof(*dip),GFP_KERNEL);
 	if (!dip) return;
-	dip->attr_debugcmd.attr.owner = THIS_MODULE;
 	dip->attr_debugcmd.attr.name = "debugcmd";
 	dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP;
 	dip->attr_debugcmd.show = debugcmd_show;
 	dip->attr_debugcmd.store = debugcmd_store;
-	dip->attr_debuginfo.attr.owner = THIS_MODULE;
 	dip->attr_debuginfo.attr.name = "debuginfo";
 	dip->attr_debuginfo.attr.mode = S_IRUGO;
 	dip->attr_debuginfo.show = debuginfo_show;
@@ -811,7 +801,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
 		return;
 	}
 
-	sfp->attr_v4l_minor_number.attr.owner = THIS_MODULE;
 	sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number";
 	sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
 	sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
@@ -825,7 +814,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
 		sfp->v4l_minor_number_created_ok = !0;
 	}
 
-	sfp->attr_v4l_radio_minor_number.attr.owner = THIS_MODULE;
 	sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number";
 	sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO;
 	sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show;
@@ -839,7 +827,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
 		sfp->v4l_radio_minor_number_created_ok = !0;
 	}
 
-	sfp->attr_unit_number.attr.owner = THIS_MODULE;
 	sfp->attr_unit_number.attr.name = "unit_number";
 	sfp->attr_unit_number.attr.mode = S_IRUGO;
 	sfp->attr_unit_number.show = unit_number_show;
@@ -852,7 +839,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp,
 		sfp->unit_number_created_ok = !0;
 	}
 
-	sfp->attr_bus_info.attr.owner = THIS_MODULE;
 	sfp->attr_bus_info.attr.name = "bus_info_str";
 	sfp->attr_bus_info.attr.mode = S_IRUGO;
 	sfp->attr_bus_info.show = bus_info_show;

+ 1 - 1
drivers/media/video/pwc/Kconfig

@@ -1,6 +1,6 @@
 config USB_PWC
 	tristate "USB Philips Cameras"
-	depends on USB && VIDEO_V4L1
+	depends on VIDEO_V4L1
 	---help---
 	  Say Y or M here if you want to use one of these Philips & OEM
 	  webcams:

+ 122 - 1
drivers/media/video/saa7134/saa7134-cards.c

@@ -1170,6 +1170,42 @@ struct saa7134_board saa7134_boards[] = {
 			.amux   = LINE2,
 		},
 	},
+    [SAA7134_BOARD_ECS_TVP3XP_4CB6] = {
+		/* Barry Scott <barry.scott@onelan.co.uk> */
+		.name		= "Elitegroup ECS TVP3XP FM1246 Tuner Card (PAL,FM)",
+		.audio_clock    = 0x187de7,
+		.tuner_type     = TUNER_PHILIPS_PAL_I,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_tv_mono,
+			.vmux   = 1,
+			.amux   = LINE2,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		},{
+			.name   = "CVid over SVid",
+			.vmux   = 0,
+			.amux   = LINE1,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = LINE2,
+		},
+	},
 	[SAA7134_BOARD_AVACSSMARTTV] = {
 		/* Roman Pszonczenko <romka@kolos.math.uni.lodz.pl> */
 		.name           = "AVACS SmartTV",
@@ -2754,6 +2790,35 @@ struct saa7134_board saa7134_boards[] = {
 			.amux   = LINE1,
 		},
 	},
+	[SAA7134_BOARD_KWORLD_DVBT_210] = {
+		.name           = "KWorld DVB-T 210",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 1 << 21,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = TV,
+			.gpio   = 0x0200000,
+		},
+	},
 	[SAA7134_BOARD_KWORLD_ATSC110] = {
 		.name           = "Kworld ATSC110",
 		.audio_clock    = 0x00187de7,
@@ -3407,6 +3472,36 @@ struct saa7134_board saa7134_boards[] = {
 			.gpio = 0x0200000,
 		},
 	},
+	[SAA7134_BOARD_SABRENT_TV_PCB05] = {
+		.name           = "Sabrent PCMCIA TV-PCB05",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		},{
+			.name = name_comp2,
+			.vmux = 0,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+		},
+	},
 };
 
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -3515,7 +3610,13 @@ struct pci_device_id saa7134_pci_tbl[] = {
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x5168,	/* Animation Technologies (LifeView) */
-		.subdevice    = 0x0214, /* Standard PCI, LR214WF */
+		.subdevice    = 0x0214, /* Standard PCI, LR214 Rev E and earlier (SAA7135) */
+		.driver_data  = SAA7134_BOARD_FLYTVPLATINUM_FM,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5168,	/* Animation Technologies (LifeView) */
+		.subdevice    = 0x5214, /* Standard PCI, LR214 Rev F onwards (SAA7131) */
 		.driver_data  = SAA7134_BOARD_FLYTVPLATINUM_FM,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
@@ -3687,6 +3788,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
 		.subvendor    = 0x1019,
 		.subdevice    = 0x4cb5,
 		.driver_data  = SAA7134_BOARD_ECS_TVP3XP_4CB5,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1019,
+		.subdevice    = 0x4cb6,
+		.driver_data  = SAA7134_BOARD_ECS_TVP3XP_4CB6,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
@@ -3913,6 +4020,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
 		.subvendor    = 0x17de,
 		.subdevice    = 0x7201,
 		.driver_data  = SAA7134_BOARD_TEVION_DVBT_220RF,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x17de,
+		.subdevice    = 0x7250,
+		.driver_data  = SAA7134_BOARD_KWORLD_DVBT_210,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
@@ -4099,6 +4212,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
 		.subvendor    = 0x1043,
 		.subdevice    = 0x4857,
 		.driver_data  = SAA7134_BOARD_ASUSTeK_P7131_DUAL,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x0919, /* SinoVideo PCI 2309 Proteus (7134) */
+		.subdevice    = 0x2003, /* OEM cardbus */
+		.driver_data  = SAA7134_BOARD_SABRENT_TV_PCB05,
 	},{
 		/* --- boards without eeprom + subsystem ID --- */
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
@@ -4178,6 +4297,7 @@ int saa7134_board_init1(struct saa7134_dev *dev)
 	case SAA7134_BOARD_CINERGY600_MK3:
 	case SAA7134_BOARD_ECS_TVP3XP:
 	case SAA7134_BOARD_ECS_TVP3XP_4CB5:
+	case SAA7134_BOARD_ECS_TVP3XP_4CB6:
 	case SAA7134_BOARD_MD2819:
 	case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
 	case SAA7134_BOARD_KWORLD_XPERT:
@@ -4426,6 +4546,7 @@ int saa7134_board_init2(struct saa7134_dev *dev)
 		}
 		break;
 	case SAA7134_BOARD_PINNACLE_PCTV_310i:
+	case SAA7134_BOARD_KWORLD_DVBT_210:
 	case SAA7134_BOARD_TEVION_DVBT_220RF:
 	case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
 	case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:

+ 17 - 0
drivers/media/video/saa7134/saa7134-dvb.c

@@ -887,6 +887,20 @@ static struct tda1004x_config asus_p7131_hybrid_lna_config = {
 	.antenna_switch= 2,
 	.request_firmware = philips_tda1004x_request_firmware
 };
+static struct tda1004x_config kworld_dvb_t_210_config = {
+	.demod_address = 0x08,
+	.invert        = 1,
+	.invert_oclk   = 0,
+	.xtal_freq     = TDA10046_XTAL_16M,
+	.agc_config    = TDA10046_AGC_TDA827X,
+	.gpio_config   = TDA10046_GP11_I,
+	.if_freq       = TDA10046_FREQ_045,
+	.i2c_gate      = 0x4b,
+	.tuner_address = 0x61,
+	.tuner_config  = 2,
+	.antenna_switch= 1,
+	.request_firmware = philips_tda1004x_request_firmware
+};
 /* ------------------------------------------------------------------
  * special case: this card uses saa713x GPIO22 for the mode switch
  */
@@ -1039,6 +1053,9 @@ static int dvb_init(struct saa7134_dev *dev)
 			dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
 		}
 		break;
+	case SAA7134_BOARD_KWORLD_DVBT_210:
+		configure_tda827x_fe(dev, &kworld_dvb_t_210_config);
+		break;
 	case SAA7134_BOARD_PHILIPS_TIGER:
 		configure_tda827x_fe(dev, &philips_tiger_config);
 		break;

+ 3 - 0
drivers/media/video/saa7134/saa7134.h

@@ -235,6 +235,9 @@ struct saa7134_format {
 #define SAA7134_BOARD_AVERMEDIA_M102	   110
 #define SAA7134_BOARD_ASUS_P7131_4871	   111
 #define SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA 112
+#define SAA7134_BOARD_ECS_TVP3XP_4CB6  113
+#define SAA7134_BOARD_KWORLD_DVBT_210 114
+#define SAA7134_BOARD_SABRENT_TV_PCB05     115
 
 #define SAA7134_MAXBOARDS 8
 #define SAA7134_INPUT_MAX 8

+ 1 - 1
drivers/media/video/sn9c102/Kconfig

@@ -1,6 +1,6 @@
 config USB_SN9C102
 	tristate "USB SN9C1xx PC Camera Controller support"
-	depends on USB && VIDEO_V4L2
+	depends on VIDEO_V4L2
 	---help---
 	  Say Y here if you want support for cameras based on SONiX SN9C101,
 	  SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers.

+ 1 - 1
drivers/media/video/sn9c102/sn9c102.h

@@ -141,7 +141,7 @@ sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id)
 
 void
 sn9c102_attach_sensor(struct sn9c102_device* cam,
-		      struct sn9c102_sensor* sensor)
+		      const struct sn9c102_sensor* sensor)
 {
 	memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
 }

+ 43 - 48
drivers/media/video/sn9c102/sn9c102_core.c

@@ -48,8 +48,8 @@
 #define SN9C102_MODULE_AUTHOR   "(C) 2004-2007 Luca Risolia"
 #define SN9C102_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
 #define SN9C102_MODULE_LICENSE  "GPL"
-#define SN9C102_MODULE_VERSION  "1:1.39"
-#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 1, 39)
+#define SN9C102_MODULE_VERSION  "1:1.44"
+#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 1, 44)
 
 /*****************************************************************************/
 
@@ -209,38 +209,41 @@ static void sn9c102_queue_unusedframes(struct sn9c102_device* cam)
 }
 
 /*****************************************************************************/
+
 /*
- * Write a sequence of count value/register pairs.  Returns -1 after the
- * first failed write, or 0 for no errors.
- */
+   Write a sequence of count value/register pairs. Returns -1 after the first
+   failed write, or 0 for no errors.
+*/
 int sn9c102_write_regs(struct sn9c102_device* cam, const u8 valreg[][2],
 		       int count)
 {
 	struct usb_device* udev = cam->usbdev;
-	u8* value = cam->control_buffer;  /* Needed for DMA'able memory */
+	u8* buff = cam->control_buffer;
 	int i, res;
 
 	for (i = 0; i < count; i++) {
 		u8 index = valreg[i][1];
 
 		/*
-		 * index is a u8, so it must be <256 and can't be out of range.
-		 * If we put in a check anyway, gcc annoys us with a warning
-		 * that our check is useless.  People get all uppity when they
-		 * see warnings in the kernel compile.
-		 */
-
-		*value = valreg[i][0];
-		res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-				      0x08, 0x41, index, 0,
-				      value, 1, SN9C102_CTRL_TIMEOUT);
+		   index is a u8, so it must be <256 and can't be out of range.
+		   If we put in a check anyway, gcc annoys us with a warning
+		   hat our check is useless. People get all uppity when they
+		   see warnings in the kernel compile.
+		*/
+
+		*buff = valreg[i][0];
+
+		res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08,
+				      0x41, index, 0, buff, 1,
+				      SN9C102_CTRL_TIMEOUT);
+
 		if (res < 0) {
 			DBG(3, "Failed to write a register (value 0x%02X, "
-			       "index 0x%02X, error %d)", *value, index, res);
+			       "index 0x%02X, error %d)", *buff, index, res);
 			return -1;
 		}
 
-		cam->reg[index] = *value;
+		cam->reg[index] = *buff;
 	}
 
 	return 0;
@@ -272,8 +275,8 @@ int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index)
 }
 
 
-/* NOTE: reading some registers always returns 0 */
-static int sn9c102_read_reg(struct sn9c102_device* cam, u16 index)
+/* NOTE: with the SN9C10[123] reading some registers always returns 0 */
+int sn9c102_read_reg(struct sn9c102_device* cam, u16 index)
 {
 	struct usb_device* udev = cam->usbdev;
 	u8* buff = cam->control_buffer;
@@ -299,7 +302,8 @@ int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index)
 
 
 static int
-sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor)
+sn9c102_i2c_wait(struct sn9c102_device* cam,
+		 const struct sn9c102_sensor* sensor)
 {
 	int i, r;
 
@@ -320,7 +324,7 @@ sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor)
 
 static int
 sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
-			      struct sn9c102_sensor* sensor)
+			      const struct sn9c102_sensor* sensor)
 {
 	int r , err = 0;
 
@@ -342,7 +346,7 @@ sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
 
 static int
 sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
-			       struct sn9c102_sensor* sensor)
+			       const struct sn9c102_sensor* sensor)
 {
 	int r;
 	r = sn9c102_read_reg(cam, 0x08);
@@ -352,12 +356,12 @@ sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
 
 int
 sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
-			 struct sn9c102_sensor* sensor, u8 data0, u8 data1,
-			 u8 n, u8 buffer[])
+			 const struct sn9c102_sensor* sensor, u8 data0,
+			 u8 data1, u8 n, u8 buffer[])
 {
 	struct usb_device* udev = cam->usbdev;
 	u8* data = cam->control_buffer;
-	int err = 0, res;
+	int i = 0, err = 0, res;
 
 	/* Write cycle */
 	data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
@@ -402,7 +406,8 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
 	}
 
 	if (buffer)
-		memcpy(buffer, data, sizeof(buffer));
+		for (i = 0; i < n && i < 5; i++)
+			buffer[n-i-1] = data[4-i];
 
 	return (int)data[4];
 }
@@ -410,7 +415,7 @@ sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
 
 int
 sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
-			  struct sn9c102_sensor* sensor, u8 n, u8 data0,
+			  const struct sn9c102_sensor* sensor, u8 n, u8 data0,
 			  u8 data1, u8 data2, u8 data3, u8 data4, u8 data5)
 {
 	struct usb_device* udev = cam->usbdev;
@@ -449,7 +454,7 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
 
 int
 sn9c102_i2c_try_read(struct sn9c102_device* cam,
-		     struct sn9c102_sensor* sensor, u8 address)
+		     const struct sn9c102_sensor* sensor, u8 address)
 {
 	return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id,
 					address, 1, NULL);
@@ -458,7 +463,7 @@ sn9c102_i2c_try_read(struct sn9c102_device* cam,
 
 int
 sn9c102_i2c_try_write(struct sn9c102_device* cam,
-		      struct sn9c102_sensor* sensor, u8 address, u8 value)
+		      const struct sn9c102_sensor* sensor, u8 address, u8 value)
 {
 	return sn9c102_i2c_try_raw_write(cam, sensor, 3,
 					 sensor->i2c_slave_id, address,
@@ -657,16 +662,6 @@ sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
 }
 
 
-static void
-sn9c102_write_eoimarker(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
-{
-	static const u8 eoi_marker[2] = {0xff, 0xd9};
-
-	memcpy(f->bufmem + f->buf.bytesused, eoi_marker, sizeof(eoi_marker));
-	f->buf.bytesused += sizeof(eoi_marker);
-}
-
-
 static void sn9c102_urb_complete(struct urb *urb)
 {
 	struct sn9c102_device* cam = urb->context;
@@ -3181,14 +3176,14 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp,
 
 static const struct file_operations sn9c102_fops = {
 	.owner = THIS_MODULE,
-	.open =    sn9c102_open,
+	.open = sn9c102_open,
 	.release = sn9c102_release,
-	.ioctl =   sn9c102_ioctl,
+	.ioctl = sn9c102_ioctl,
 	.compat_ioctl = v4l_compat_ioctl32,
-	.read =    sn9c102_read,
-	.poll =    sn9c102_poll,
-	.mmap =    sn9c102_mmap,
-	.llseek =  no_llseek,
+	.read = sn9c102_read,
+	.poll = sn9c102_poll,
+	.mmap = sn9c102_mmap,
+	.llseek = no_llseek,
 };
 
 /*****************************************************************************/
@@ -3251,7 +3246,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 		break;
 	}
 
-	for  (i = 0; sn9c102_sensor_table[i]; i++) {
+	for  (i = 0; i < ARRAY_SIZE(sn9c102_sensor_table); i++) {
 		err = sn9c102_sensor_table[i](cam);
 		if (!err)
 			break;
@@ -3262,7 +3257,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 		DBG(3, "Support for %s maintained by %s",
 		    cam->sensor.name, cam->sensor.maintainer);
 	} else {
-		DBG(1, "No supported image sensor detected");
+		DBG(1, "No supported image sensor detected for this bridge");
 		err = -ENODEV;
 		goto fail;
 	}

+ 3 - 1
drivers/media/video/sn9c102/sn9c102_devtable.h

@@ -86,6 +86,8 @@ static const struct usb_device_id sn9c102_id_table[] = {
 	{ SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), },
 	/* SN9C105 */
+	{ SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), },
+	{ SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), },
 	{ SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
 	{ SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
@@ -100,6 +102,7 @@ static const struct usb_device_id sn9c102_id_table[] = {
 	{ SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
 	/* SN9C120 */
+	{ SN9C102_USB_DEVICE(0x0458, 0x7025, BRIDGE_SN9C120), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), },
 	{ SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), },
@@ -148,7 +151,6 @@ static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {
 	&sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
 	&sn9c102_probe_tas5110d, /* detection based on USB pid/vid */
 	&sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
-	NULL,
 };
 
 #endif /* _SN9C102_DEVTABLE_H_ */

+ 2 - 4
drivers/media/video/sn9c102/sn9c102_hv7131d.c

@@ -144,7 +144,7 @@ static int hv7131d_set_pix_format(struct sn9c102_device* cam,
 }
 
 
-static struct sn9c102_sensor hv7131d = {
+static const struct sn9c102_sensor hv7131d = {
 	.name = "HV7131D",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
 	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
@@ -248,12 +248,10 @@ int sn9c102_probe_hv7131d(struct sn9c102_device* cam)
 
 	err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
 				       {0x28, 0x17});
-	if (err)
-		return -EIO;
 
 	r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00);
 	r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01);
-	if (r0 < 0 || r1 < 0)
+	if (err || r0 < 0 || r1 < 0)
 		return -EIO;
 
 	if (r0 != 0x00 || r1 != 0x04)

+ 2 - 6
drivers/media/video/sn9c102/sn9c102_hv7131r.c

@@ -44,7 +44,6 @@ static int hv7131r_init(struct sn9c102_device* cam)
 					       {0xb0, 0x2b}, {0xc0, 0x2c},
 					       {0xd0, 0x2d}, {0xe0, 0x2e},
 					       {0xf0, 0x2f}, {0xff, 0x30});
-
 		break;
 	case BRIDGE_SN9C105:
 	case BRIDGE_SN9C120:
@@ -254,7 +253,7 @@ static int hv7131r_set_pix_format(struct sn9c102_device* cam,
 }
 
 
-static struct sn9c102_sensor hv7131r = {
+static const struct sn9c102_sensor hv7131r = {
 	.name = "HV7131R",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
 	.supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
@@ -350,11 +349,8 @@ int sn9c102_probe_hv7131r(struct sn9c102_device* cam)
 				       {0x34, 0x01}, {0x20, 0x17},
 				       {0x34, 0x01}, {0x46, 0x01});
 
-	if (err)
-		return -EIO;
-
 	devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00);
-	if (devid < 0)
+	if (err || devid < 0)
 		return -EIO;
 
 	if (devid != 0x02)

+ 24 - 27
drivers/media/video/sn9c102/sn9c102_mi0343.c

@@ -55,45 +55,45 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
 			   struct v4l2_control* ctrl)
 {
 	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-	u8 data[5+1];
+	u8 data[2];
 
 	switch (ctrl->id) {
 	case V4L2_CID_EXPOSURE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09,
-					     2+1, data) < 0)
+		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
+					     data) < 0)
 			return -EIO;
-		ctrl->value = data[2];
+		ctrl->value = data[0];
 		return 0;
 	case V4L2_CID_GAIN:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35,
-					     2+1, data) < 0)
+		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
+					     data) < 0)
 			return -EIO;
 		break;
 	case V4L2_CID_HFLIP:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
-					     2+1, data) < 0)
+		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
+					     data) < 0)
 			return -EIO;
-		ctrl->value = data[3] & 0x20 ? 1 : 0;
+		ctrl->value = data[1] & 0x20 ? 1 : 0;
 		return 0;
 	case V4L2_CID_VFLIP:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
-					     2+1, data) < 0)
+		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
+					     data) < 0)
 			return -EIO;
-		ctrl->value = data[3] & 0x80 ? 1 : 0;
+		ctrl->value = data[1] & 0x80 ? 1 : 0;
 		return 0;
 	case V4L2_CID_RED_BALANCE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d,
-					     2+1, data) < 0)
+		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
+					     data) < 0)
 			return -EIO;
 		break;
 	case V4L2_CID_BLUE_BALANCE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c,
-					     2+1, data) < 0)
+		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
+					     data) < 0)
 			return -EIO;
 		break;
 	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e,
-					     2+1, data) < 0)
+		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
+					     data) < 0)
 			return -EIO;
 		break;
 	default:
@@ -105,7 +105,7 @@ static int mi0343_get_ctrl(struct sn9c102_device* cam,
 	case V4L2_CID_RED_BALANCE:
 	case V4L2_CID_BLUE_BALANCE:
 	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		ctrl->value = data[3] | (data[2] << 8);
+		ctrl->value = data[1] | (data[0] << 8);
 		if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
 			ctrl->value -= 0x10;
 		else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
@@ -223,7 +223,7 @@ static int mi0343_set_pix_format(struct sn9c102_device* cam,
 }
 
 
-static struct sn9c102_sensor mi0343 = {
+static const struct sn9c102_sensor mi0343 = {
 	.name = "MI-0343",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
 	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
@@ -332,20 +332,17 @@ static struct sn9c102_sensor mi0343 = {
 
 int sn9c102_probe_mi0343(struct sn9c102_device* cam)
 {
-	u8 data[5+1];
-	int err = 0;
-
-	err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
-				       {0x28, 0x17});
+	u8 data[2];
 
-	if (err)
+	if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
+				     {0x28, 0x17}))
 		return -EIO;
 
 	if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
 				     2, data) < 0)
 		return -EIO;
 
-	if (data[4] != 0x32 || data[3] != 0xe3)
+	if (data[1] != 0x42 || data[0] != 0xe3)
 		return -ENODEV;
 
 	sn9c102_attach_sensor(cam, &mi0343);

+ 167 - 53
drivers/media/video/sn9c102/sn9c102_mi0360.c

@@ -27,20 +27,105 @@ static int mi0360_init(struct sn9c102_device* cam)
 	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
 	int err = 0;
 
-	err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
-				       {0x0a, 0x14}, {0x40, 0x01},
-				       {0x20, 0x17}, {0x07, 0x18},
-				       {0xa0, 0x19}, {0x02, 0x1c},
-				       {0x03, 0x1d}, {0x0f, 0x1e},
-				       {0x0c, 0x1f}, {0x00, 0x20},
-				       {0x10, 0x21}, {0x20, 0x22},
-				       {0x30, 0x23}, {0x40, 0x24},
-				       {0x50, 0x25}, {0x60, 0x26},
-				       {0x70, 0x27}, {0x80, 0x28},
-				       {0x90, 0x29}, {0xa0, 0x2a},
-				       {0xb0, 0x2b}, {0xc0, 0x2c},
-				       {0xd0, 0x2d}, {0xe0, 0x2e},
-				       {0xf0, 0x2f}, {0xff, 0x30});
+	switch (sn9c102_get_bridge(cam)) {
+	case BRIDGE_SN9C103:
+		err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
+					       {0x0a, 0x14}, {0x40, 0x01},
+					       {0x20, 0x17}, {0x07, 0x18},
+					       {0xa0, 0x19}, {0x02, 0x1c},
+					       {0x03, 0x1d}, {0x0f, 0x1e},
+					       {0x0c, 0x1f}, {0x00, 0x20},
+					       {0x10, 0x21}, {0x20, 0x22},
+					       {0x30, 0x23}, {0x40, 0x24},
+					       {0x50, 0x25}, {0x60, 0x26},
+					       {0x70, 0x27}, {0x80, 0x28},
+					       {0x90, 0x29}, {0xa0, 0x2a},
+					       {0xb0, 0x2b}, {0xc0, 0x2c},
+					       {0xd0, 0x2d}, {0xe0, 0x2e},
+					       {0xf0, 0x2f}, {0xff, 0x30});
+		break;
+	case BRIDGE_SN9C105:
+	case BRIDGE_SN9C120:
+		err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
+					       {0x00, 0x03}, {0x1a, 0x04},
+					       {0x50, 0x05}, {0x20, 0x06},
+					       {0x10, 0x07}, {0x03, 0x10},
+					       {0x08, 0x14}, {0xa2, 0x17},
+					       {0x47, 0x18}, {0x00, 0x19},
+					       {0x1d, 0x1a}, {0x10, 0x1b},
+					       {0x02, 0x1c}, {0x03, 0x1d},
+					       {0x0f, 0x1e}, {0x0c, 0x1f},
+					       {0x00, 0x20}, {0x29, 0x21},
+					       {0x40, 0x22}, {0x54, 0x23},
+					       {0x66, 0x24}, {0x76, 0x25},
+					       {0x85, 0x26}, {0x94, 0x27},
+					       {0xa1, 0x28}, {0xae, 0x29},
+					       {0xbb, 0x2a}, {0xc7, 0x2b},
+					       {0xd3, 0x2c}, {0xde, 0x2d},
+					       {0xea, 0x2e}, {0xf4, 0x2f},
+					       {0xff, 0x30}, {0x00, 0x3F},
+					       {0xC7, 0x40}, {0x01, 0x41},
+					       {0x44, 0x42}, {0x00, 0x43},
+					       {0x44, 0x44}, {0x00, 0x45},
+					       {0x44, 0x46}, {0x00, 0x47},
+					       {0xC7, 0x48}, {0x01, 0x49},
+					       {0xC7, 0x4A}, {0x01, 0x4B},
+					       {0xC7, 0x4C}, {0x01, 0x4D},
+					       {0x44, 0x4E}, {0x00, 0x4F},
+					       {0x44, 0x50}, {0x00, 0x51},
+					       {0x44, 0x52}, {0x00, 0x53},
+					       {0xC7, 0x54}, {0x01, 0x55},
+					       {0xC7, 0x56}, {0x01, 0x57},
+					       {0xC7, 0x58}, {0x01, 0x59},
+					       {0x44, 0x5A}, {0x00, 0x5B},
+					       {0x44, 0x5C}, {0x00, 0x5D},
+					       {0x44, 0x5E}, {0x00, 0x5F},
+					       {0xC7, 0x60}, {0x01, 0x61},
+					       {0xC7, 0x62}, {0x01, 0x63},
+					       {0xC7, 0x64}, {0x01, 0x65},
+					       {0x44, 0x66}, {0x00, 0x67},
+					       {0x44, 0x68}, {0x00, 0x69},
+					       {0x44, 0x6A}, {0x00, 0x6B},
+					       {0xC7, 0x6C}, {0x01, 0x6D},
+					       {0xC7, 0x6E}, {0x01, 0x6F},
+					       {0xC7, 0x70}, {0x01, 0x71},
+					       {0x44, 0x72}, {0x00, 0x73},
+					       {0x44, 0x74}, {0x00, 0x75},
+					       {0x44, 0x76}, {0x00, 0x77},
+					       {0xC7, 0x78}, {0x01, 0x79},
+					       {0xC7, 0x7A}, {0x01, 0x7B},
+					       {0xC7, 0x7C}, {0x01, 0x7D},
+					       {0x44, 0x7E}, {0x00, 0x7F},
+					       {0x14, 0x84}, {0x00, 0x85},
+					       {0x27, 0x86}, {0x00, 0x87},
+					       {0x07, 0x88}, {0x00, 0x89},
+					       {0xEC, 0x8A}, {0x0f, 0x8B},
+					       {0xD8, 0x8C}, {0x0f, 0x8D},
+					       {0x3D, 0x8E}, {0x00, 0x8F},
+					       {0x3D, 0x90}, {0x00, 0x91},
+					       {0xCD, 0x92}, {0x0f, 0x93},
+					       {0xf7, 0x94}, {0x0f, 0x95},
+					       {0x0C, 0x96}, {0x00, 0x97},
+					       {0x00, 0x98}, {0x66, 0x99},
+					       {0x05, 0x9A}, {0x00, 0x9B},
+					       {0x04, 0x9C}, {0x00, 0x9D},
+					       {0x08, 0x9E}, {0x00, 0x9F},
+					       {0x2D, 0xC0}, {0x2D, 0xC1},
+					       {0x3A, 0xC2}, {0x05, 0xC3},
+					       {0x04, 0xC4}, {0x3F, 0xC5},
+					       {0x00, 0xC6}, {0x00, 0xC7},
+					       {0x50, 0xC8}, {0x3C, 0xC9},
+					       {0x28, 0xCA}, {0xD8, 0xCB},
+					       {0x14, 0xCC}, {0xEC, 0xCD},
+					       {0x32, 0xCE}, {0xDD, 0xCF},
+					       {0x32, 0xD0}, {0xDD, 0xD1},
+					       {0x6A, 0xD2}, {0x50, 0xD3},
+					       {0x00, 0xD4}, {0x00, 0xD5},
+					       {0x00, 0xD6});
+		break;
+	default:
+		break;
+	}
 
 	err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
 					 0x00, 0x01, 0, 0);
@@ -65,50 +150,50 @@ static int mi0360_get_ctrl(struct sn9c102_device* cam,
 			   struct v4l2_control* ctrl)
 {
 	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-	u8 data[5+1];
+	u8 data[2];
 
 	switch (ctrl->id) {
 	case V4L2_CID_EXPOSURE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09,
-					     2+1, data) < 0)
+		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
+					     data) < 0)
 			return -EIO;
-		ctrl->value = data[2];
+		ctrl->value = data[0];
 		return 0;
 	case V4L2_CID_GAIN:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35,
-					     2+1, data) < 0)
+		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
+					     data) < 0)
 			return -EIO;
-		ctrl->value = data[3];
+		ctrl->value = data[1];
 		return 0;
 	case V4L2_CID_RED_BALANCE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c,
-					     2+1, data) < 0)
+		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
+					     data) < 0)
 			return -EIO;
-		ctrl->value = data[3];
+		ctrl->value = data[1];
 		return 0;
 	case V4L2_CID_BLUE_BALANCE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d,
-					     2+1, data) < 0)
+		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
+					     data) < 0)
 			return -EIO;
-		ctrl->value = data[3];
+		ctrl->value = data[1];
 		return 0;
 	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e,
-					     2+1, data) < 0)
+		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
+					     data) < 0)
 			return -EIO;
-		ctrl->value = data[3];
+		ctrl->value = data[1];
 		return 0;
 	case V4L2_CID_HFLIP:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
-					     2+1, data) < 0)
+		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
+					     data) < 0)
 			return -EIO;
-		ctrl->value = data[3] & 0x20 ? 1 : 0;
+		ctrl->value = data[1] & 0x20 ? 1 : 0;
 		return 0;
 	case V4L2_CID_VFLIP:
-		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20,
-					     2+1, data) < 0)
+		if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
+					     data) < 0)
 			return -EIO;
-		ctrl->value = data[3] & 0x80 ? 1 : 0;
+		ctrl->value = data[1] & 0x80 ? 1 : 0;
 		return 0;
 	default:
 		return -EINVAL;
@@ -178,8 +263,19 @@ static int mi0360_set_crop(struct sn9c102_device* cam,
 {
 	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
 	int err = 0;
-	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
-	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+	u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+
+	switch (sn9c102_get_bridge(cam)) {
+	case BRIDGE_SN9C103:
+		h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0;
+		break;
+	case BRIDGE_SN9C105:
+	case BRIDGE_SN9C120:
+		h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
+		break;
+	default:
+		break;
+	}
 
 	err += sn9c102_write_reg(cam, h_start, 0x12);
 	err += sn9c102_write_reg(cam, v_start, 0x13);
@@ -194,24 +290,30 @@ static int mi0360_set_pix_format(struct sn9c102_device* cam,
 	struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
 	int err = 0;
 
-	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
-		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-						 0x0a, 0x00, 0x02, 0, 0);
-		err += sn9c102_write_reg(cam, 0x20, 0x19);
-	} else {
+	if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
 		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
 						 0x0a, 0x00, 0x05, 0, 0);
 		err += sn9c102_write_reg(cam, 0x60, 0x19);
+		if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
+		    sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
+			err += sn9c102_write_reg(cam, 0xa6, 0x17);
+	} else {
+		err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+						 0x0a, 0x00, 0x02, 0, 0);
+		err += sn9c102_write_reg(cam, 0x20, 0x19);
+		if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
+		    sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
+			err += sn9c102_write_reg(cam, 0xa2, 0x17);
 	}
 
 	return err;
 }
 
 
-static struct sn9c102_sensor mi0360 = {
+static const struct sn9c102_sensor mi0360 = {
 	.name = "MI-0360",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-	.supported_bridge = BRIDGE_SN9C103,
+	.supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
 	.frequency = SN9C102_I2C_100KHZ,
 	.interface = SN9C102_I2C_2WIRES,
 	.i2c_slave_id = 0x5d,
@@ -317,19 +419,31 @@ static struct sn9c102_sensor mi0360 = {
 
 int sn9c102_probe_mi0360(struct sn9c102_device* cam)
 {
-	u8 data[5+1];
-	int err;
 
-	err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
-				       {0x28, 0x17});
-	if (err)
-		return -EIO;
+	u8 data[2];
+
+	switch (sn9c102_get_bridge(cam)) {
+	case BRIDGE_SN9C103:
+		if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
+					     {0x28, 0x17}))
+			return -EIO;
+		break;
+	case BRIDGE_SN9C105:
+	case BRIDGE_SN9C120:
+		if (sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
+					     {0x01, 0x01}, {0x00, 0x01},
+					     {0x28, 0x17}))
+			return -EIO;
+		break;
+	default:
+		break;
+	}
 
 	if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00,
-				     2+1, data) < 0)
+				     2, data) < 0)
 		return -EIO;
 
-	if (data[2] != 0x82 || data[3] != 0x43)
+	if (data[0] != 0x82 || data[1] != 0x43)
 		return -ENODEV;
 
 	sn9c102_attach_sensor(cam, &mi0360);

+ 10 - 15
drivers/media/video/sn9c102/sn9c102_ov7630.c

@@ -29,9 +29,8 @@ static int ov7630_init(struct sn9c102_device* cam)
 	switch (sn9c102_get_bridge(cam)) {
 	case BRIDGE_SN9C101:
 	case BRIDGE_SN9C102:
-		err = sn9c102_write_const_regs(cam, {0x00, 0x14},
-					       {0x60, 0x17}, {0x0f, 0x18},
-					       {0x50, 0x19});
+		err = sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17},
+					       {0x0f, 0x18}, {0x50, 0x19});
 
 		err += sn9c102_i2c_write(cam, 0x12, 0x8d);
 		err += sn9c102_i2c_write(cam, 0x12, 0x0d);
@@ -61,7 +60,6 @@ static int ov7630_init(struct sn9c102_device* cam)
 		err += sn9c102_i2c_write(cam, 0x71, 0x00);
 		err += sn9c102_i2c_write(cam, 0x74, 0x21);
 		err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
-
 		break;
 	case BRIDGE_SN9C103:
 		err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
@@ -253,7 +251,7 @@ static int ov7630_set_pix_format(struct sn9c102_device* cam,
 }
 
 
-static struct sn9c102_sensor ov7630 = {
+static const struct sn9c102_sensor ov7630 = {
 	.name = "OV7630",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
 	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
@@ -408,19 +406,16 @@ int sn9c102_probe_ov7630(struct sn9c102_device* cam)
 	switch (sn9c102_get_bridge(cam)) {
 	case BRIDGE_SN9C101:
 	case BRIDGE_SN9C102:
-		err = sn9c102_write_const_regs(cam, {0x01, 0x01},
-					       {0x00, 0x01}, {0x28, 0x17});
-
+		err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
+					       {0x28, 0x17});
 		break;
 	case BRIDGE_SN9C103: /* do _not_ change anything! */
-		err = sn9c102_write_const_regs(cam, {0x09, 0x01},
-					       {0x42, 0x01}, {0x28, 0x17},
-					       {0x44, 0x02});
+		err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x42, 0x01},
+					       {0x28, 0x17}, {0x44, 0x02});
 		pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
-		if (err || pid < 0) { /* try a different initialization */
-			err = sn9c102_write_reg(cam, 0x01, 0x01);
-			err += sn9c102_write_reg(cam, 0x00, 0x01);
-		}
+		if (err || pid < 0) /* try a different initialization */
+			err += sn9c102_write_const_regs(cam, {0x01, 0x01},
+							{0x00, 0x01});
 		break;
 	default:
 		break;

+ 43 - 20
drivers/media/video/sn9c102/sn9c102_ov7660.c

@@ -104,8 +104,8 @@ static int ov7660_init(struct sn9c102_device* cam)
 	err += sn9c102_i2c_write(cam, 0x12, 0x80);
 	err += sn9c102_i2c_write(cam, 0x11, 0x09);
 	err += sn9c102_i2c_write(cam, 0x00, 0x0A);
-	err += sn9c102_i2c_write(cam, 0x01, 0x78);
-	err += sn9c102_i2c_write(cam, 0x02, 0x90);
+	err += sn9c102_i2c_write(cam, 0x01, 0x80);
+	err += sn9c102_i2c_write(cam, 0x02, 0x80);
 	err += sn9c102_i2c_write(cam, 0x03, 0x00);
 	err += sn9c102_i2c_write(cam, 0x04, 0x00);
 	err += sn9c102_i2c_write(cam, 0x05, 0x08);
@@ -122,7 +122,7 @@ static int ov7660_init(struct sn9c102_device* cam)
 	err += sn9c102_i2c_write(cam, 0x10, 0x20);
 	err += sn9c102_i2c_write(cam, 0x11, 0x03);
 	err += sn9c102_i2c_write(cam, 0x12, 0x05);
-	err += sn9c102_i2c_write(cam, 0x13, 0xF8);
+	err += sn9c102_i2c_write(cam, 0x13, 0xC7);
 	err += sn9c102_i2c_write(cam, 0x14, 0x2C);
 	err += sn9c102_i2c_write(cam, 0x15, 0x00);
 	err += sn9c102_i2c_write(cam, 0x16, 0x02);
@@ -162,7 +162,7 @@ static int ov7660_init(struct sn9c102_device* cam)
 	err += sn9c102_i2c_write(cam, 0x38, 0x02);
 	err += sn9c102_i2c_write(cam, 0x39, 0x43);
 	err += sn9c102_i2c_write(cam, 0x3A, 0x00);
-	err += sn9c102_i2c_write(cam, 0x3B, 0x02);
+	err += sn9c102_i2c_write(cam, 0x3B, 0x0A);
 	err += sn9c102_i2c_write(cam, 0x3C, 0x6C);
 	err += sn9c102_i2c_write(cam, 0x3D, 0x99);
 	err += sn9c102_i2c_write(cam, 0x3E, 0x0E);
@@ -281,25 +281,34 @@ static int ov7660_get_ctrl(struct sn9c102_device* cam,
 			return -EIO;
 		break;
 	case V4L2_CID_DO_WHITE_BALANCE:
-		ctrl->value = sn9c102_pread_reg(cam, 0x02);
+		if ((ctrl->value = sn9c102_read_reg(cam, 0x02)) < 0)
+			return -EIO;
 		ctrl->value = (ctrl->value & 0x04) ? 1 : 0;
 		break;
 	case V4L2_CID_RED_BALANCE:
-		ctrl->value = sn9c102_pread_reg(cam, 0x05);
+		if ((ctrl->value = sn9c102_read_reg(cam, 0x05)) < 0)
+			return -EIO;
 		ctrl->value &= 0x7f;
 		break;
 	case V4L2_CID_BLUE_BALANCE:
-		ctrl->value = sn9c102_pread_reg(cam, 0x06);
+		if ((ctrl->value = sn9c102_read_reg(cam, 0x06)) < 0)
+			return -EIO;
 		ctrl->value &= 0x7f;
 		break;
 	case SN9C102_V4L2_CID_GREEN_BALANCE:
-		ctrl->value = sn9c102_pread_reg(cam, 0x07);
+		if ((ctrl->value = sn9c102_read_reg(cam, 0x07)) < 0)
+			return -EIO;
 		ctrl->value &= 0x7f;
 		break;
+	case SN9C102_V4L2_CID_BAND_FILTER:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x3b)) < 0)
+			return -EIO;
+		ctrl->value &= 0x08;
+		break;
 	case V4L2_CID_GAIN:
 		if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
 			return -EIO;
-		ctrl->value &= 0x7f;
+		ctrl->value &= 0x1f;
 		break;
 	case V4L2_CID_AUTOGAIN:
 		if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0)
@@ -335,12 +344,15 @@ static int ov7660_set_ctrl(struct sn9c102_device* cam,
 	case SN9C102_V4L2_CID_GREEN_BALANCE:
 		err += sn9c102_write_reg(cam, ctrl->value, 0x07);
 		break;
+	case SN9C102_V4L2_CID_BAND_FILTER:
+		err += sn9c102_i2c_write(cam, ctrl->value << 3, 0x3b);
+		break;
 	case V4L2_CID_GAIN:
-		err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
+		err += sn9c102_i2c_write(cam, 0x00, 0x60 + ctrl->value);
 		break;
 	case V4L2_CID_AUTOGAIN:
-		err += sn9c102_i2c_write(cam, 0x13, 0xf0 | ctrl->value |
-						    (ctrl->value << 1));
+		err += sn9c102_i2c_write(cam, 0x13, 0xc0 |
+						    (ctrl->value * 0x07));
 		break;
 	default:
 		return -EINVAL;
@@ -386,7 +398,7 @@ static int ov7660_set_pix_format(struct sn9c102_device* cam,
 }
 
 
-static struct sn9c102_sensor ov7660 = {
+static const struct sn9c102_sensor ov7660 = {
 	.name = "OV7660",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
 	.supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
@@ -401,9 +413,9 @@ static struct sn9c102_sensor ov7660 = {
 			.type = V4L2_CTRL_TYPE_INTEGER,
 			.name = "global gain",
 			.minimum = 0x00,
-			.maximum = 0x7f,
+			.maximum = 0x1f,
 			.step = 0x01,
-			.default_value = 0x0a,
+			.default_value = 0x09,
 			.flags = 0,
 		},
 		{
@@ -413,7 +425,7 @@ static struct sn9c102_sensor ov7660 = {
 			.minimum = 0x00,
 			.maximum = 0xff,
 			.step = 0x01,
-			.default_value = 0x50,
+			.default_value = 0x27,
 			.flags = 0,
 		},
 		{
@@ -433,7 +445,7 @@ static struct sn9c102_sensor ov7660 = {
 			.minimum = 0x00,
 			.maximum = 0x7f,
 			.step = 0x01,
-			.default_value = 0x1f,
+			.default_value = 0x14,
 			.flags = 0,
 		},
 		{
@@ -443,7 +455,7 @@ static struct sn9c102_sensor ov7660 = {
 			.minimum = 0x00,
 			.maximum = 0x7f,
 			.step = 0x01,
-			.default_value = 0x1e,
+			.default_value = 0x14,
 			.flags = 0,
 		},
 		{
@@ -453,7 +465,7 @@ static struct sn9c102_sensor ov7660 = {
 			.minimum = 0x00,
 			.maximum = 0x01,
 			.step = 0x01,
-			.default_value = 0x00,
+			.default_value = 0x01,
 			.flags = 0,
 		},
 		{
@@ -463,7 +475,17 @@ static struct sn9c102_sensor ov7660 = {
 			.minimum = 0x00,
 			.maximum = 0x7f,
 			.step = 0x01,
-			.default_value = 0x20,
+			.default_value = 0x14,
+			.flags = 0,
+		},
+		{
+			.id = SN9C102_V4L2_CID_BAND_FILTER,
+			.type = V4L2_CTRL_TYPE_BOOLEAN,
+			.name = "band filter",
+			.minimum = 0x00,
+			.maximum = 0x01,
+			.step = 0x01,
+			.default_value = 0x00,
 			.flags = 0,
 		},
 	},
@@ -508,6 +530,7 @@ int sn9c102_probe_ov7660(struct sn9c102_device* cam)
 		return -EIO;
 	if (pid != 0x76 || ver != 0x60)
 		return -ENODEV;
+
 	sn9c102_attach_sensor(cam, &ov7660);
 
 	return 0;

+ 6 - 8
drivers/media/video/sn9c102/sn9c102_pas106b.c

@@ -163,7 +163,7 @@ static int pas106b_set_pix_format(struct sn9c102_device* cam,
 }
 
 
-static struct sn9c102_sensor pas106b = {
+static const struct sn9c102_sensor pas106b = {
 	.name = "PAS106B",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
 	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
@@ -273,23 +273,21 @@ static struct sn9c102_sensor pas106b = {
 
 int sn9c102_probe_pas106b(struct sn9c102_device* cam)
 {
-	int r0 = 0, r1 = 0, err;
+	int r0 = 0, r1 = 0;
 	unsigned int pid = 0;
 
 	/*
 	   Minimal initialization to enable the I2C communication
 	   NOTE: do NOT change the values!
 	*/
-	err = sn9c102_write_const_regs(cam,
-				       {0x01, 0x01}, /* sensor power down */
-				       {0x00, 0x01}, /* sensor power on */
-				       {0x28, 0x17});/* sensor clock 24 MHz */
-	if (err)
+	if (sn9c102_write_const_regs(cam,
+				     {0x01, 0x01}, /* sensor power down */
+				     {0x00, 0x01}, /* sensor power on */
+				    {0x28, 0x17})) /* sensor clock at 24 MHz */
 		return -EIO;
 
 	r0 = sn9c102_i2c_try_read(cam, &pas106b, 0x00);
 	r1 = sn9c102_i2c_try_read(cam, &pas106b, 0x01);
-
 	if (r0 < 0 || r1 < 0)
 		return -EIO;
 

+ 23 - 25
drivers/media/video/sn9c102/sn9c102_pas202bcb.c

@@ -35,29 +35,28 @@ static int pas202bcb_init(struct sn9c102_device* cam)
 	switch (sn9c102_get_bridge(cam)) {
 	case BRIDGE_SN9C101:
 	case BRIDGE_SN9C102:
-		err = sn9c102_write_const_regs(cam, {0x00, 0x10},
-					       {0x00, 0x11}, {0x00, 0x14},
-					       {0x20, 0x17}, {0x30, 0x19},
-					       {0x09, 0x18});
+		err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
+					       {0x00, 0x14}, {0x20, 0x17},
+					       {0x30, 0x19}, {0x09, 0x18});
 		break;
 	case BRIDGE_SN9C103:
-		err = sn9c102_write_const_regs(cam, {0x00, 0x02},
-					       {0x00, 0x03}, {0x1a, 0x04},
-					       {0x20, 0x05}, {0x20, 0x06},
-					       {0x20, 0x07}, {0x00, 0x10},
-					       {0x00, 0x11}, {0x00, 0x14},
-					       {0x20, 0x17}, {0x30, 0x19},
-					       {0x09, 0x18}, {0x02, 0x1c},
-					       {0x03, 0x1d}, {0x0f, 0x1e},
-					       {0x0c, 0x1f}, {0x00, 0x20},
-					       {0x10, 0x21}, {0x20, 0x22},
-					       {0x30, 0x23}, {0x40, 0x24},
-					       {0x50, 0x25}, {0x60, 0x26},
-					       {0x70, 0x27}, {0x80, 0x28},
-					       {0x90, 0x29}, {0xa0, 0x2a},
-					       {0xb0, 0x2b}, {0xc0, 0x2c},
-					       {0xd0, 0x2d}, {0xe0, 0x2e},
-					       {0xf0, 0x2f}, {0xff, 0x30});
+		err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
+					       {0x1a, 0x04}, {0x20, 0x05},
+					       {0x20, 0x06}, {0x20, 0x07},
+					       {0x00, 0x10}, {0x00, 0x11},
+					       {0x00, 0x14}, {0x20, 0x17},
+					       {0x30, 0x19}, {0x09, 0x18},
+					       {0x02, 0x1c}, {0x03, 0x1d},
+					       {0x0f, 0x1e}, {0x0c, 0x1f},
+					       {0x00, 0x20}, {0x10, 0x21},
+					       {0x20, 0x22}, {0x30, 0x23},
+					       {0x40, 0x24}, {0x50, 0x25},
+					       {0x60, 0x26}, {0x70, 0x27},
+					       {0x80, 0x28}, {0x90, 0x29},
+					       {0xa0, 0x2a}, {0xb0, 0x2b},
+					       {0xc0, 0x2c}, {0xd0, 0x2d},
+					       {0xe0, 0x2e}, {0xf0, 0x2f},
+					       {0xff, 0x30});
 		break;
 	default:
 		break;
@@ -197,7 +196,7 @@ static int pas202bcb_set_crop(struct sn9c102_device* cam,
 }
 
 
-static struct sn9c102_sensor pas202bcb = {
+static const struct sn9c102_sensor pas202bcb = {
 	.name = "PAS202BCB",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
 	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
@@ -313,9 +312,8 @@ int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
 					       {0x28, 0x17});/* clock 24 MHz */
 		break;
 	case BRIDGE_SN9C103: /* do _not_ change anything! */
-		err = sn9c102_write_const_regs(cam, {0x09, 0x01},
-					       {0x44, 0x01}, {0x44, 0x02},
-					       {0x29, 0x17});
+		err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x01},
+					       {0x44, 0x02}, {0x29, 0x17});
 		break;
 	default:
 		break;

+ 18 - 15
drivers/media/video/sn9c102/sn9c102_sensor.h

@@ -22,7 +22,7 @@
 #define _SN9C102_SENSOR_H_
 
 #include <linux/usb.h>
-#include <linux/videodev.h>
+#include <linux/videodev2.h>
 #include <linux/device.h>
 #include <linux/stddef.h>
 #include <linux/errno.h>
@@ -74,7 +74,7 @@ sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id);
 /* Attach a probed sensor to the camera. */
 extern void
 sn9c102_attach_sensor(struct sn9c102_device* cam,
-		      struct sn9c102_sensor* sensor);
+		      const struct sn9c102_sensor* sensor);
 
 /*
    Read/write routines: they always return -1 on error, 0 or the read value
@@ -85,10 +85,11 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
 */
 
 /* The "try" I2C I/O versions are used when probing the sensor */
-extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*,
-				 u8 address, u8 value);
-extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
-				u8 address);
+extern int sn9c102_i2c_try_write(struct sn9c102_device*,
+				 const struct sn9c102_sensor*, u8 address,
+				 u8 value);
+extern int sn9c102_i2c_try_read(struct sn9c102_device*,
+				const struct sn9c102_sensor*, u8 address);
 
 /*
    These must be used if and only if the sensor doesn't implement the standard
@@ -102,29 +103,31 @@ extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
    byte.
 */
 extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
-				     struct sn9c102_sensor* sensor, u8 n,
+				     const struct sn9c102_sensor* sensor, u8 n,
 				     u8 data0, u8 data1, u8 data2, u8 data3,
 				     u8 data4, u8 data5);
 extern int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
-				    struct sn9c102_sensor* sensor, u8 data0,
-				    u8 data1, u8 n, u8 buffer[]);
+				    const struct sn9c102_sensor* sensor,
+				    u8 data0, u8 data1, u8 n, u8 buffer[]);
 
 /* To be used after the sensor struct has been attached to the camera struct */
 extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value);
 extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address);
 
 /* I/O on registers in the bridge. Could be used by the sensor methods too */
+extern int sn9c102_read_reg(struct sn9c102_device*, u16 index);
 extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
 extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
 extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2],
 			      int count);
 /*
- * Write multiple registers with constant values.  For example:
- * sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18});
- */
-#define sn9c102_write_const_regs(device, data...) \
-	({ const static u8 _data[][2] = {data}; \
-	sn9c102_write_regs(device, _data, ARRAY_SIZE(_data)); })
+   Write multiple registers with constant values. For example:
+   sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18});
+   Register adresses must be < 256.
+*/
+#define sn9c102_write_const_regs(sn9c102_device, data...)                     \
+	({ const static u8 _valreg[][2] = {data};                             \
+	sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); })
 
 /*****************************************************************************/
 

+ 1 - 1
drivers/media/video/sn9c102/sn9c102_tas5110c1b.c

@@ -88,7 +88,7 @@ static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
 }
 
 
-static struct sn9c102_sensor tas5110c1b = {
+static const struct sn9c102_sensor tas5110c1b = {
 	.name = "TAS5110C1B",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
 	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,

+ 1 - 1
drivers/media/video/sn9c102/sn9c102_tas5110d.c

@@ -68,7 +68,7 @@ static int tas5110d_set_pix_format(struct sn9c102_device* cam,
 }
 
 
-static struct sn9c102_sensor tas5110d = {
+static const struct sn9c102_sensor tas5110d = {
 	.name = "TAS5110D",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
 	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,

+ 1 - 1
drivers/media/video/sn9c102/sn9c102_tas5130d1b.c

@@ -89,7 +89,7 @@ static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
 }
 
 
-static struct sn9c102_sensor tas5130d1b = {
+static const struct sn9c102_sensor tas5130d1b = {
 	.name = "TAS5130D1B",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
 	.supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,

+ 4 - 4
drivers/media/video/usbvideo/Kconfig

@@ -3,7 +3,7 @@ config VIDEO_USBVIDEO
 
 config USB_VICAM
 	tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
-	depends on USB && VIDEO_DEV && VIDEO_V4L1 && EXPERIMENTAL
+	depends on VIDEO_V4L1 && EXPERIMENTAL
 	select VIDEO_USBVIDEO
 	---help---
 	  Say Y here if you have 3com homeconnect camera (vicam).
@@ -13,7 +13,7 @@ config USB_VICAM
 
 config USB_IBMCAM
 	tristate "USB IBM (Xirlink) C-it Camera support"
-	depends on USB && VIDEO_DEV && VIDEO_V4L1
+	depends on VIDEO_V4L1
 	select VIDEO_USBVIDEO
 	---help---
 	  Say Y here if you want to connect a IBM "C-It" camera, also known as
@@ -28,7 +28,7 @@ config USB_IBMCAM
 
 config USB_KONICAWC
 	tristate "USB Konica Webcam support"
-	depends on USB && VIDEO_DEV && VIDEO_V4L1
+	depends on VIDEO_V4L1
 	select VIDEO_USBVIDEO
 	---help---
 	  Say Y here if you want support for webcams based on a Konica
@@ -39,7 +39,7 @@ config USB_KONICAWC
 
 config USB_QUICKCAM_MESSENGER
 	tristate "USB Logitech Quickcam Messenger"
-	depends on USB && VIDEO_DEV && VIDEO_V4L1
+	depends on VIDEO_V4L1
 	select VIDEO_USBVIDEO
 	---help---
 	  Say Y or M here to enable support for the USB Logitech Quickcam

+ 1 - 1
drivers/media/video/usbvision/Kconfig

@@ -1,6 +1,6 @@
 config VIDEO_USBVISION
 	tristate "USB video devices based on Nogatech NT1003/1004/1005"
-	depends on I2C && VIDEO_V4L2 && USB
+	depends on I2C && VIDEO_V4L2
 	select VIDEO_TUNER
 	select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
 	---help---

+ 45 - 17
drivers/media/video/v4l1-compat.c

@@ -127,7 +127,7 @@ set_v4l_control(struct inode            *inode,
 
 /* ----------------------------------------------------------------- */
 
-static int palette2pixelformat[] = {
+const static unsigned int palette2pixelformat[] = {
 	[VIDEO_PALETTE_GREY]    = V4L2_PIX_FMT_GREY,
 	[VIDEO_PALETTE_RGB555]  = V4L2_PIX_FMT_RGB555,
 	[VIDEO_PALETTE_RGB565]  = V4L2_PIX_FMT_RGB565,
@@ -145,7 +145,7 @@ static int palette2pixelformat[] = {
 	[VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P,
 };
 
-static unsigned int
+static unsigned int __attribute_pure__
 palette_to_pixelformat(unsigned int palette)
 {
 	if (palette < ARRAY_SIZE(palette2pixelformat))
@@ -154,8 +154,8 @@ palette_to_pixelformat(unsigned int palette)
 		return 0;
 }
 
-static unsigned int
-pixelformat_to_palette(int pixelformat)
+static unsigned int __attribute_const__
+pixelformat_to_palette(unsigned int pixelformat)
 {
 	int	palette = 0;
 	switch (pixelformat)
@@ -616,6 +616,8 @@ v4l_compat_translate_ioctl(struct inode         *inode,
 	case VIDIOCSPICT: /*  set tone controls & partial capture format  */
 	{
 		struct video_picture	*pict = arg;
+		int mem_err = 0, ovl_err = 0;
+
 		memset(&fbuf2, 0, sizeof(fbuf2));
 
 		set_v4l_control(inode, file,
@@ -628,33 +630,59 @@ v4l_compat_translate_ioctl(struct inode         *inode,
 				V4L2_CID_SATURATION, pict->colour, drv);
 		set_v4l_control(inode, file,
 				V4L2_CID_WHITENESS, pict->whiteness, drv);
+		/*
+		 * V4L1 uses this ioctl to set both memory capture and overlay
+		 * pixel format, while V4L2 has two different ioctls for this.
+		 * Some cards may not support one or the other, and may support
+		 * different pixel formats for memory vs overlay.
+		 */
 
 		fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
 		fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
-		if (err < 0)
+		/* If VIDIOC_G_FMT failed, then the driver likely doesn't
+		   support memory capture.  Trying to set the memory capture
+		   parameters would be pointless.  */
+		if (err < 0) {
 			dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err);
-		if (fmt2->fmt.pix.pixelformat !=
-		    palette_to_pixelformat(pict->palette)) {
+			mem_err = -1000;  /* didn't even try */
+		} else if (fmt2->fmt.pix.pixelformat !=
+			 palette_to_pixelformat(pict->palette)) {
 			fmt2->fmt.pix.pixelformat = palette_to_pixelformat(
 				pict->palette);
-			err = drv(inode, file, VIDIOC_S_FMT, fmt2);
-			if (err < 0)
-				dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",err);
+			mem_err = drv(inode, file, VIDIOC_S_FMT, fmt2);
+			if (mem_err < 0)
+				dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
+					mem_err);
 		}
 
 		err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
-		if (err < 0)
+		/* If VIDIOC_G_FBUF failed, then the driver likely doesn't
+		   support overlay.  Trying to set the overlay parameters
+		   would be quite pointless.  */
+		if (err < 0) {
 			dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err);
-		if (fbuf2.fmt.pixelformat !=
-		    palette_to_pixelformat(pict->palette)) {
+			ovl_err = -1000;  /* didn't even try */
+		} else if (fbuf2.fmt.pixelformat !=
+			 palette_to_pixelformat(pict->palette)) {
 			fbuf2.fmt.pixelformat = palette_to_pixelformat(
 				pict->palette);
-			err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
-			if (err < 0)
-				dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",err);
-			err = 0; /* likely fails for non-root */
+			ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
+			if (ovl_err < 0)
+				dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
+					ovl_err);
 		}
+		if (ovl_err < 0 && mem_err < 0)
+			/* ioctl failed, couldn't set either parameter */
+			if (mem_err != -1000) {
+			    err = mem_err;
+			} else if (ovl_err == -EPERM) {
+			    err = 0;
+			} else {
+			    err = ovl_err;
+			}
+		else
+			err = 0;
 		break;
 	}
 	case VIDIOCGTUNER: /*  get tuner information  */

+ 1 - 3
drivers/media/video/video-buf.c

@@ -702,9 +702,7 @@ videobuf_qbuf(struct videobuf_queue *q,
 		dprintk(1,"qbuf: memory type is wrong.\n");
 		goto done;
 	}
-	if (buf->state == STATE_QUEUED ||
-	    buf->state == STATE_PREPARED ||
-	    buf->state == STATE_ACTIVE) {
+	if (buf->state != STATE_NEEDS_INIT && buf->state != STATE_IDLE) {
 		dprintk(1,"qbuf: buffer is already queued or active.\n");
 		goto done;
 	}

+ 31 - 19
drivers/media/video/videodev.c

@@ -433,13 +433,43 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
 	int                  ret = -EINVAL;
 
 	if ( (vfd->debug & V4L2_DEBUG_IOCTL) &&
-				!(vfd->debug | V4L2_DEBUG_IOCTL_ARG)) {
+				!(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
 		v4l_print_ioctl(vfd->name, cmd);
 	}
 
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+	/***********************************************************
+	 Handles calls to the obsoleted V4L1 API
+	 Due to the nature of VIDIOCGMBUF, each driver that supports
+	 V4L1 should implement its own handler for this ioctl.
+	 ***********************************************************/
+
+	/* --- streaming capture ------------------------------------- */
+	if (cmd == VIDIOCGMBUF) {
+		struct video_mbuf *p=arg;
+
+		memset(p,0,sizeof(p));
+
+		if (!vfd->vidiocgmbuf)
+			return ret;
+		ret=vfd->vidiocgmbuf(file, fh, p);
+		if (!ret)
+			dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n",
+						p->size, p->frames,
+						(unsigned long)p->offsets);
+		return ret;
+	}
+
+	/********************************************************
+	 All other V4L1 calls are handled by v4l1_compat module.
+	 Those calls will be translated into V4L2 calls, and
+	 __video_do_ioctl will be called again, with one or more
+	 V4L2 ioctls.
+	 ********************************************************/
 	if (_IOC_TYPE(cmd)=='v')
 		return v4l_compat_translate_ioctl(inode,file,cmd,arg,
 						__video_do_ioctl);
+#endif
 
 	switch(cmd) {
 	/* --- capabilities ------------------------------------------ */
@@ -791,24 +821,6 @@ static int __video_do_ioctl(struct inode *inode, struct file *file,
 		ret=vfd->vidioc_overlay(file, fh, *i);
 		break;
 	}
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-	/* --- streaming capture ------------------------------------- */
-	case VIDIOCGMBUF:
-	{
-		struct video_mbuf *p=arg;
-
-		memset(p,0,sizeof(p));
-
-		if (!vfd->vidiocgmbuf)
-			break;
-		ret=vfd->vidiocgmbuf(file, fh, p);
-		if (!ret)
-			dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n",
-						p->size, p->frames,
-						(unsigned long)p->offsets);
-		break;
-	}
-#endif
 	case VIDIOC_G_FBUF:
 	{
 		struct v4l2_framebuffer *p=arg;

+ 1 - 1
drivers/media/video/zc0301/Kconfig

@@ -1,6 +1,6 @@
 config USB_ZC0301
 	tristate "USB ZC0301[P] Image Processor and Control Chip support"
-	depends on USB && VIDEO_V4L1
+	depends on VIDEO_V4L1
 	---help---
 	  Say Y here if you want support for cameras based on the ZC0301 or
 	  ZC0301P Image Processors and Control Chips.

+ 2 - 0
include/media/saa7146.h

@@ -58,6 +58,7 @@ struct saa7146_pgtable {
 	unsigned long	offset;
 	/* used for custom pagetables (used for example by budget dvb cards) */
 	struct scatterlist *slist;
+	int		nents;
 };
 
 struct saa7146_pci_extension_data {
@@ -157,6 +158,7 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt);
 void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt);
 int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length );
 char *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt);
+void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, char *mem, struct saa7146_pgtable *pt);
 void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data);
 int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop);
 

+ 2 - 0
include/media/saa7146_vv.h

@@ -216,6 +216,8 @@ void saa7146_set_gpio(struct saa7146_dev *saa, u8 pin, u8 data);
 extern struct saa7146_use_ops saa7146_video_uops;
 int saa7146_start_preview(struct saa7146_fh *fh);
 int saa7146_stop_preview(struct saa7146_fh *fh);
+int saa7146_video_do_ioctl(struct inode *inode, struct file *file,
+			   unsigned int cmd, void *arg);
 
 /* from saa7146_vbi.c */
 extern struct saa7146_use_ops saa7146_vbi_uops;