[media] move tm6000 to drivers/media/video
authorMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 23 Sep 2011 12:30:01 +0000 (09:30 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 23 Sep 2011 12:32:35 +0000 (09:32 -0300)
The serious bugs got fixed already.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
34 files changed:
Documentation/video4linux/CARDLIST.tm6000 [new file with mode: 0644]
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/tm6000/Kconfig [new file with mode: 0644]
drivers/media/video/tm6000/Makefile [new file with mode: 0644]
drivers/media/video/tm6000/tm6000-alsa.c [new file with mode: 0644]
drivers/media/video/tm6000/tm6000-cards.c [new file with mode: 0644]
drivers/media/video/tm6000/tm6000-core.c [new file with mode: 0644]
drivers/media/video/tm6000/tm6000-dvb.c [new file with mode: 0644]
drivers/media/video/tm6000/tm6000-i2c.c [new file with mode: 0644]
drivers/media/video/tm6000/tm6000-input.c [new file with mode: 0644]
drivers/media/video/tm6000/tm6000-regs.h [new file with mode: 0644]
drivers/media/video/tm6000/tm6000-stds.c [new file with mode: 0644]
drivers/media/video/tm6000/tm6000-usb-isoc.h [new file with mode: 0644]
drivers/media/video/tm6000/tm6000-video.c [new file with mode: 0644]
drivers/media/video/tm6000/tm6000.h [new file with mode: 0644]
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/tm6000/CARDLIST [deleted file]
drivers/staging/tm6000/Kconfig [deleted file]
drivers/staging/tm6000/Makefile [deleted file]
drivers/staging/tm6000/README [deleted file]
drivers/staging/tm6000/TODO [deleted file]
drivers/staging/tm6000/tm6000-alsa.c [deleted file]
drivers/staging/tm6000/tm6000-cards.c [deleted file]
drivers/staging/tm6000/tm6000-core.c [deleted file]
drivers/staging/tm6000/tm6000-dvb.c [deleted file]
drivers/staging/tm6000/tm6000-i2c.c [deleted file]
drivers/staging/tm6000/tm6000-input.c [deleted file]
drivers/staging/tm6000/tm6000-regs.h [deleted file]
drivers/staging/tm6000/tm6000-stds.c [deleted file]
drivers/staging/tm6000/tm6000-usb-isoc.h [deleted file]
drivers/staging/tm6000/tm6000-video.c [deleted file]
drivers/staging/tm6000/tm6000.h [deleted file]

diff --git a/Documentation/video4linux/CARDLIST.tm6000 b/Documentation/video4linux/CARDLIST.tm6000
new file mode 100644 (file)
index 0000000..b5edce4
--- /dev/null
@@ -0,0 +1,16 @@
+  1 -> Generic tm5600 board                   (tm5600)          [6000:0001]
+  2 -> Generic tm6000 board                   (tm6000)          [6000:0001]
+  3 -> Generic tm6010 board                   (tm6010)          [6000:0002]
+  4 -> 10Moons UT821                          (tm5600)          [6000:0001]
+  5 -> 10Moons UT330                          (tm5600)
+  6 -> ADSTech Dual TV                        (tm6000)          [06e1:f332]
+  7 -> FreeCom and similar                    (tm6000)          [14aa:0620]
+  8 -> ADSTech Mini Dual TV                   (tm6000)          [06e1:b339]
+  9 -> Hauppauge WinTV HVR-900H/USB2 Stick    (tm6010)          [2040:6600,2040:6601,2040:6610,2040:6611]
+ 10 -> Beholder Wander                        (tm6010)          [6000:dec0]
+ 11 -> Beholder Voyager                       (tm6010)          [6000:dec1]
+ 12 -> TerraTec Cinergy Hybrid XE/Cinergy Hybrid Stick (tm6010) [0ccd:0086,0ccd:00a5]
+ 13 -> TwinHan TU501                          (tm6010)          [13d3:3240,13d3:3241,13d3:3243,13d3:3264]
+ 14 -> Beholder Wander Lite                   (tm6010)          [6000:dec2]
+ 15 -> Beholder Voyager Lite                  (tm6010)          [6000:dec3]
+
index 4a10086bb46064e177d0976d84ed58e8bb9e086d..aed5b3d740ca0160f7ae500e52f60ca754cf7388 100644 (file)
@@ -1019,6 +1019,8 @@ source "drivers/media/video/tlg2300/Kconfig"
 
 source "drivers/media/video/cx231xx/Kconfig"
 
+source "drivers/media/video/tm6000/Kconfig"
+
 source "drivers/media/video/usbvision/Kconfig"
 
 source "drivers/media/video/et61x251/Kconfig"
index 0f0c6af58d81898f24e23e42ea10f16b31b3fcd9..11fff97e7196c43cb2b2aa5cab7200d9042882ee 100644 (file)
@@ -107,6 +107,7 @@ obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
 obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
 obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
 obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
+obj-$(CONFIG_VIDEO_TM6000) += tm6000/
 obj-$(CONFIG_VIDEO_MXB) += mxb.o
 obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
 obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
diff --git a/drivers/media/video/tm6000/Kconfig b/drivers/media/video/tm6000/Kconfig
new file mode 100644 (file)
index 0000000..114eec8
--- /dev/null
@@ -0,0 +1,33 @@
+config VIDEO_TM6000
+       tristate "TV Master TM5600/6000/6010 driver"
+       depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB && EXPERIMENTAL
+       select VIDEO_TUNER
+       select MEDIA_TUNER_XC2028
+       select MEDIA_TUNER_XC5000
+       select VIDEOBUF_VMALLOC
+       help
+         Support for TM5600/TM6000/TM6010 USB Device
+
+         Since these cards have no MPEG decoder onboard, they transmit
+         only compressed MPEG data over the usb bus, so you need
+         an external software decoder to watch TV on your computer.
+
+         Say Y if you own such a device and want to use it.
+
+config VIDEO_TM6000_ALSA
+       tristate "TV Master TM5600/6000/6010 audio support"
+       depends on VIDEO_TM6000 && SND && EXPERIMENTAL
+       select SND_PCM
+       ---help---
+         This is a video4linux driver for direct (DMA) audio for
+         TM5600/TM6000/TM6010 USB Devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tm6000-alsa.
+
+config VIDEO_TM6000_DVB
+       tristate "DVB Support for tm6000 based TV cards"
+       depends on VIDEO_TM6000 && DVB_CORE && USB && EXPERIMENTAL
+       select DVB_ZL10353
+       ---help---
+         This adds support for DVB cards based on the tm5600/tm6000 chip.
diff --git a/drivers/media/video/tm6000/Makefile b/drivers/media/video/tm6000/Makefile
new file mode 100644 (file)
index 0000000..395515b
--- /dev/null
@@ -0,0 +1,15 @@
+tm6000-y := tm6000-cards.o \
+                  tm6000-core.o  \
+                  tm6000-i2c.o   \
+                  tm6000-video.o \
+                  tm6000-stds.o \
+                  tm6000-input.o
+
+obj-$(CONFIG_VIDEO_TM6000) += tm6000.o
+obj-$(CONFIG_VIDEO_TM6000_ALSA) += tm6000-alsa.o
+obj-$(CONFIG_VIDEO_TM6000_DVB) += tm6000-dvb.o
+
+ccflags-y := -Idrivers/media/video
+ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/media/video/tm6000/tm6000-alsa.c b/drivers/media/video/tm6000/tm6000-alsa.c
new file mode 100644 (file)
index 0000000..7d675c7
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+ *
+ *  Support for audio capture for tm5600/6000/6010
+ *    (c) 2007-2008 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ *  Based on cx88-alsa.c
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+
+
+#include "tm6000.h"
+#include "tm6000-regs.h"
+
+#undef dprintk
+
+#define dprintk(level, fmt, arg...) do {                                  \
+       if (debug >= level)                                                \
+               printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg); \
+       } while (0)
+
+/****************************************************************************
+                       Module global static vars
+ ****************************************************************************/
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
+
+static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable tm6000x soundcard. default enabled.");
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for tm6000x capture interface(s).");
+
+
+/****************************************************************************
+                               Module macros
+ ****************************************************************************/
+
+MODULE_DESCRIPTION("ALSA driver module for tm5600/tm6000/tm6010 based TV cards");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Trident,tm5600},"
+                       "{{Trident,tm6000},"
+                       "{{Trident,tm6010}");
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+/****************************************************************************
+                       Module specific funtions
+ ****************************************************************************/
+
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int _tm6000_start_audio_dma(struct snd_tm6000_card *chip)
+{
+       struct tm6000_core *core = chip->core;
+
+       dprintk(1, "Starting audio DMA\n");
+
+       /* Enables audio */
+       tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x40, 0x40);
+
+       tm6000_set_audio_bitrate(core, 48000);
+
+       return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int _tm6000_stop_audio_dma(struct snd_tm6000_card *chip)
+{
+       struct tm6000_core *core = chip->core;
+
+       dprintk(1, "Stopping audio DMA\n");
+
+       /* Disables audio */
+       tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x00, 0x40);
+
+       return 0;
+}
+
+static void dsp_buffer_free(struct snd_pcm_substream *substream)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+
+       dprintk(2, "Freeing buffer\n");
+
+       vfree(substream->runtime->dma_area);
+       substream->runtime->dma_area = NULL;
+       substream->runtime->dma_bytes = 0;
+}
+
+static int dsp_buffer_alloc(struct snd_pcm_substream *substream, int size)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+
+       dprintk(2, "Allocating buffer\n");
+
+       if (substream->runtime->dma_area) {
+               if (substream->runtime->dma_bytes > size)
+                       return 0;
+
+               dsp_buffer_free(substream);
+       }
+
+       substream->runtime->dma_area = vmalloc(size);
+       if (!substream->runtime->dma_area)
+               return -ENOMEM;
+
+       substream->runtime->dma_bytes = size;
+
+       return 0;
+}
+
+
+/****************************************************************************
+                               ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE      4096
+
+static struct snd_pcm_hardware snd_tm6000_digital_hw = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID,
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+       .rates = SNDRV_PCM_RATE_CONTINUOUS,
+       .rate_min = 48000,
+       .rate_max = 48000,
+       .channels_min = 2,
+       .channels_max = 2,
+       .period_bytes_min = 64,
+       .period_bytes_max = 12544,
+       .periods_min = 1,
+       .periods_max = 98,
+       .buffer_bytes_max = 62720 * 8,
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_tm6000_pcm_open(struct snd_pcm_substream *substream)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int err;
+
+       err = snd_pcm_hw_constraint_pow2(runtime, 0,
+                                        SNDRV_PCM_HW_PARAM_PERIODS);
+       if (err < 0)
+               goto _error;
+
+       chip->substream = substream;
+
+       runtime->hw = snd_tm6000_digital_hw;
+
+       return 0;
+_error:
+       dprintk(1, "Error opening PCM!\n");
+       return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_tm6000_close(struct snd_pcm_substream *substream)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+       struct tm6000_core *core = chip->core;
+
+       if (atomic_read(&core->stream_started) > 0) {
+               atomic_set(&core->stream_started, 0);
+               schedule_work(&core->wq_trigger);
+       }
+
+       return 0;
+}
+
+static int tm6000_fillbuf(struct tm6000_core *core, char *buf, int size)
+{
+       struct snd_tm6000_card *chip = core->adev;
+       struct snd_pcm_substream *substream = chip->substream;
+       struct snd_pcm_runtime *runtime;
+       int period_elapsed = 0;
+       unsigned int stride, buf_pos;
+       int length;
+
+       if (atomic_read(&core->stream_started) == 0)
+               return 0;
+
+       if (!size || !substream) {
+               dprintk(1, "substream was NULL\n");
+               return -EINVAL;
+       }
+
+       runtime = substream->runtime;
+       if (!runtime || !runtime->dma_area) {
+               dprintk(1, "runtime was NULL\n");
+               return -EINVAL;
+       }
+
+       buf_pos = chip->buf_pos;
+       stride = runtime->frame_bits >> 3;
+
+       if (stride == 0) {
+               dprintk(1, "stride is zero\n");
+               return -EINVAL;
+       }
+
+       length = size / stride;
+       if (length == 0) {
+               dprintk(1, "%s: length was zero\n", __func__);
+               return -EINVAL;
+       }
+
+       dprintk(1, "Copying %d bytes at %p[%d] - buf size=%d x %d\n", size,
+               runtime->dma_area, buf_pos,
+               (unsigned int)runtime->buffer_size, stride);
+
+       if (buf_pos + length >= runtime->buffer_size) {
+               unsigned int cnt = runtime->buffer_size - buf_pos;
+               memcpy(runtime->dma_area + buf_pos * stride, buf, cnt * stride);
+               memcpy(runtime->dma_area, buf + cnt * stride,
+                       length * stride - cnt * stride);
+       } else
+               memcpy(runtime->dma_area + buf_pos * stride, buf,
+                       length * stride);
+
+       snd_pcm_stream_lock(substream);
+
+       chip->buf_pos += length;
+       if (chip->buf_pos >= runtime->buffer_size)
+               chip->buf_pos -= runtime->buffer_size;
+
+       chip->period_pos += length;
+       if (chip->period_pos >= runtime->period_size) {
+               chip->period_pos -= runtime->period_size;
+               period_elapsed = 1;
+       }
+
+       snd_pcm_stream_unlock(substream);
+
+       if (period_elapsed)
+               snd_pcm_period_elapsed(substream);
+
+       return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_tm6000_hw_params(struct snd_pcm_substream *substream,
+                             struct snd_pcm_hw_params *hw_params)
+{
+       int size, rc;
+
+       size = params_period_bytes(hw_params) * params_periods(hw_params);
+
+       rc = dsp_buffer_alloc(substream, size);
+       if (rc < 0)
+               return rc;
+
+       return 0;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_tm6000_hw_free(struct snd_pcm_substream *substream)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+       struct tm6000_core *core = chip->core;
+
+       if (atomic_read(&core->stream_started) > 0) {
+               atomic_set(&core->stream_started, 0);
+               schedule_work(&core->wq_trigger);
+       }
+
+       dsp_buffer_free(substream);
+       return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_tm6000_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+
+       chip->buf_pos = 0;
+       chip->period_pos = 0;
+
+       return 0;
+}
+
+
+/*
+ * trigger callback
+ */
+static void audio_trigger(struct work_struct *work)
+{
+       struct tm6000_core *core = container_of(work, struct tm6000_core,
+                                               wq_trigger);
+       struct snd_tm6000_card *chip = core->adev;
+
+       if (atomic_read(&core->stream_started)) {
+               dprintk(1, "starting capture");
+               _tm6000_start_audio_dma(chip);
+       } else {
+               dprintk(1, "stopping capture");
+               _tm6000_stop_audio_dma(chip);
+       }
+}
+
+static int snd_tm6000_card_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+       struct tm6000_core *core = chip->core;
+       int err = 0;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               atomic_set(&core->stream_started, 1);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               atomic_set(&core->stream_started, 0);
+               break;
+       default:
+               err = -EINVAL;
+               break;
+       }
+       schedule_work(&core->wq_trigger);
+
+       return err;
+}
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_tm6000_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+
+       return chip->buf_pos;
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_tm6000_pcm_ops = {
+       .open = snd_tm6000_pcm_open,
+       .close = snd_tm6000_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = snd_tm6000_hw_params,
+       .hw_free = snd_tm6000_hw_free,
+       .prepare = snd_tm6000_prepare,
+       .trigger = snd_tm6000_card_trigger,
+       .pointer = snd_tm6000_pointer,
+};
+
+/*
+ * create a PCM device
+ */
+
+/* FIXME: Control interface - How to control volume/mute? */
+
+/****************************************************************************
+                       Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * Alsa Constructor - Component probe
+ */
+static int tm6000_audio_init(struct tm6000_core *dev)
+{
+       struct snd_card         *card;
+       struct snd_tm6000_card  *chip;
+       int                     rc;
+       static int              devnr;
+       char                    component[14];
+       struct snd_pcm          *pcm;
+
+       if (!dev)
+               return 0;
+
+       if (devnr >= SNDRV_CARDS)
+               return -ENODEV;
+
+       if (!enable[devnr])
+               return -ENOENT;
+
+       rc = snd_card_create(index[devnr], "tm6000", THIS_MODULE, 0, &card);
+       if (rc < 0) {
+               snd_printk(KERN_ERR "cannot create card instance %d\n", devnr);
+               return rc;
+       }
+       strcpy(card->driver, "tm6000-alsa");
+       strcpy(card->shortname, "TM5600/60x0");
+       sprintf(card->longname, "TM5600/60x0 Audio at bus %d device %d",
+               dev->udev->bus->busnum, dev->udev->devnum);
+
+       sprintf(component, "USB%04x:%04x",
+               le16_to_cpu(dev->udev->descriptor.idVendor),
+               le16_to_cpu(dev->udev->descriptor.idProduct));
+       snd_component_add(card, component);
+       snd_card_set_dev(card, &dev->udev->dev);
+
+       chip = kzalloc(sizeof(struct snd_tm6000_card), GFP_KERNEL);
+       if (!chip) {
+               rc = -ENOMEM;
+               goto error;
+       }
+
+       chip->core = dev;
+       chip->card = card;
+       dev->adev = chip;
+       spin_lock_init(&chip->reg_lock);
+
+       rc = snd_pcm_new(card, "TM6000 Audio", 0, 0, 1, &pcm);
+       if (rc < 0)
+               goto error_chip;
+
+       pcm->info_flags = 0;
+       pcm->private_data = chip;
+       strcpy(pcm->name, "Trident TM5600/60x0");
+
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops);
+
+       INIT_WORK(&dev->wq_trigger, audio_trigger);
+       rc = snd_card_register(card);
+       if (rc < 0)
+               goto error_chip;
+
+       dprintk(1, "Registered audio driver for %s\n", card->longname);
+
+       return 0;
+
+error_chip:
+       kfree(chip);
+       dev->adev = NULL;
+error:
+       snd_card_free(card);
+       return rc;
+}
+
+static int tm6000_audio_fini(struct tm6000_core *dev)
+{
+       struct snd_tm6000_card  *chip = dev->adev;
+
+       if (!dev)
+               return 0;
+
+       if (!chip)
+               return 0;
+
+       if (!chip->card)
+               return 0;
+
+       snd_card_free(chip->card);
+       chip->card = NULL;
+       kfree(chip);
+       dev->adev = NULL;
+
+       return 0;
+}
+
+static struct tm6000_ops audio_ops = {
+       .type   = TM6000_AUDIO,
+       .name   = "TM6000 Audio Extension",
+       .init   = tm6000_audio_init,
+       .fini   = tm6000_audio_fini,
+       .fillbuf = tm6000_fillbuf,
+};
+
+static int __init tm6000_alsa_register(void)
+{
+       return tm6000_register_extension(&audio_ops);
+}
+
+static void __exit tm6000_alsa_unregister(void)
+{
+       tm6000_unregister_extension(&audio_ops);
+}
+
+module_init(tm6000_alsa_register);
+module_exit(tm6000_alsa_unregister);
diff --git a/drivers/media/video/tm6000/tm6000-cards.c b/drivers/media/video/tm6000/tm6000-cards.c
new file mode 100644 (file)
index 0000000..ec2578a
--- /dev/null
@@ -0,0 +1,1402 @@
+/*
+ *  tm6000-cards.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+#include <media/tvaudio.h>
+#include <media/i2c-addr.h>
+#include <media/rc-map.h>
+
+#include "tm6000.h"
+#include "tm6000-regs.h"
+#include "tuner-xc2028.h"
+#include "xc5000.h"
+
+#define TM6000_BOARD_UNKNOWN                   0
+#define TM5600_BOARD_GENERIC                   1
+#define TM6000_BOARD_GENERIC                   2
+#define TM6010_BOARD_GENERIC                   3
+#define TM5600_BOARD_10MOONS_UT821             4
+#define TM5600_BOARD_10MOONS_UT330             5
+#define TM6000_BOARD_ADSTECH_DUAL_TV           6
+#define TM6000_BOARD_FREECOM_AND_SIMILAR       7
+#define TM6000_BOARD_ADSTECH_MINI_DUAL_TV      8
+#define TM6010_BOARD_HAUPPAUGE_900H            9
+#define TM6010_BOARD_BEHOLD_WANDER             10
+#define TM6010_BOARD_BEHOLD_VOYAGER            11
+#define TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE        12
+#define TM6010_BOARD_TWINHAN_TU501             13
+#define TM6010_BOARD_BEHOLD_WANDER_LITE                14
+#define TM6010_BOARD_BEHOLD_VOYAGER_LITE       15
+#define TM5600_BOARD_TERRATEC_GRABSTER         16
+
+#define is_generic(model) ((model == TM6000_BOARD_UNKNOWN) || \
+                          (model == TM5600_BOARD_GENERIC) || \
+                          (model == TM6000_BOARD_GENERIC) || \
+                          (model == TM6010_BOARD_GENERIC))
+
+#define TM6000_MAXBOARDS        16
+static unsigned int card[]     = {[0 ... (TM6000_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(card,  int, NULL, 0444);
+
+static unsigned long tm6000_devused;
+
+
+struct tm6000_board {
+       char            *name;
+       char            eename[16];             /* EEPROM name */
+       unsigned        eename_size;            /* size of EEPROM name */
+       unsigned        eename_pos;             /* Position where it appears at ROM */
+
+       struct tm6000_capabilities caps;
+
+       enum            tm6000_devtype type;    /* variant of the chipset */
+       int             tuner_type;     /* type of the tuner */
+       int             tuner_addr;     /* tuner address */
+       int             demod_addr;     /* demodulator address */
+
+       struct tm6000_gpio gpio;
+
+       struct tm6000_input     vinput[3];
+       struct tm6000_input     rinput;
+
+       char            *ir_codes;
+};
+
+static struct tm6000_board tm6000_boards[] = {
+       [TM6000_BOARD_UNKNOWN] = {
+               .name         = "Unknown tm6000 video grabber",
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_eeprom     = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6000_GPIO_1,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM5600_BOARD_GENERIC] = {
+               .name         = "Generic tm5600 board",
+               .type         = TM5600,
+               .tuner_type   = TUNER_XC2028,
+               .tuner_addr   = 0xc2 >> 1,
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_eeprom     = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6000_GPIO_1,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6000_BOARD_GENERIC] = {
+               .name         = "Generic tm6000 board",
+               .tuner_type   = TUNER_XC2028,
+               .tuner_addr   = 0xc2 >> 1,
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_eeprom     = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6000_GPIO_1,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6010_BOARD_GENERIC] = {
+               .name         = "Generic tm6010 board",
+               .type         = TM6010,
+               .tuner_type   = TUNER_XC2028,
+               .tuner_addr   = 0xc2 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_dvb        = 1,
+                       .has_zl10353    = 1,
+                       .has_eeprom     = 1,
+                       .has_remote     = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_2,
+                       .tuner_on       = TM6010_GPIO_3,
+                       .demod_reset    = TM6010_GPIO_1,
+                       .demod_on       = TM6010_GPIO_4,
+                       .power_led      = TM6010_GPIO_7,
+                       .dvb_led        = TM6010_GPIO_5,
+                       .ir             = TM6010_GPIO_0,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM5600_BOARD_10MOONS_UT821] = {
+               .name         = "10Moons UT 821",
+               .tuner_type   = TUNER_XC2028,
+               .eename       = { '1', '0', 'M', 'O', 'O', 'N', 'S', '5', '6', '0', '0', 0xff, 0x45, 0x5b},
+               .eename_size  = 14,
+               .eename_pos   = 0x14,
+               .type         = TM5600,
+               .tuner_addr   = 0xc2 >> 1,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_eeprom   = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6000_GPIO_1,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM5600_BOARD_10MOONS_UT330] = {
+               .name         = "10Moons UT 330",
+               .tuner_type   = TUNER_PHILIPS_FQ1216AME_MK4,
+               .tuner_addr   = 0xc8 >> 1,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_dvb      = 0,
+                       .has_zl10353  = 0,
+                       .has_eeprom   = 1,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6000_BOARD_ADSTECH_DUAL_TV] = {
+               .name         = "ADSTECH Dual TV USB",
+               .tuner_type   = TUNER_XC2028,
+               .tuner_addr   = 0xc8 >> 1,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_tda9874  = 1,
+                       .has_dvb      = 1,
+                       .has_zl10353  = 1,
+                       .has_eeprom   = 1,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6000_BOARD_FREECOM_AND_SIMILAR] = {
+               .name         = "Freecom Hybrid Stick / Moka DVB-T Receiver Dual",
+               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
+               .tuner_addr   = 0xc2 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_dvb      = 1,
+                       .has_zl10353  = 1,
+                       .has_eeprom   = 0,
+                       .has_remote   = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6000_GPIO_4,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6000_BOARD_ADSTECH_MINI_DUAL_TV] = {
+               .name         = "ADSTECH Mini Dual TV USB",
+               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
+               .tuner_addr   = 0xc8 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_dvb      = 1,
+                       .has_zl10353  = 1,
+                       .has_eeprom   = 0,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6000_GPIO_4,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6010_BOARD_HAUPPAUGE_900H] = {
+               .name         = "Hauppauge WinTV HVR-900H / WinTV USB2-Stick",
+               .eename       = { 'H', 0, 'V', 0, 'R', 0, '9', 0, '0', 0, '0', 0, 'H', 0 },
+               .eename_size  = 14,
+               .eename_pos   = 0x42,
+               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
+               .tuner_addr   = 0xc2 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .type         = TM6010,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_dvb      = 1,
+                       .has_zl10353  = 1,
+                       .has_eeprom   = 1,
+                       .has_remote   = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_2,
+                       .tuner_on       = TM6010_GPIO_3,
+                       .demod_reset    = TM6010_GPIO_1,
+                       .demod_on       = TM6010_GPIO_4,
+                       .power_led      = TM6010_GPIO_7,
+                       .dvb_led        = TM6010_GPIO_5,
+                       .ir             = TM6010_GPIO_0,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6010_BOARD_BEHOLD_WANDER] = {
+               .name         = "Beholder Wander DVB-T/TV/FM USB2.0",
+               .tuner_type   = TUNER_XC5000,
+               .tuner_addr   = 0xc2 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .type         = TM6010,
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_dvb        = 1,
+                       .has_zl10353    = 1,
+                       .has_eeprom     = 1,
+                       .has_remote     = 1,
+                       .has_radio      = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_0,
+                       .demod_reset    = TM6010_GPIO_1,
+                       .power_led      = TM6010_GPIO_6,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+               .rinput = {
+                       .type   = TM6000_INPUT_RADIO,
+                       .amux   = TM6000_AMUX_ADC1,
+               },
+       },
+       [TM6010_BOARD_BEHOLD_VOYAGER] = {
+               .name         = "Beholder Voyager TV/FM USB2.0",
+               .tuner_type   = TUNER_XC5000,
+               .tuner_addr   = 0xc2 >> 1,
+               .type         = TM6010,
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_dvb        = 0,
+                       .has_zl10353    = 0,
+                       .has_eeprom     = 1,
+                       .has_remote     = 1,
+                       .has_radio      = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_0,
+                       .power_led      = TM6010_GPIO_6,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+               .rinput = {
+                       .type   = TM6000_INPUT_RADIO,
+                       .amux   = TM6000_AMUX_ADC1,
+               },
+       },
+       [TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE] = {
+               .name         = "Terratec Cinergy Hybrid XE / Cinergy Hybrid-Stick",
+               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
+               .tuner_addr   = 0xc2 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .type         = TM6010,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_dvb      = 1,
+                       .has_zl10353  = 1,
+                       .has_eeprom   = 1,
+                       .has_remote   = 1,
+                       .has_radio    = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_2,
+                       .tuner_on       = TM6010_GPIO_3,
+                       .demod_reset    = TM6010_GPIO_1,
+                       .demod_on       = TM6010_GPIO_4,
+                       .power_led      = TM6010_GPIO_7,
+                       .dvb_led        = TM6010_GPIO_5,
+                       .ir             = TM6010_GPIO_0,
+               },
+               .ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS,
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+               .rinput = {
+                       .type = TM6000_INPUT_RADIO,
+                       .amux = TM6000_AMUX_SIF1,
+               },
+       },
+       [TM5600_BOARD_TERRATEC_GRABSTER] = {
+               .name         = "Terratec Grabster AV 150/250 MX",
+               .type         = TM5600,
+               .tuner_type   = TUNER_ABSENT,
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6010_BOARD_TWINHAN_TU501] = {
+               .name         = "Twinhan TU501(704D1)",
+               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
+               .tuner_addr   = 0xc2 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .type         = TM6010,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_dvb      = 1,
+                       .has_zl10353  = 1,
+                       .has_eeprom   = 1,
+                       .has_remote   = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_2,
+                       .tuner_on       = TM6010_GPIO_3,
+                       .demod_reset    = TM6010_GPIO_1,
+                       .demod_on       = TM6010_GPIO_4,
+                       .power_led      = TM6010_GPIO_7,
+                       .dvb_led        = TM6010_GPIO_5,
+                       .ir             = TM6010_GPIO_0,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6010_BOARD_BEHOLD_WANDER_LITE] = {
+               .name         = "Beholder Wander Lite DVB-T/TV/FM USB2.0",
+               .tuner_type   = TUNER_XC5000,
+               .tuner_addr   = 0xc2 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .type         = TM6010,
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_dvb        = 1,
+                       .has_zl10353    = 1,
+                       .has_eeprom     = 1,
+                       .has_remote     = 0,
+                       .has_radio      = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_0,
+                       .demod_reset    = TM6010_GPIO_1,
+                       .power_led      = TM6010_GPIO_6,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       },
+               },
+               .rinput = {
+                       .type   = TM6000_INPUT_RADIO,
+                       .amux   = TM6000_AMUX_ADC1,
+               },
+       },
+       [TM6010_BOARD_BEHOLD_VOYAGER_LITE] = {
+               .name         = "Beholder Voyager Lite TV/FM USB2.0",
+               .tuner_type   = TUNER_XC5000,
+               .tuner_addr   = 0xc2 >> 1,
+               .type         = TM6010,
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_dvb        = 0,
+                       .has_zl10353    = 0,
+                       .has_eeprom     = 1,
+                       .has_remote     = 0,
+                       .has_radio      = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_0,
+                       .power_led      = TM6010_GPIO_6,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       },
+               },
+               .rinput = {
+                       .type   = TM6000_INPUT_RADIO,
+                       .amux   = TM6000_AMUX_ADC1,
+               },
+       },
+};
+
+/* table of devices that work with this driver */
+static struct usb_device_id tm6000_id_table[] = {
+       { USB_DEVICE(0x6000, 0x0001), .driver_info = TM5600_BOARD_GENERIC },
+       { USB_DEVICE(0x6000, 0x0002), .driver_info = TM6010_BOARD_GENERIC },
+       { USB_DEVICE(0x06e1, 0xf332), .driver_info = TM6000_BOARD_ADSTECH_DUAL_TV },
+       { USB_DEVICE(0x14aa, 0x0620), .driver_info = TM6000_BOARD_FREECOM_AND_SIMILAR },
+       { USB_DEVICE(0x06e1, 0xb339), .driver_info = TM6000_BOARD_ADSTECH_MINI_DUAL_TV },
+       { USB_DEVICE(0x2040, 0x6600), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
+       { USB_DEVICE(0x2040, 0x6601), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
+       { USB_DEVICE(0x2040, 0x6610), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
+       { USB_DEVICE(0x2040, 0x6611), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
+       { USB_DEVICE(0x6000, 0xdec0), .driver_info = TM6010_BOARD_BEHOLD_WANDER },
+       { USB_DEVICE(0x6000, 0xdec1), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER },
+       { USB_DEVICE(0x0ccd, 0x0086), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE },
+       { USB_DEVICE(0x0ccd, 0x00A5), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE },
+       { USB_DEVICE(0x0ccd, 0x0079), .driver_info = TM5600_BOARD_TERRATEC_GRABSTER },
+       { USB_DEVICE(0x13d3, 0x3240), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
+       { USB_DEVICE(0x13d3, 0x3241), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
+       { USB_DEVICE(0x13d3, 0x3243), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
+       { USB_DEVICE(0x13d3, 0x3264), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
+       { USB_DEVICE(0x6000, 0xdec2), .driver_info = TM6010_BOARD_BEHOLD_WANDER_LITE },
+       { USB_DEVICE(0x6000, 0xdec3), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER_LITE },
+       { }
+};
+
+/* Control power led for show some activity */
+void tm6000_flash_led(struct tm6000_core *dev, u8 state)
+{
+       /* Power LED unconfigured */
+       if (!dev->gpio.power_led)
+               return;
+
+       /* ON Power LED */
+       if (state) {
+               switch (dev->model) {
+               case TM6010_BOARD_HAUPPAUGE_900H:
+               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+               case TM6010_BOARD_TWINHAN_TU501:
+                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                               dev->gpio.power_led, 0x00);
+                       break;
+               case TM6010_BOARD_BEHOLD_WANDER:
+               case TM6010_BOARD_BEHOLD_VOYAGER:
+               case TM6010_BOARD_BEHOLD_WANDER_LITE:
+               case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
+                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                               dev->gpio.power_led, 0x01);
+                       break;
+               }
+       }
+       /* OFF Power LED */
+       else {
+               switch (dev->model) {
+               case TM6010_BOARD_HAUPPAUGE_900H:
+               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+               case TM6010_BOARD_TWINHAN_TU501:
+                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                               dev->gpio.power_led, 0x01);
+                       break;
+               case TM6010_BOARD_BEHOLD_WANDER:
+               case TM6010_BOARD_BEHOLD_VOYAGER:
+               case TM6010_BOARD_BEHOLD_WANDER_LITE:
+               case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
+                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                               dev->gpio.power_led, 0x00);
+                       break;
+               }
+       }
+}
+
+/* Tuner callback to provide the proper gpio changes needed for xc5000 */
+int tm6000_xc5000_callback(void *ptr, int component, int command, int arg)
+{
+       int rc = 0;
+       struct tm6000_core *dev = ptr;
+
+       if (dev->tuner_type != TUNER_XC5000)
+               return 0;
+
+       switch (command) {
+       case XC5000_TUNER_RESET:
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                              dev->gpio.tuner_reset, 0x01);
+               msleep(15);
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                              dev->gpio.tuner_reset, 0x00);
+               msleep(15);
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                              dev->gpio.tuner_reset, 0x01);
+               break;
+       }
+       return rc;
+}
+EXPORT_SYMBOL_GPL(tm6000_xc5000_callback);
+
+/* Tuner callback to provide the proper gpio changes needed for xc2028 */
+
+int tm6000_tuner_callback(void *ptr, int component, int command, int arg)
+{
+       int rc = 0;
+       struct tm6000_core *dev = ptr;
+
+       if (dev->tuner_type != TUNER_XC2028)
+               return 0;
+
+       switch (command) {
+       case XC2028_RESET_CLK:
+               tm6000_ir_wait(dev, 0);
+
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT,
+                                       0x02, arg);
+               msleep(10);
+               rc = tm6000_i2c_reset(dev, 10);
+               break;
+       case XC2028_TUNER_RESET:
+               /* Reset codes during load firmware */
+               switch (arg) {
+               case 0:
+                       /* newer tuner can faster reset */
+                       switch (dev->model) {
+                       case TM5600_BOARD_10MOONS_UT821:
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x01);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              0x300, 0x01);
+                               msleep(10);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x00);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              0x300, 0x00);
+                               msleep(10);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x01);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              0x300, 0x01);
+                               break;
+                       case TM6010_BOARD_HAUPPAUGE_900H:
+                       case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+                       case TM6010_BOARD_TWINHAN_TU501:
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x01);
+                               msleep(60);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x00);
+                               msleep(75);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x01);
+                               msleep(60);
+                               break;
+                       default:
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x00);
+                               msleep(130);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x01);
+                               msleep(130);
+                               break;
+                       }
+
+                       tm6000_ir_wait(dev, 1);
+                       break;
+               case 1:
+                       tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT,
+                                               0x02, 0x01);
+                       msleep(10);
+                       break;
+               case 2:
+                       rc = tm6000_i2c_reset(dev, 100);
+                       break;
+               }
+               break;
+       case XC2028_I2C_FLUSH:
+               tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
+               tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
+               break;
+       }
+       return rc;
+}
+EXPORT_SYMBOL_GPL(tm6000_tuner_callback);
+
+int tm6000_cards_setup(struct tm6000_core *dev)
+{
+       /*
+        * Board-specific initialization sequence. Handles all GPIO
+        * initialization sequences that are board-specific.
+        * Up to now, all found devices use GPIO1 and GPIO4 at the same way.
+        * Probably, they're all based on some reference device. Due to that,
+        * there's a common routine at the end to handle those GPIO's. Devices
+        * that use different pinups or init sequences can just return at
+        * the board-specific session.
+        */
+       switch (dev->model) {
+       case TM6010_BOARD_HAUPPAUGE_900H:
+       case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+       case TM6010_BOARD_TWINHAN_TU501:
+       case TM6010_BOARD_GENERIC:
+               /* Turn xceive 3028 on */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.tuner_on, 0x01);
+               msleep(15);
+               /* Turn zarlink zl10353 on */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00);
+               msleep(15);
+               /* Reset zarlink zl10353 */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00);
+               msleep(50);
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01);
+               msleep(15);
+               /* Turn zarlink zl10353 off */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x01);
+               msleep(15);
+               /* ir ? */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.ir, 0x01);
+               msleep(15);
+               /* Power led on (blue) */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x00);
+               msleep(15);
+               /* DVB led off (orange) */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.dvb_led, 0x01);
+               msleep(15);
+               /* Turn zarlink zl10353 on */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00);
+               msleep(15);
+               break;
+       case TM6010_BOARD_BEHOLD_WANDER:
+       case TM6010_BOARD_BEHOLD_WANDER_LITE:
+               /* Power led on (blue) */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01);
+               msleep(15);
+               /* Reset zarlink zl10353 */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00);
+               msleep(50);
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01);
+               msleep(15);
+               break;
+       case TM6010_BOARD_BEHOLD_VOYAGER:
+       case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
+               /* Power led on (blue) */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01);
+               msleep(15);
+               break;
+       default:
+               break;
+       }
+
+       /*
+        * Default initialization. Most of the devices seem to use GPIO1
+        * and GPIO4.on the same way, so, this handles the common sequence
+        * used by most devices.
+        * If a device uses a different sequence or different GPIO pins for
+        * reset, just add the code at the board-specific part
+        */
+
+       if (dev->gpio.tuner_reset) {
+               int rc;
+               int i;
+
+               for (i = 0; i < 2; i++) {
+                       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                               dev->gpio.tuner_reset, 0x00);
+                       if (rc < 0) {
+                               printk(KERN_ERR "Error %i doing tuner reset\n", rc);
+                               return rc;
+                       }
+
+                       msleep(10); /* Just to be conservative */
+                       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                               dev->gpio.tuner_reset, 0x01);
+                       if (rc < 0) {
+                               printk(KERN_ERR "Error %i doing tuner reset\n", rc);
+                               return rc;
+                       }
+               }
+       } else {
+               printk(KERN_ERR "Tuner reset is not configured\n");
+               return -1;
+       }
+
+       msleep(50);
+
+       return 0;
+};
+
+static void tm6000_config_tuner(struct tm6000_core *dev)
+{
+       struct tuner_setup tun_setup;
+
+       /* Load tuner module */
+       v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+               "tuner", dev->tuner_addr, NULL);
+
+       memset(&tun_setup, 0, sizeof(tun_setup));
+       tun_setup.type = dev->tuner_type;
+       tun_setup.addr = dev->tuner_addr;
+
+       tun_setup.mode_mask = 0;
+       if (dev->caps.has_tuner)
+               tun_setup.mode_mask |= (T_ANALOG_TV | T_RADIO);
+
+       switch (dev->tuner_type) {
+       case TUNER_XC2028:
+               tun_setup.tuner_callback = tm6000_tuner_callback;
+               break;
+       case TUNER_XC5000:
+               tun_setup.tuner_callback = tm6000_xc5000_callback;
+               break;
+       }
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
+
+       switch (dev->tuner_type) {
+       case TUNER_XC2028: {
+               struct v4l2_priv_tun_config xc2028_cfg;
+               struct xc2028_ctrl ctl;
+
+               memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
+               memset(&ctl, 0, sizeof(ctl));
+
+               ctl.demod = XC3028_FE_ZARLINK456;
+
+               xc2028_cfg.tuner = TUNER_XC2028;
+               xc2028_cfg.priv  = &ctl;
+
+               switch (dev->model) {
+               case TM6010_BOARD_HAUPPAUGE_900H:
+               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+               case TM6010_BOARD_TWINHAN_TU501:
+                       ctl.fname = "xc3028L-v36.fw";
+                       break;
+               default:
+                       if (dev->dev_type == TM6010)
+                               ctl.fname = "xc3028-v27.fw";
+                       else
+                               ctl.fname = "xc3028-v24.fw";
+               }
+
+               printk(KERN_INFO "Setting firmware parameters for xc2028\n");
+               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config,
+                                    &xc2028_cfg);
+
+               }
+               break;
+       case TUNER_XC5000:
+               {
+               struct v4l2_priv_tun_config  xc5000_cfg;
+               struct xc5000_config ctl = {
+                       .i2c_address = dev->tuner_addr,
+                       .if_khz      = 4570,
+                       .radio_input = XC5000_RADIO_FM1_MONO,
+                       };
+
+               xc5000_cfg.tuner = TUNER_XC5000;
+               xc5000_cfg.priv  = &ctl;
+
+               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config,
+                                    &xc5000_cfg);
+               }
+               break;
+       default:
+               printk(KERN_INFO "Unknown tuner type. Tuner is not configured.\n");
+               break;
+       }
+}
+
+static int fill_board_specific_data(struct tm6000_core *dev)
+{
+       int rc;
+
+       dev->dev_type   = tm6000_boards[dev->model].type;
+       dev->tuner_type = tm6000_boards[dev->model].tuner_type;
+       dev->tuner_addr = tm6000_boards[dev->model].tuner_addr;
+
+       dev->gpio = tm6000_boards[dev->model].gpio;
+
+       dev->ir_codes = tm6000_boards[dev->model].ir_codes;
+
+       dev->demod_addr = tm6000_boards[dev->model].demod_addr;
+
+       dev->caps = tm6000_boards[dev->model].caps;
+
+       dev->vinput[0] = tm6000_boards[dev->model].vinput[0];
+       dev->vinput[1] = tm6000_boards[dev->model].vinput[1];
+       dev->vinput[2] = tm6000_boards[dev->model].vinput[2];
+       dev->rinput = tm6000_boards[dev->model].rinput;
+
+       /* setup per-model quirks */
+       switch (dev->model) {
+       case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+               dev->quirks |= TM6000_QUIRK_NO_USB_DELAY;
+               break;
+
+       default:
+               break;
+       }
+
+       /* initialize hardware */
+       rc = tm6000_init(dev);
+       if (rc < 0)
+               return rc;
+
+       return v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev);
+}
+
+
+static void use_alternative_detection_method(struct tm6000_core *dev)
+{
+       int i, model = -1;
+
+       if (!dev->eedata_size)
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(tm6000_boards); i++) {
+               if (!tm6000_boards[i].eename_size)
+                       continue;
+               if (dev->eedata_size < tm6000_boards[i].eename_pos +
+                                      tm6000_boards[i].eename_size)
+                       continue;
+
+               if (!memcmp(&dev->eedata[tm6000_boards[i].eename_pos],
+                           tm6000_boards[i].eename,
+                           tm6000_boards[i].eename_size)) {
+                       model = i;
+                       break;
+               }
+       }
+       if (model < 0) {
+               printk(KERN_INFO "Device has eeprom but is currently unknown\n");
+               return;
+       }
+
+       dev->model = model;
+
+       printk(KERN_INFO "Device identified via eeprom as %s (type = %d)\n",
+              tm6000_boards[model].name, model);
+}
+
+static int tm6000_init_dev(struct tm6000_core *dev)
+{
+       struct v4l2_frequency f;
+       int rc = 0;
+
+       mutex_init(&dev->lock);
+       mutex_lock(&dev->lock);
+
+       if (!is_generic(dev->model)) {
+               rc = fill_board_specific_data(dev);
+               if (rc < 0)
+                       goto err;
+
+               /* register i2c bus */
+               rc = tm6000_i2c_register(dev);
+               if (rc < 0)
+                       goto err;
+       } else {
+               /* register i2c bus */
+               rc = tm6000_i2c_register(dev);
+               if (rc < 0)
+                       goto err;
+
+               use_alternative_detection_method(dev);
+
+               rc = fill_board_specific_data(dev);
+               if (rc < 0)
+                       goto err;
+       }
+
+       /* Default values for STD and resolutions */
+       dev->width = 720;
+       dev->height = 480;
+       dev->norm = V4L2_STD_PAL_M;
+
+       /* Configure tuner */
+       tm6000_config_tuner(dev);
+
+       /* Set video standard */
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
+
+       /* Set tuner frequency - also loads firmware on xc2028/xc3028 */
+       f.tuner = 0;
+       f.type = V4L2_TUNER_ANALOG_TV;
+       f.frequency = 3092;     /* 193.25 MHz */
+       dev->freq = f.frequency;
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
+
+       if (dev->caps.has_tda9874)
+               v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+                       "tvaudio", I2C_ADDR_TDA9874, NULL);
+
+       /* register and initialize V4L2 */
+       rc = tm6000_v4l2_register(dev);
+       if (rc < 0)
+               goto err;
+
+       tm6000_add_into_devlist(dev);
+       tm6000_init_extension(dev);
+
+       tm6000_ir_init(dev);
+
+       mutex_unlock(&dev->lock);
+       return 0;
+
+err:
+       mutex_unlock(&dev->lock);
+       return rc;
+}
+
+/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
+#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
+
+static void get_max_endpoint(struct usb_device *udev,
+                            struct usb_host_interface *alt,
+                            char *msgtype,
+                            struct usb_host_endpoint *curr_e,
+                            struct tm6000_endpoint *tm_ep)
+{
+       u16 tmp = le16_to_cpu(curr_e->desc.wMaxPacketSize);
+       unsigned int size = tmp & 0x7ff;
+
+       if (udev->speed == USB_SPEED_HIGH)
+               size = size * hb_mult(tmp);
+
+       if (size > tm_ep->maxsize) {
+               tm_ep->endp = curr_e;
+               tm_ep->maxsize = size;
+               tm_ep->bInterfaceNumber = alt->desc.bInterfaceNumber;
+               tm_ep->bAlternateSetting = alt->desc.bAlternateSetting;
+
+               printk(KERN_INFO "tm6000: %s endpoint: 0x%02x (max size=%u bytes)\n",
+                                       msgtype, curr_e->desc.bEndpointAddress,
+                                       size);
+       }
+}
+
+/*
+ * tm6000_usb_probe()
+ * checks for supported devices
+ */
+static int tm6000_usb_probe(struct usb_interface *interface,
+                           const struct usb_device_id *id)
+{
+       struct usb_device *usbdev;
+       struct tm6000_core *dev = NULL;
+       int i, rc = 0;
+       int nr = 0;
+       char *speed;
+
+       usbdev = usb_get_dev(interface_to_usbdev(interface));
+
+       /* Selects the proper interface */
+       rc = usb_set_interface(usbdev, 0, 1);
+       if (rc < 0)
+               goto err;
+
+       /* Check to see next free device and mark as used */
+       nr = find_first_zero_bit(&tm6000_devused, TM6000_MAXBOARDS);
+       if (nr >= TM6000_MAXBOARDS) {
+               printk(KERN_ERR "tm6000: Supports only %i tm60xx boards.\n", TM6000_MAXBOARDS);
+               usb_put_dev(usbdev);
+               return -ENOMEM;
+       }
+
+       /* Create and initialize dev struct */
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (dev == NULL) {
+               printk(KERN_ERR "tm6000" ": out of memory!\n");
+               usb_put_dev(usbdev);
+               return -ENOMEM;
+       }
+       spin_lock_init(&dev->slock);
+       mutex_init(&dev->usb_lock);
+
+       /* Increment usage count */
+       set_bit(nr, &tm6000_devused);
+       snprintf(dev->name, 29, "tm6000 #%d", nr);
+
+       dev->model = id->driver_info;
+       if (card[nr] < ARRAY_SIZE(tm6000_boards))
+               dev->model = card[nr];
+
+       dev->udev = usbdev;
+       dev->devno = nr;
+
+       switch (usbdev->speed) {
+       case USB_SPEED_LOW:
+               speed = "1.5";
+               break;
+       case USB_SPEED_UNKNOWN:
+       case USB_SPEED_FULL:
+               speed = "12";
+               break;
+       case USB_SPEED_HIGH:
+               speed = "480";
+               break;
+       default:
+               speed = "unknown";
+       }
+
+       /* Get endpoints */
+       for (i = 0; i < interface->num_altsetting; i++) {
+               int ep;
+
+               for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) {
+                       struct usb_host_endpoint        *e;
+                       int dir_out;
+
+                       e = &interface->altsetting[i].endpoint[ep];
+
+                       dir_out = ((e->desc.bEndpointAddress &
+                                       USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
+
+                       printk(KERN_INFO "tm6000: alt %d, interface %i, class %i\n",
+                              i,
+                              interface->altsetting[i].desc.bInterfaceNumber,
+                              interface->altsetting[i].desc.bInterfaceClass);
+
+                       switch (e->desc.bmAttributes) {
+                       case USB_ENDPOINT_XFER_BULK:
+                               if (!dir_out) {
+                                       get_max_endpoint(usbdev,
+                                                        &interface->altsetting[i],
+                                                        "Bulk IN", e,
+                                                        &dev->bulk_in);
+                               } else {
+                                       get_max_endpoint(usbdev,
+                                                        &interface->altsetting[i],
+                                                        "Bulk OUT", e,
+                                                        &dev->bulk_out);
+                               }
+                               break;
+                       case USB_ENDPOINT_XFER_ISOC:
+                               if (!dir_out) {
+                                       get_max_endpoint(usbdev,
+                                                        &interface->altsetting[i],
+                                                        "ISOC IN", e,
+                                                        &dev->isoc_in);
+                               } else {
+                                       get_max_endpoint(usbdev,
+                                                        &interface->altsetting[i],
+                                                        "ISOC OUT", e,
+                                                        &dev->isoc_out);
+                               }
+                               break;
+                       case USB_ENDPOINT_XFER_INT:
+                               if (!dir_out) {
+                                       get_max_endpoint(usbdev,
+                                                       &interface->altsetting[i],
+                                                       "INT IN", e,
+                                                       &dev->int_in);
+                               } else {
+                                       get_max_endpoint(usbdev,
+                                                       &interface->altsetting[i],
+                                                       "INT OUT", e,
+                                                       &dev->int_out);
+                               }
+                               break;
+                       }
+               }
+       }
+
+
+       printk(KERN_INFO "tm6000: New video device @ %s Mbps (%04x:%04x, ifnum %d)\n",
+               speed,
+               le16_to_cpu(dev->udev->descriptor.idVendor),
+               le16_to_cpu(dev->udev->descriptor.idProduct),
+               interface->altsetting->desc.bInterfaceNumber);
+
+/* check if the the device has the iso in endpoint at the correct place */
+       if (!dev->isoc_in.endp) {
+               printk(KERN_ERR "tm6000: probing error: no IN ISOC endpoint!\n");
+               rc = -ENODEV;
+
+               goto err;
+       }
+
+       /* save our data pointer in this interface device */
+       usb_set_intfdata(interface, dev);
+
+       printk(KERN_INFO "tm6000: Found %s\n", tm6000_boards[dev->model].name);
+
+       rc = tm6000_init_dev(dev);
+       if (rc < 0)
+               goto err;
+
+       return 0;
+
+err:
+       printk(KERN_ERR "tm6000: Error %d while registering\n", rc);
+
+       clear_bit(nr, &tm6000_devused);
+       usb_put_dev(usbdev);
+
+       kfree(dev);
+       return rc;
+}
+
+/*
+ * tm6000_usb_disconnect()
+ * called when the device gets diconencted
+ * video device will be unregistered on v4l2_close in case it is still open
+ */
+static void tm6000_usb_disconnect(struct usb_interface *interface)
+{
+       struct tm6000_core *dev = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
+
+       if (!dev)
+               return;
+
+       printk(KERN_INFO "tm6000: disconnecting %s\n", dev->name);
+
+       tm6000_ir_fini(dev);
+
+       if (dev->gpio.power_led) {
+               switch (dev->model) {
+               case TM6010_BOARD_HAUPPAUGE_900H:
+               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+               case TM6010_BOARD_TWINHAN_TU501:
+                       /* Power led off */
+                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                               dev->gpio.power_led, 0x01);
+                       msleep(15);
+                       break;
+               case TM6010_BOARD_BEHOLD_WANDER:
+               case TM6010_BOARD_BEHOLD_VOYAGER:
+               case TM6010_BOARD_BEHOLD_WANDER_LITE:
+               case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
+                       /* Power led off */
+                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                               dev->gpio.power_led, 0x00);
+                       msleep(15);
+                       break;
+               }
+       }
+       tm6000_v4l2_unregister(dev);
+
+       tm6000_i2c_unregister(dev);
+
+       v4l2_device_unregister(&dev->v4l2_dev);
+
+       dev->state |= DEV_DISCONNECTED;
+
+       usb_put_dev(dev->udev);
+
+       tm6000_close_extension(dev);
+       tm6000_remove_from_devlist(dev);
+
+       clear_bit(dev->devno, &tm6000_devused);
+       kfree(dev);
+}
+
+static struct usb_driver tm6000_usb_driver = {
+               .name = "tm6000",
+               .probe = tm6000_usb_probe,
+               .disconnect = tm6000_usb_disconnect,
+               .id_table = tm6000_id_table,
+};
+
+static int __init tm6000_module_init(void)
+{
+       int result;
+
+       printk(KERN_INFO "tm6000" " v4l2 driver version %d.%d.%d loaded\n",
+              (TM6000_VERSION  >> 16) & 0xff,
+              (TM6000_VERSION  >> 8) & 0xff, TM6000_VERSION  & 0xff);
+
+       /* register this driver with the USB subsystem */
+       result = usb_register(&tm6000_usb_driver);
+       if (result)
+               printk(KERN_ERR "tm6000"
+                          " usb_register failed. Error number %d.\n", result);
+
+       return result;
+}
+
+static void __exit tm6000_module_exit(void)
+{
+       /* deregister at USB subsystem */
+       usb_deregister(&tm6000_usb_driver);
+}
+
+module_init(tm6000_module_init);
+module_exit(tm6000_module_exit);
+
+MODULE_DESCRIPTION("Trident TVMaster TM5600/TM6000/TM6010 USB2 adapter");
+MODULE_AUTHOR("Mauro Carvalho Chehab");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/tm6000/tm6000-core.c b/drivers/media/video/tm6000/tm6000-core.c
new file mode 100644 (file)
index 0000000..9783616
--- /dev/null
@@ -0,0 +1,965 @@
+/*
+ *  tm6000-core.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ *      - DVB-T support
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include "tm6000.h"
+#include "tm6000-regs.h"
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+
+#define USB_TIMEOUT    (5 * HZ) /* ms */
+
+int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req,
+                         u16 value, u16 index, u8 *buf, u16 len)
+{
+       int          ret, i;
+       unsigned int pipe;
+       u8           *data = NULL;
+
+       mutex_lock(&dev->usb_lock);
+
+       if (len)
+               data = kzalloc(len, GFP_KERNEL);
+
+       if (req_type & USB_DIR_IN)
+               pipe = usb_rcvctrlpipe(dev->udev, 0);
+       else {
+               pipe = usb_sndctrlpipe(dev->udev, 0);
+               memcpy(data, buf, len);
+       }
+
+       if (tm6000_debug & V4L2_DEBUG_I2C) {
+               printk(KERN_DEBUG "(dev %p, pipe %08x): ", dev->udev, pipe);
+
+               printk(KERN_CONT "%s: %02x %02x %02x %02x %02x %02x %02x %02x ",
+                       (req_type & USB_DIR_IN) ? " IN" : "OUT",
+                       req_type, req, value&0xff, value>>8, index&0xff,
+                       index>>8, len&0xff, len>>8);
+
+               if (!(req_type & USB_DIR_IN)) {
+                       printk(KERN_CONT ">>> ");
+                       for (i = 0; i < len; i++)
+                               printk(KERN_CONT " %02x", buf[i]);
+                       printk(KERN_CONT "\n");
+               }
+       }
+
+       ret = usb_control_msg(dev->udev, pipe, req, req_type, value, index,
+                             data, len, USB_TIMEOUT);
+
+       if (req_type &  USB_DIR_IN)
+               memcpy(buf, data, len);
+
+       if (tm6000_debug & V4L2_DEBUG_I2C) {
+               if (ret < 0) {
+                       if (req_type &  USB_DIR_IN)
+                               printk(KERN_DEBUG "<<< (len=%d)\n", len);
+
+                       printk(KERN_CONT "%s: Error #%d\n", __func__, ret);
+               } else if (req_type &  USB_DIR_IN) {
+                       printk(KERN_CONT "<<< ");
+                       for (i = 0; i < len; i++)
+                               printk(KERN_CONT " %02x", buf[i]);
+                       printk(KERN_CONT "\n");
+               }
+       }
+
+       kfree(data);
+       msleep(5);
+
+       mutex_unlock(&dev->usb_lock);
+       return ret;
+}
+
+int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index)
+{
+       return
+               tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
+                                     req, value, index, NULL, 0);
+}
+EXPORT_SYMBOL_GPL(tm6000_set_reg);
+
+int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index)
+{
+       int rc;
+       u8 buf[1];
+
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
+                                       value, index, buf, 1);
+
+       if (rc < 0)
+               return rc;
+
+       return *buf;
+}
+EXPORT_SYMBOL_GPL(tm6000_get_reg);
+
+int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
+                                               u16 index, u16 mask)
+{
+       int rc;
+       u8 buf[1];
+       u8 new_index;
+
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
+                                       value, index, buf, 1);
+
+       if (rc < 0)
+               return rc;
+
+       new_index = (buf[0] & ~mask) | (index & mask);
+
+       if (new_index == index)
+               return 0;
+
+       return tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
+                                     req, value, new_index, NULL, 0);
+}
+EXPORT_SYMBOL_GPL(tm6000_set_reg_mask);
+
+int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index)
+{
+       int rc;
+       u8 buf[2];
+
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
+                                       value, index, buf, 2);
+
+       if (rc < 0)
+               return rc;
+
+       return buf[1]|buf[0]<<8;
+}
+
+int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index)
+{
+       int rc;
+       u8 buf[4];
+
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
+                                       value, index, buf, 4);
+
+       if (rc < 0)
+               return rc;
+
+       return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24;
+}
+
+int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep)
+{
+       int rc;
+
+       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
+       if (rc < 0)
+               return rc;
+
+       msleep(tsleep);
+
+       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
+       msleep(tsleep);
+
+       return rc;
+}
+
+void tm6000_set_fourcc_format(struct tm6000_core *dev)
+{
+       if (dev->dev_type == TM6010) {
+               int val;
+
+               val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, 0) & 0xfc;
+               if (dev->fourcc == V4L2_PIX_FMT_UYVY)
+                       tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val);
+               else
+                       tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val | 1);
+       } else {
+               if (dev->fourcc == V4L2_PIX_FMT_UYVY)
+                       tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0);
+               else
+                       tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0x90);
+       }
+}
+
+static void tm6000_set_vbi(struct tm6000_core *dev)
+{
+       /*
+        * FIXME:
+        * VBI lines and start/end are different between 60Hz and 50Hz
+        * So, it is very likely that we need to change the config to
+        * something that takes it into account, doing something different
+        * if (dev->norm & V4L2_STD_525_60)
+        */
+
+       if (dev->dev_type == TM6010) {
+               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
+               tm6000_set_reg(dev, TM6010_REQ07_R41_TELETEXT_VBI_CODE1, 0x27);
+               tm6000_set_reg(dev, TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55);
+               tm6000_set_reg(dev, TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7, 0x66);
+               tm6000_set_reg(dev, TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8, 0x66);
+               tm6000_set_reg(dev, TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23, 0x00);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES, 0x00);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN, 0x00);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02);
+               tm6000_set_reg(dev, TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35);
+               tm6000_set_reg(dev, TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0);
+               tm6000_set_reg(dev, TM6010_REQ07_R5A_VBI_TELETEXT_DTO1, 0x11);
+               tm6000_set_reg(dev, TM6010_REQ07_R5B_VBI_TELETEXT_DTO0, 0x4c);
+               tm6000_set_reg(dev, TM6010_REQ07_R40_TELETEXT_VBI_CODE0, 0x01);
+               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00);
+       }
+}
+
+int tm6000_init_analog_mode(struct tm6000_core *dev)
+{
+       struct v4l2_frequency f;
+
+       if (dev->dev_type == TM6010) {
+               u8 active = TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE;
+
+               if (!dev->radio)
+                       active |= TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE;
+
+               /* Enable video and audio */
+               tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
+                                                       active, 0x60);
+               /* Disable TS input */
+               tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
+                                                       0x00, 0x40);
+       } else {
+               /* Enables soft reset */
+               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
+
+               if (dev->scaler)
+                       /* Disable Hfilter and Enable TS Drop err */
+                       tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x20);
+               else    /* Enable Hfilter and disable TS Drop err */
+                       tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x80);
+
+               tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x88);
+               tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x23);
+               tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xc0);
+               tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xd8);
+               tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x06);
+               tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f);
+
+               /* AP Software reset */
+               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08);
+               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00);
+
+               tm6000_set_fourcc_format(dev);
+
+               /* Disables soft reset */
+               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00);
+       }
+       msleep(20);
+
+       /* Tuner firmware can now be loaded */
+
+       /*
+        * FIXME: This is a hack! xc3028 "sleeps" when no channel is detected
+        * for more than a few seconds. Not sure why, as this behavior does
+        * not happen on other devices with xc3028. So, I suspect that it
+        * is yet another bug at tm6000. After start sleeping, decoding
+        * doesn't start automatically. Instead, it requires some
+        * I2C commands to wake it up. As we want to have image at the
+        * beginning, we needed to add this hack. The better would be to
+        * discover some way to make tm6000 to wake up without this hack.
+        */
+       f.frequency = dev->freq;
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
+
+       msleep(100);
+       tm6000_set_standard(dev);
+       tm6000_set_vbi(dev);
+       tm6000_set_audio_bitrate(dev, 48000);
+
+       /* switch dvb led off */
+       if (dev->gpio.dvb_led) {
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                       dev->gpio.dvb_led, 0x01);
+       }
+
+       return 0;
+}
+
+int tm6000_init_digital_mode(struct tm6000_core *dev)
+{
+       if (dev->dev_type == TM6010) {
+               /* Disable video and audio */
+               tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
+                               0x00, 0x60);
+               /* Enable TS input */
+               tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
+                               0x40, 0x40);
+               /* all power down, but not the digital data port */
+               tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0x28);
+               tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xfc);
+               tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0xff);
+       } else  {
+               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08);
+               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00);
+               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
+               tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x08);
+               tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c);
+               tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff);
+               tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0xd8);
+               tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x40);
+               tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0);
+               tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x09);
+               tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x37);
+               tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xd8);
+               tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xc0);
+               tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x60);
+
+               tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c);
+               tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff);
+               tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0x08);
+               msleep(50);
+
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
+               msleep(50);
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x01);
+               msleep(50);
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
+               msleep(100);
+       }
+
+       /* switch dvb led on */
+       if (dev->gpio.dvb_led) {
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                       dev->gpio.dvb_led, 0x00);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(tm6000_init_digital_mode);
+
+struct reg_init {
+       u8 req;
+       u8 reg;
+       u8 val;
+};
+
+/* The meaning of those initializations are unknown */
+static struct reg_init tm6000_init_tab[] = {
+       /* REG  VALUE */
+       { TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f },
+       { TM6010_REQ07_RFF_SOFT_RESET, 0x08 },
+       { TM6010_REQ07_RFF_SOFT_RESET, 0x00 },
+       { TM6010_REQ07_RD5_POWERSAVE, 0x4f },
+       { TM6000_REQ07_RDA_CLK_SEL, 0x23 },
+       { TM6000_REQ07_RDB_OUT_SEL, 0x08 },
+       { TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x00 },
+       { TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10 },
+       { TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00 },
+       { TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00 },
+       { TM6000_REQ07_REB_VADC_AADC_MODE, 0x64 },      /* 48000 bits/sample, external input */
+       { TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL, 0xc2 },
+
+       { TM6010_REQ07_R3F_RESET, 0x01 },               /* Start of soft reset */
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
+       { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 },
+       { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 },
+       { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 },
+       { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 },
+       { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a },
+       { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 },
+       { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 },
+       { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b },
+       { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 },
+       { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f },
+       { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c },
+       { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c },
+       { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+       { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
+       { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a },
+       { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 },
+       { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 },
+       { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a },
+       { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 },
+       { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 },
+       { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 },
+       { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 },
+       { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 },
+       { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 },
+       { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+       { TM6010_REQ07_RC1_TRESHOLD, 0xd0 },
+       { TM6010_REQ07_RC3_HSTART1, 0x88 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },               /* End of the soft reset */
+       { TM6010_REQ05_R18_IMASK7, 0x00 },
+};
+
+static struct reg_init tm6010_init_tab[] = {
+       { TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x00 },
+       { TM6010_REQ07_RC4_HSTART0, 0xa0 },
+       { TM6010_REQ07_RC6_HEND0, 0x40 },
+       { TM6010_REQ07_RCA_VEND0, 0x31 },
+       { TM6010_REQ07_RCC_ACTIVE_IF, 0xe1 },
+       { TM6010_REQ07_RE0_DVIDEO_SOURCE, 0x03 },
+       { TM6010_REQ07_RFE_POWER_DOWN, 0x7f },
+
+       { TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0 },
+       { TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4 },
+       { TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8 },
+       { TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x00 },
+       { TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2 },
+       { TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0 },
+       { TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2 },
+       { TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60 },
+       { TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc },
+
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
+       { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 },
+       { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 },
+       { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 },
+       { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 },
+       { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a },
+       { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 },
+       { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 },
+       { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b },
+       { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 },
+       { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f },
+       { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c },
+       { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c },
+       { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+       { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
+       { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a },
+       { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 },
+       { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 },
+       { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a },
+       { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 },
+       { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 },
+       { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 },
+       { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 },
+       { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 },
+       { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 },
+       { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+       { TM6010_REQ07_RC1_TRESHOLD, 0xd0 },
+       { TM6010_REQ07_RC3_HSTART1, 0x88 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+
+       { TM6010_REQ05_R18_IMASK7, 0x00 },
+
+       { TM6010_REQ07_RD8_IR_LEADER1, 0xaa },
+       { TM6010_REQ07_RD8_IR_LEADER0, 0x30 },
+       { TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20 },
+       { TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0 },
+       { REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 },
+       { TM6010_REQ07_RD8_IR, 0x2f },
+
+       /* set remote wakeup key:any key wakeup */
+       { TM6010_REQ07_RE5_REMOTE_WAKEUP,  0xfe },
+       { TM6010_REQ07_RD8_IR_WAKEUP_SEL,  0xff },
+};
+
+int tm6000_init(struct tm6000_core *dev)
+{
+       int board, rc = 0, i, size;
+       struct reg_init *tab;
+
+       /* Check board revision */
+       board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0);
+       if (board >= 0) {
+               switch (board & 0xff) {
+               case 0xf3:
+                       printk(KERN_INFO "Found tm6000\n");
+                       if (dev->dev_type != TM6000)
+                               dev->dev_type = TM6000;
+                       break;
+               case 0xf4:
+                       printk(KERN_INFO "Found tm6010\n");
+                       if (dev->dev_type != TM6010)
+                               dev->dev_type = TM6010;
+                       break;
+               default:
+                       printk(KERN_INFO "Unknown board version = 0x%08x\n", board);
+               }
+       } else
+               printk(KERN_ERR "Error %i while retrieving board version\n", board);
+
+       if (dev->dev_type == TM6010) {
+               tab = tm6010_init_tab;
+               size = ARRAY_SIZE(tm6010_init_tab);
+       } else {
+               tab = tm6000_init_tab;
+               size = ARRAY_SIZE(tm6000_init_tab);
+       }
+
+       /* Load board's initialization table */
+       for (i = 0; i < size; i++) {
+               rc = tm6000_set_reg(dev, tab[i].req, tab[i].reg, tab[i].val);
+               if (rc < 0) {
+                       printk(KERN_ERR "Error %i while setting req %d, "
+                                       "reg %d to value %d\n", rc,
+                                       tab[i].req, tab[i].reg, tab[i].val);
+                       return rc;
+               }
+       }
+
+       msleep(5); /* Just to be conservative */
+
+       rc = tm6000_cards_setup(dev);
+
+       return rc;
+}
+
+int tm6000_reset(struct tm6000_core *dev)
+{
+       int pipe;
+       int err;
+
+       msleep(500);
+
+       err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 0);
+       if (err < 0) {
+               tm6000_err("failed to select interface %d, alt. setting 0\n",
+                               dev->isoc_in.bInterfaceNumber);
+               return err;
+       }
+
+       err = usb_reset_configuration(dev->udev);
+       if (err < 0) {
+               tm6000_err("failed to reset configuration\n");
+               return err;
+       }
+
+       if ((dev->quirks & TM6000_QUIRK_NO_USB_DELAY) == 0)
+               msleep(5);
+
+       /*
+        * Not all devices have int_in defined
+        */
+       if (!dev->int_in.endp)
+               return 0;
+
+       err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 2);
+       if (err < 0) {
+               tm6000_err("failed to select interface %d, alt. setting 2\n",
+                               dev->isoc_in.bInterfaceNumber);
+               return err;
+       }
+
+       msleep(5);
+
+       pipe = usb_rcvintpipe(dev->udev,
+                       dev->int_in.endp->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+
+       err = usb_clear_halt(dev->udev, pipe);
+       if (err < 0) {
+               tm6000_err("usb_clear_halt failed: %d\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate)
+{
+       int val = 0;
+       u8 areg_f0 = 0x60; /* ADC MCLK = 250 Fs */
+       u8 areg_0a = 0x91; /* SIF 48KHz */
+
+       switch (bitrate) {
+       case 48000:
+               areg_f0 = 0x60; /* ADC MCLK = 250 Fs */
+               areg_0a = 0x91; /* SIF 48KHz */
+               dev->audio_bitrate = bitrate;
+               break;
+       case 32000:
+               areg_f0 = 0x00; /* ADC MCLK = 375 Fs */
+               areg_0a = 0x90; /* SIF 32KHz */
+               dev->audio_bitrate = bitrate;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+
+       /* enable I2S, if we use sif or external I2S device */
+       if (dev->dev_type == TM6010) {
+               val = tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, areg_0a);
+               if (val < 0)
+                       return val;
+
+               val = tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+                                                       areg_f0, 0xf0);
+               if (val < 0)
+                       return val;
+       } else {
+               val = tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
+                                                       areg_f0, 0xf0);
+               if (val < 0)
+                       return val;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate);
+
+int tm6000_set_audio_rinput(struct tm6000_core *dev)
+{
+       if (dev->dev_type == TM6010) {
+               /* Audio crossbar setting, default SIF1 */
+               u8 areg_f0;
+
+               switch (dev->rinput.amux) {
+               case TM6000_AMUX_SIF1:
+               case TM6000_AMUX_SIF2:
+                       areg_f0 = 0x03;
+                       break;
+               case TM6000_AMUX_ADC1:
+                       areg_f0 = 0x00;
+                       break;
+               case TM6000_AMUX_ADC2:
+                       areg_f0 = 0x08;
+                       break;
+               case TM6000_AMUX_I2S:
+                       areg_f0 = 0x04;
+                       break;
+               default:
+                       printk(KERN_INFO "%s: audio input dosn't support\n",
+                               dev->name);
+                       return 0;
+                       break;
+               }
+               /* Set audio input crossbar */
+               tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+                                                       areg_f0, 0x0f);
+       } else {
+               u8 areg_eb;
+               /* Audio setting, default LINE1 */
+               switch (dev->rinput.amux) {
+               case TM6000_AMUX_ADC1:
+                       areg_eb = 0x00;
+                       break;
+               case TM6000_AMUX_ADC2:
+                       areg_eb = 0x04;
+                       break;
+               default:
+                       printk(KERN_INFO "%s: audio input dosn't support\n",
+                               dev->name);
+                       return 0;
+                       break;
+               }
+               /* Set audio input */
+               tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
+                                                       areg_eb, 0x0f);
+       }
+       return 0;
+}
+
+static void tm6010_set_mute_sif(struct tm6000_core *dev, u8 mute)
+{
+       u8 mute_reg = 0;
+
+       if (mute)
+               mute_reg = 0x08;
+
+       tm6000_set_reg_mask(dev, TM6010_REQ08_R0A_A_I2S_MOD, mute_reg, 0x08);
+}
+
+static void tm6010_set_mute_adc(struct tm6000_core *dev, u8 mute)
+{
+       u8 mute_reg = 0;
+
+       if (mute)
+               mute_reg = 0x20;
+
+       if (dev->dev_type == TM6010) {
+               tm6000_set_reg_mask(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL,
+                                                       mute_reg, 0x20);
+               tm6000_set_reg_mask(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL,
+                                                       mute_reg, 0x20);
+       } else {
+               tm6000_set_reg_mask(dev, TM6000_REQ07_REC_VADC_AADC_LVOL,
+                                                       mute_reg, 0x20);
+               tm6000_set_reg_mask(dev, TM6000_REQ07_RED_VADC_AADC_RVOL,
+                                                       mute_reg, 0x20);
+       }
+}
+
+int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute)
+{
+       enum tm6000_mux mux;
+
+       if (dev->radio)
+               mux = dev->rinput.amux;
+       else
+               mux = dev->vinput[dev->input].amux;
+
+       switch (mux) {
+       case TM6000_AMUX_SIF1:
+       case TM6000_AMUX_SIF2:
+               if (dev->dev_type == TM6010)
+                       tm6010_set_mute_sif(dev, mute);
+               else {
+                       printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has"
+                                       " SIF audio inputs. Please check the %s"
+                                       " configuration.\n", dev->name);
+                       return -EINVAL;
+               }
+               break;
+       case TM6000_AMUX_ADC1:
+       case TM6000_AMUX_ADC2:
+               tm6010_set_mute_adc(dev, mute);
+               break;
+       default:
+               return -EINVAL;
+               break;
+       }
+       return 0;
+}
+
+static void tm6010_set_volume_sif(struct tm6000_core *dev, int vol)
+{
+       u8 vol_reg;
+
+       vol_reg = vol & 0x0F;
+
+       if (vol < 0)
+               vol_reg |= 0x40;
+
+       tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, vol_reg);
+       tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, vol_reg);
+}
+
+static void tm6010_set_volume_adc(struct tm6000_core *dev, int vol)
+{
+       u8 vol_reg;
+
+       vol_reg = (vol + 0x10) & 0x1f;
+
+       if (dev->dev_type == TM6010) {
+               tm6000_set_reg(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL, vol_reg);
+               tm6000_set_reg(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL, vol_reg);
+       } else {
+               tm6000_set_reg(dev, TM6000_REQ07_REC_VADC_AADC_LVOL, vol_reg);
+               tm6000_set_reg(dev, TM6000_REQ07_RED_VADC_AADC_RVOL, vol_reg);
+       }
+}
+
+void tm6000_set_volume(struct tm6000_core *dev, int vol)
+{
+       enum tm6000_mux mux;
+
+       if (dev->radio) {
+               mux = dev->rinput.amux;
+               vol += 8; /* Offset to 0 dB */
+       } else
+               mux = dev->vinput[dev->input].amux;
+
+       switch (mux) {
+       case TM6000_AMUX_SIF1:
+       case TM6000_AMUX_SIF2:
+               if (dev->dev_type == TM6010)
+                       tm6010_set_volume_sif(dev, vol);
+               else
+                       printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has"
+                                       " SIF audio inputs. Please check the %s"
+                                       " configuration.\n", dev->name);
+               break;
+       case TM6000_AMUX_ADC1:
+       case TM6000_AMUX_ADC2:
+               tm6010_set_volume_adc(dev, vol);
+               break;
+       default:
+               break;
+       }
+}
+
+static LIST_HEAD(tm6000_devlist);
+static DEFINE_MUTEX(tm6000_devlist_mutex);
+
+/*
+ * tm6000_realease_resource()
+ */
+
+void tm6000_remove_from_devlist(struct tm6000_core *dev)
+{
+       mutex_lock(&tm6000_devlist_mutex);
+       list_del(&dev->devlist);
+       mutex_unlock(&tm6000_devlist_mutex);
+};
+
+void tm6000_add_into_devlist(struct tm6000_core *dev)
+{
+       mutex_lock(&tm6000_devlist_mutex);
+       list_add_tail(&dev->devlist, &tm6000_devlist);
+       mutex_unlock(&tm6000_devlist_mutex);
+};
+
+/*
+ * Extension interface
+ */
+
+static LIST_HEAD(tm6000_extension_devlist);
+
+int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type,
+                       char *buf, int size)
+{
+       struct tm6000_ops *ops = NULL;
+
+       /* FIXME: tm6000_extension_devlist_lock should be a spinlock */
+
+       if (!list_empty(&tm6000_extension_devlist)) {
+               list_for_each_entry(ops, &tm6000_extension_devlist, next) {
+                       if (ops->fillbuf && ops->type == type)
+                               ops->fillbuf(dev, buf, size);
+               }
+       }
+
+       return 0;
+}
+
+int tm6000_register_extension(struct tm6000_ops *ops)
+{
+       struct tm6000_core *dev = NULL;
+
+       mutex_lock(&tm6000_devlist_mutex);
+       list_add_tail(&ops->next, &tm6000_extension_devlist);
+       list_for_each_entry(dev, &tm6000_devlist, devlist) {
+               ops->init(dev);
+               printk(KERN_INFO "%s: Initialized (%s) extension\n",
+                      dev->name, ops->name);
+       }
+       mutex_unlock(&tm6000_devlist_mutex);
+       return 0;
+}
+EXPORT_SYMBOL(tm6000_register_extension);
+
+void tm6000_unregister_extension(struct tm6000_ops *ops)
+{
+       struct tm6000_core *dev = NULL;
+
+       mutex_lock(&tm6000_devlist_mutex);
+       list_for_each_entry(dev, &tm6000_devlist, devlist)
+               ops->fini(dev);
+
+       printk(KERN_INFO "tm6000: Remove (%s) extension\n", ops->name);
+       list_del(&ops->next);
+       mutex_unlock(&tm6000_devlist_mutex);
+}
+EXPORT_SYMBOL(tm6000_unregister_extension);
+
+void tm6000_init_extension(struct tm6000_core *dev)
+{
+       struct tm6000_ops *ops = NULL;
+
+       mutex_lock(&tm6000_devlist_mutex);
+       if (!list_empty(&tm6000_extension_devlist)) {
+               list_for_each_entry(ops, &tm6000_extension_devlist, next) {
+                       if (ops->init)
+                               ops->init(dev);
+               }
+       }
+       mutex_unlock(&tm6000_devlist_mutex);
+}
+
+void tm6000_close_extension(struct tm6000_core *dev)
+{
+       struct tm6000_ops *ops = NULL;
+
+       mutex_lock(&tm6000_devlist_mutex);
+       if (!list_empty(&tm6000_extension_devlist)) {
+               list_for_each_entry(ops, &tm6000_extension_devlist, next) {
+                       if (ops->fini)
+                               ops->fini(dev);
+               }
+       }
+       mutex_unlock(&tm6000_devlist_mutex);
+}
diff --git a/drivers/media/video/tm6000/tm6000-dvb.c b/drivers/media/video/tm6000/tm6000-dvb.c
new file mode 100644 (file)
index 0000000..5e6c129
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ *  tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include "tm6000.h"
+#include "tm6000-regs.h"
+
+#include "zl10353.h"
+
+#include <media/tuner.h>
+
+#include "tuner-xc2028.h"
+#include "xc5000.h"
+
+MODULE_DESCRIPTION("DVB driver extension module for tm5600/6000/6010 based TV cards");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_LICENSE("GPL");
+
+MODULE_SUPPORTED_DEVICE("{{Trident, tm5600},"
+                       "{{Trident, tm6000},"
+                       "{{Trident, tm6010}");
+
+static int debug;
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug message");
+
+static inline void print_err_status(struct tm6000_core *dev,
+                                   int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+       if (packet < 0) {
+               dprintk(dev, 1, "URB status %d [%s].\n",
+                       status, errmsg);
+       } else {
+               dprintk(dev, 1, "URB packet %d, status %d [%s].\n",
+                       packet, status, errmsg);
+       }
+}
+
+static void tm6000_urb_received(struct urb *urb)
+{
+       int ret;
+       struct tm6000_core *dev = urb->context;
+
+       if (urb->status != 0)
+               print_err_status(dev, 0, urb->status);
+       else if (urb->actual_length > 0)
+               dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
+                                                  urb->actual_length);
+
+       if (dev->dvb->streams > 0) {
+               ret = usb_submit_urb(urb, GFP_ATOMIC);
+               if (ret < 0) {
+                       printk(KERN_ERR "tm6000:  error %s\n", __func__);
+                       kfree(urb->transfer_buffer);
+                       usb_free_urb(urb);
+               }
+       }
+}
+
+static int tm6000_start_stream(struct tm6000_core *dev)
+{
+       int ret;
+       unsigned int pipe, size;
+       struct tm6000_dvb *dvb = dev->dvb;
+
+       printk(KERN_INFO "tm6000: got start stream request %s\n", __func__);
+
+       if (dev->mode != TM6000_MODE_DIGITAL) {
+               tm6000_init_digital_mode(dev);
+               dev->mode = TM6000_MODE_DIGITAL;
+       }
+
+       dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (dvb->bulk_urb == NULL) {
+               printk(KERN_ERR "tm6000: couldn't allocate urb\n");
+               return -ENOMEM;
+       }
+
+       pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress
+                                                         & USB_ENDPOINT_NUMBER_MASK);
+
+       size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
+       size = size * 15; /* 512 x 8 or 12 or 15 */
+
+       dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
+       if (dvb->bulk_urb->transfer_buffer == NULL) {
+               usb_free_urb(dvb->bulk_urb);
+               printk(KERN_ERR "tm6000: couldn't allocate transfer buffer!\n");
+               return -ENOMEM;
+       }
+
+       usb_fill_bulk_urb(dvb->bulk_urb, dev->udev, pipe,
+                                                dvb->bulk_urb->transfer_buffer,
+                                                size,
+                                                tm6000_urb_received, dev);
+
+       ret = usb_clear_halt(dev->udev, pipe);
+       if (ret < 0) {
+               printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",
+                                                       ret, __func__);
+               return ret;
+       } else
+               printk(KERN_ERR "tm6000: pipe resetted\n");
+
+/*     mutex_lock(&tm6000_driver.open_close_mutex); */
+       ret = usb_submit_urb(dvb->bulk_urb, GFP_KERNEL);
+
+/*     mutex_unlock(&tm6000_driver.open_close_mutex); */
+       if (ret) {
+               printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n",
+                                                                       ret);
+
+               kfree(dvb->bulk_urb->transfer_buffer);
+               usb_free_urb(dvb->bulk_urb);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void tm6000_stop_stream(struct tm6000_core *dev)
+{
+       struct tm6000_dvb *dvb = dev->dvb;
+
+       if (dvb->bulk_urb) {
+               printk(KERN_INFO "urb killing\n");
+               usb_kill_urb(dvb->bulk_urb);
+               printk(KERN_INFO "urb buffer free\n");
+               kfree(dvb->bulk_urb->transfer_buffer);
+               usb_free_urb(dvb->bulk_urb);
+               dvb->bulk_urb = NULL;
+       }
+}
+
+static int tm6000_start_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct tm6000_core *dev = demux->priv;
+       struct tm6000_dvb *dvb = dev->dvb;
+       printk(KERN_INFO "tm6000: got start feed request %s\n", __func__);
+
+       mutex_lock(&dvb->mutex);
+       if (dvb->streams == 0) {
+               dvb->streams = 1;
+/*             mutex_init(&tm6000_dev->streming_mutex); */
+               tm6000_start_stream(dev);
+       } else
+               ++(dvb->streams);
+       mutex_unlock(&dvb->mutex);
+
+       return 0;
+}
+
+static int tm6000_stop_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct tm6000_core *dev = demux->priv;
+       struct tm6000_dvb *dvb = dev->dvb;
+
+       printk(KERN_INFO "tm6000: got stop feed request %s\n", __func__);
+
+       mutex_lock(&dvb->mutex);
+
+       printk(KERN_INFO "stream %#x\n", dvb->streams);
+       --(dvb->streams);
+       if (dvb->streams == 0) {
+               printk(KERN_INFO "stop stream\n");
+               tm6000_stop_stream(dev);
+/*             mutex_destroy(&tm6000_dev->streaming_mutex); */
+       }
+       mutex_unlock(&dvb->mutex);
+/*     mutex_destroy(&tm6000_dev->streaming_mutex); */
+
+       return 0;
+}
+
+static int tm6000_dvb_attach_frontend(struct tm6000_core *dev)
+{
+       struct tm6000_dvb *dvb = dev->dvb;
+
+       if (dev->caps.has_zl10353) {
+               struct zl10353_config config = {
+                                    .demod_address = dev->demod_addr,
+                                    .no_tuner = 1,
+                                    .parallel_ts = 1,
+                                    .if2 = 45700,
+                                    .disable_i2c_gate_ctrl = 1,
+                                   };
+
+               dvb->frontend = dvb_attach(zl10353_attach, &config,
+                                                          &dev->i2c_adap);
+       } else {
+               printk(KERN_ERR "tm6000: no frontend defined for the device!\n");
+               return -1;
+       }
+
+       return (!dvb->frontend) ? -1 : 0;
+}
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static int register_dvb(struct tm6000_core *dev)
+{
+       int ret = -1;
+       struct tm6000_dvb *dvb = dev->dvb;
+
+       mutex_init(&dvb->mutex);
+
+       dvb->streams = 0;
+
+       /* attach the frontend */
+       ret = tm6000_dvb_attach_frontend(dev);
+       if (ret < 0) {
+               printk(KERN_ERR "tm6000: couldn't attach the frontend!\n");
+               goto err;
+       }
+
+       ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T",
+                                       THIS_MODULE, &dev->udev->dev, adapter_nr);
+       dvb->adapter.priv = dev;
+
+       if (dvb->frontend) {
+               switch (dev->tuner_type) {
+               case TUNER_XC2028: {
+                       struct xc2028_config cfg = {
+                               .i2c_adap = &dev->i2c_adap,
+                               .i2c_addr = dev->tuner_addr,
+                       };
+
+                       dvb->frontend->callback = tm6000_tuner_callback;
+                       ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+                       if (ret < 0) {
+                               printk(KERN_ERR
+                                       "tm6000: couldn't register frontend\n");
+                               goto adapter_err;
+                       }
+
+                       if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
+                               printk(KERN_ERR "tm6000: couldn't register "
+                                               "frontend (xc3028)\n");
+                               ret = -EINVAL;
+                               goto frontend_err;
+                       }
+                       printk(KERN_INFO "tm6000: XC2028/3028 asked to be "
+                                        "attached to frontend!\n");
+                       break;
+                       }
+               case TUNER_XC5000: {
+                       struct xc5000_config cfg = {
+                               .i2c_address = dev->tuner_addr,
+                       };
+
+                       dvb->frontend->callback = tm6000_xc5000_callback;
+                       ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+                       if (ret < 0) {
+                               printk(KERN_ERR
+                                       "tm6000: couldn't register frontend\n");
+                               goto adapter_err;
+                       }
+
+                       if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) {
+                               printk(KERN_ERR "tm6000: couldn't register "
+                                               "frontend (xc5000)\n");
+                               ret = -EINVAL;
+                               goto frontend_err;
+                       }
+                       printk(KERN_INFO "tm6000: XC5000 asked to be "
+                                        "attached to frontend!\n");
+                       break;
+                       }
+               }
+       } else
+               printk(KERN_ERR "tm6000: no frontend found\n");
+
+       dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING
+                                                           | DMX_MEMORY_BASED_FILTERING;
+       dvb->demux.priv = dev;
+       dvb->demux.filternum = 8;
+       dvb->demux.feednum = 8;
+       dvb->demux.start_feed = tm6000_start_feed;
+       dvb->demux.stop_feed = tm6000_stop_feed;
+       dvb->demux.write_to_decoder = NULL;
+       ret = dvb_dmx_init(&dvb->demux);
+       if (ret < 0) {
+               printk(KERN_ERR "tm6000: dvb_dmx_init failed (errno = %d)\n", ret);
+               goto frontend_err;
+       }
+
+       dvb->dmxdev.filternum = dev->dvb->demux.filternum;
+       dvb->dmxdev.demux = &dev->dvb->demux.dmx;
+       dvb->dmxdev.capabilities = 0;
+
+       ret =  dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
+       if (ret < 0) {
+               printk(KERN_ERR "tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret);
+               goto dvb_dmx_err;
+       }
+
+       return 0;
+
+dvb_dmx_err:
+       dvb_dmx_release(&dvb->demux);
+frontend_err:
+       if (dvb->frontend) {
+               dvb_frontend_detach(dvb->frontend);
+               dvb_unregister_frontend(dvb->frontend);
+       }
+adapter_err:
+       dvb_unregister_adapter(&dvb->adapter);
+err:
+       return ret;
+}
+
+static void unregister_dvb(struct tm6000_core *dev)
+{
+       struct tm6000_dvb *dvb = dev->dvb;
+
+       if (dvb->bulk_urb != NULL) {
+               struct urb *bulk_urb = dvb->bulk_urb;
+
+               kfree(bulk_urb->transfer_buffer);
+               bulk_urb->transfer_buffer = NULL;
+               usb_unlink_urb(bulk_urb);
+               usb_free_urb(bulk_urb);
+       }
+
+/*     mutex_lock(&tm6000_driver.open_close_mutex); */
+       if (dvb->frontend) {
+               dvb_frontend_detach(dvb->frontend);
+               dvb_unregister_frontend(dvb->frontend);
+       }
+
+       dvb_dmxdev_release(&dvb->dmxdev);
+       dvb_dmx_release(&dvb->demux);
+       dvb_unregister_adapter(&dvb->adapter);
+       mutex_destroy(&dvb->mutex);
+/*     mutex_unlock(&tm6000_driver.open_close_mutex); */
+}
+
+static int dvb_init(struct tm6000_core *dev)
+{
+       struct tm6000_dvb *dvb;
+       int rc;
+
+       if (!dev)
+               return 0;
+
+       if (!dev->caps.has_dvb)
+               return 0;
+
+       dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL);
+       if (!dvb) {
+               printk(KERN_INFO "Cannot allocate memory\n");
+               return -ENOMEM;
+       }
+
+       dev->dvb = dvb;
+
+       rc = register_dvb(dev);
+       if (rc < 0) {
+               kfree(dvb);
+               dev->dvb = NULL;
+               return 0;
+       }
+
+       return 0;
+}
+
+static int dvb_fini(struct tm6000_core *dev)
+{
+       if (!dev)
+               return 0;
+
+       if (!dev->caps.has_dvb)
+               return 0;
+
+       if (dev->dvb) {
+               unregister_dvb(dev);
+               kfree(dev->dvb);
+               dev->dvb = NULL;
+       }
+
+       return 0;
+}
+
+static struct tm6000_ops dvb_ops = {
+       .type   = TM6000_DVB,
+       .name   = "TM6000 dvb Extension",
+       .init   = dvb_init,
+       .fini   = dvb_fini,
+};
+
+static int __init tm6000_dvb_register(void)
+{
+       return tm6000_register_extension(&dvb_ops);
+}
+
+static void __exit tm6000_dvb_unregister(void)
+{
+       tm6000_unregister_extension(&dvb_ops);
+}
+
+module_init(tm6000_dvb_register);
+module_exit(tm6000_dvb_unregister);
diff --git a/drivers/media/video/tm6000/tm6000-i2c.c b/drivers/media/video/tm6000/tm6000-i2c.c
new file mode 100644 (file)
index 0000000..0290bbf
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ *  tm6000-i2c.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ *     - Fix SMBus Read Byte command
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+
+#include "tm6000.h"
+#include "tm6000-regs.h"
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+#include "tuner-xc2028.h"
+
+
+/* ----------------------------------------------------------- */
+
+static unsigned int i2c_debug;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+#define i2c_dprintk(lvl, fmt, args...) if (i2c_debug >= lvl) do { \
+                       printk(KERN_DEBUG "%s at %s: " fmt, \
+                       dev->name, __func__, ##args); } while (0)
+
+static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr,
+                               __u8 reg, char *buf, int len)
+{
+       int rc;
+       unsigned int tsleep;
+       unsigned int i2c_packet_limit = 16;
+
+       if (dev->dev_type == TM6010)
+               i2c_packet_limit = 64;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > i2c_packet_limit) {
+               printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
+                       len, i2c_packet_limit);
+               return -1;
+       }
+
+       /* capture mutex */
+       rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+               addr | reg << 8, 0, buf, len);
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* Calculate delay time, 14000us for 64 bytes */
+       tsleep = ((len * 200) + 200 + 1000) / 1000;
+       msleep(tsleep);
+
+       /* release mutex */
+       return rc;
+}
+
+/* Generic read - doesn't work fine with 16bit registers */
+static int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr,
+                               __u8 reg, char *buf, int len)
+{
+       int rc;
+       u8 b[2];
+       unsigned int i2c_packet_limit = 16;
+
+       if (dev->dev_type == TM6010)
+               i2c_packet_limit = 64;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > i2c_packet_limit) {
+               printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
+                       len, i2c_packet_limit);
+               return -1;
+       }
+
+       /* capture mutex */
+       if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
+               /*
+                * Workaround an I2C bug when reading from zl10353
+                */
+               reg -= 1;
+               len += 1;
+
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len);
+
+               *buf = b[1];
+       } else {
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
+       }
+
+       /* release mutex */
+       return rc;
+}
+
+/*
+ * read from a 16bit register
+ * for example xc2028, xc3028 or xc3028L
+ */
+static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr,
+                                 __u16 reg, char *buf, int len)
+{
+       int rc;
+       unsigned char ureg;
+
+       if (!buf || len != 2)
+               return -1;
+
+       /* capture mutex */
+       if (dev->dev_type == TM6010) {
+               ureg = reg & 0xFF;
+               rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
+                       USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+                       addr | (reg & 0xFF00), 0, &ureg, 1);
+
+               if (rc < 0) {
+                       /* release mutex */
+                       return rc;
+               }
+
+               msleep(1400 / 1000);
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+                       USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+                       reg, 0, buf, len);
+       } else {
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+                       USB_RECIP_DEVICE, REQ_14_SET_GET_I2C_WR2_RDN,
+                       addr, reg, buf, len);
+       }
+
+       /* release mutex */
+       return rc;
+}
+
+static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
+                          struct i2c_msg msgs[], int num)
+{
+       struct tm6000_core *dev = i2c_adap->algo_data;
+       int addr, rc, i, byte;
+
+       if (num <= 0)
+               return 0;
+       for (i = 0; i < num; i++) {
+               addr = (msgs[i].addr << 1) & 0xff;
+               i2c_dprintk(2, "%s %s addr=0x%x len=%d:",
+                        (msgs[i].flags & I2C_M_RD) ? "read" : "write",
+                        i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
+               if (msgs[i].flags & I2C_M_RD) {
+                       /* read request without preceding register selection */
+                       /*
+                        * The TM6000 only supports a read transaction
+                        * immediately after a 1 or 2 byte write to select
+                        * a register.  We cannot fulfil this request.
+                        */
+                       i2c_dprintk(2, " read without preceding write not"
+                                      " supported");
+                       rc = -EOPNOTSUPP;
+                       goto err;
+               } else if (i + 1 < num && msgs[i].len <= 2 &&
+                          (msgs[i + 1].flags & I2C_M_RD) &&
+                          msgs[i].addr == msgs[i + 1].addr) {
+                       /* 1 or 2 byte write followed by a read */
+                       if (i2c_debug >= 2)
+                               for (byte = 0; byte < msgs[i].len; byte++)
+                                       printk(KERN_CONT " %02x", msgs[i].buf[byte]);
+                       i2c_dprintk(2, "; joined to read %s len=%d:",
+                                   i == num - 2 ? "stop" : "nonstop",
+                                   msgs[i + 1].len);
+
+                       if (msgs[i].len == 2) {
+                               rc = tm6000_i2c_recv_regs16(dev, addr,
+                                       msgs[i].buf[0] << 8 | msgs[i].buf[1],
+                                       msgs[i + 1].buf, msgs[i + 1].len);
+                       } else {
+                               rc = tm6000_i2c_recv_regs(dev, addr, msgs[i].buf[0],
+                                       msgs[i + 1].buf, msgs[i + 1].len);
+                       }
+
+                       i++;
+
+                       if (addr == dev->tuner_addr << 1) {
+                               tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
+                               tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
+                       }
+                       if (i2c_debug >= 2)
+                               for (byte = 0; byte < msgs[i].len; byte++)
+                                       printk(KERN_CONT " %02x", msgs[i].buf[byte]);
+               } else {
+                       /* write bytes */
+                       if (i2c_debug >= 2)
+                               for (byte = 0; byte < msgs[i].len; byte++)
+                                       printk(KERN_CONT " %02x", msgs[i].buf[byte]);
+                       rc = tm6000_i2c_send_regs(dev, addr, msgs[i].buf[0],
+                               msgs[i].buf + 1, msgs[i].len - 1);
+               }
+               if (i2c_debug >= 2)
+                       printk(KERN_CONT "\n");
+               if (rc < 0)
+                       goto err;
+       }
+
+       return num;
+err:
+       i2c_dprintk(2, " ERROR: %i\n", rc);
+       return rc;
+}
+
+static int tm6000_i2c_eeprom(struct tm6000_core *dev)
+{
+       int i, rc;
+       unsigned char *p = dev->eedata;
+       unsigned char bytes[17];
+
+       dev->i2c_client.addr = 0xa0 >> 1;
+       dev->eedata_size = 0;
+
+       bytes[16] = '\0';
+       for (i = 0; i < sizeof(dev->eedata); ) {
+               *p = i;
+               rc = tm6000_i2c_recv_regs(dev, 0xa0, i, p, 1);
+               if (rc < 1) {
+                       if (p == dev->eedata)
+                               goto noeeprom;
+                       else {
+                               printk(KERN_WARNING
+                               "%s: i2c eeprom read error (err=%d)\n",
+                               dev->name, rc);
+                       }
+                       return -EINVAL;
+               }
+               dev->eedata_size++;
+               p++;
+               if (0 == (i % 16))
+                       printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
+               printk(KERN_CONT " %02x", dev->eedata[i]);
+               if ((dev->eedata[i] >= ' ') && (dev->eedata[i] <= 'z'))
+                       bytes[i%16] = dev->eedata[i];
+               else
+                       bytes[i%16] = '.';
+
+               i++;
+
+               if (0 == (i % 16)) {
+                       bytes[16] = '\0';
+                       printk(KERN_CONT "  %s\n", bytes);
+               }
+       }
+       if (0 != (i%16)) {
+               bytes[i%16] = '\0';
+               for (i %= 16; i < 16; i++)
+                       printk(KERN_CONT "   ");
+               printk(KERN_CONT "  %s\n", bytes);
+       }
+
+       return 0;
+
+noeeprom:
+       printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
+              dev->name, rc);
+       return -EINVAL;
+}
+
+/* ----------------------------------------------------------- */
+
+/*
+ * functionality()
+ */
+static u32 functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm tm6000_algo = {
+       .master_xfer   = tm6000_i2c_xfer,
+       .functionality = functionality,
+};
+
+/* ----------------------------------------------------------- */
+
+/*
+ * tm6000_i2c_register()
+ * register i2c bus
+ */
+int tm6000_i2c_register(struct tm6000_core *dev)
+{
+       int rc;
+
+       dev->i2c_adap.owner = THIS_MODULE;
+       dev->i2c_adap.algo = &tm6000_algo;
+       dev->i2c_adap.dev.parent = &dev->udev->dev;
+       strlcpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name));
+       dev->i2c_adap.algo_data = dev;
+       i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
+       rc = i2c_add_adapter(&dev->i2c_adap);
+       if (rc)
+               return rc;
+
+       dev->i2c_client.adapter = &dev->i2c_adap;
+       strlcpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE);
+       tm6000_i2c_eeprom(dev);
+
+       return 0;
+}
+
+/*
+ * tm6000_i2c_unregister()
+ * unregister i2c_bus
+ */
+int tm6000_i2c_unregister(struct tm6000_core *dev)
+{
+       i2c_del_adapter(&dev->i2c_adap);
+       return 0;
+}
diff --git a/drivers/media/video/tm6000/tm6000-input.c b/drivers/media/video/tm6000/tm6000-input.c
new file mode 100644 (file)
index 0000000..405d127
--- /dev/null
@@ -0,0 +1,459 @@
+/*
+ *  tm6000-input.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2010 Stefan Ringel <stefan.ringel@arcor.de>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <linux/input.h>
+#include <linux/usb.h>
+
+#include <media/rc-core.h>
+
+#include "tm6000.h"
+#include "tm6000-regs.h"
+
+static unsigned int ir_debug;
+module_param(ir_debug, int, 0644);
+MODULE_PARM_DESC(ir_debug, "enable debug message [IR]");
+
+static unsigned int enable_ir = 1;
+module_param(enable_ir, int, 0644);
+MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)");
+
+/* number of 50ms for ON-OFF-ON power led */
+/* show IR activity */
+#define PWLED_OFF 2
+
+#undef dprintk
+
+#define dprintk(fmt, arg...) \
+       if (ir_debug) { \
+               printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
+       }
+
+struct tm6000_ir_poll_result {
+       u16 rc_data;
+};
+
+struct tm6000_IR {
+       struct tm6000_core      *dev;
+       struct rc_dev           *rc;
+       char                    name[32];
+       char                    phys[32];
+
+       /* poll expernal decoder */
+       int                     polling;
+       struct delayed_work     work;
+       u8                      wait:1;
+       u8                      key:1;
+       u8                      pwled:1;
+       u8                      pwledcnt;
+       u16                     key_addr;
+       struct urb              *int_urb;
+       u8                      *urb_data;
+
+       int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *);
+
+       /* IR device properties */
+       u64                     rc_type;
+};
+
+
+void tm6000_ir_wait(struct tm6000_core *dev, u8 state)
+{
+       struct tm6000_IR *ir = dev->ir;
+
+       if (!dev->ir)
+               return;
+
+       if (state)
+               ir->wait = 1;
+       else
+               ir->wait = 0;
+}
+
+
+static int tm6000_ir_config(struct tm6000_IR *ir)
+{
+       struct tm6000_core *dev = ir->dev;
+       u8 buf[10];
+       int rc;
+
+       switch (ir->rc_type) {
+       case RC_TYPE_NEC:
+               /* Setup IR decoder for NEC standard 12MHz system clock */
+               /* IR_LEADER_CNT = 0.9ms             */
+               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER1, 0xaa);
+               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER0, 0x30);
+               /* IR_PULSE_CNT = 0.7ms              */
+               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20);
+               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0);
+               /* Remote WAKEUP = enable */
+               tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe);
+               /* IR_WKUP_SEL = Low byte in decoded IR data */
+               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff);
+               /* IR_WKU_ADD code */
+               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_ADD, 0xff);
+               tm6000_flash_led(dev, 0);
+               msleep(100);
+               tm6000_flash_led(dev, 1);
+               break;
+       default:
+               /* hack */
+               buf[0] = 0xff;
+               buf[1] = 0xff;
+               buf[2] = 0xf2;
+               buf[3] = 0x2b;
+               buf[4] = 0x20;
+               buf[5] = 0x35;
+               buf[6] = 0x60;
+               buf[7] = 0x04;
+               buf[8] = 0xc0;
+               buf[9] = 0x08;
+
+               rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
+                       USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a);
+               msleep(100);
+
+               if (rc < 0) {
+                       printk(KERN_INFO "IR configuration failed");
+                       return rc;
+               }
+               break;
+       }
+
+       return 0;
+}
+
+static void tm6000_ir_urb_received(struct urb *urb)
+{
+       struct tm6000_core *dev = urb->context;
+       struct tm6000_IR *ir = dev->ir;
+       int rc;
+
+       if (urb->status != 0)
+               printk(KERN_INFO "not ready\n");
+       else if (urb->actual_length > 0) {
+               memcpy(ir->urb_data, urb->transfer_buffer, urb->actual_length);
+
+               dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0],
+                       ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]);
+
+               ir->key = 1;
+       }
+
+       rc = usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static int default_polling_getkey(struct tm6000_IR *ir,
+                               struct tm6000_ir_poll_result *poll_result)
+{
+       struct tm6000_core *dev = ir->dev;
+       int rc;
+       u8 buf[2];
+
+       if (ir->wait && !&dev->int_in)
+               return 0;
+
+       if (&dev->int_in) {
+               switch (ir->rc_type) {
+               case RC_TYPE_RC5:
+                       poll_result->rc_data = ir->urb_data[0];
+                       break;
+               case RC_TYPE_NEC:
+                       if (ir->urb_data[1] == ((ir->key_addr >> 8) & 0xff)) {
+                               poll_result->rc_data = ir->urb_data[0]
+                                                       | ir->urb_data[1] << 8;
+                       }
+                       break;
+               default:
+                       poll_result->rc_data = ir->urb_data[0]
+                                       | ir->urb_data[1] << 8;
+                       break;
+               }
+       } else {
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
+               msleep(10);
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1);
+               msleep(10);
+
+               if (ir->rc_type == RC_TYPE_RC5) {
+                       rc = tm6000_read_write_usb(dev, USB_DIR_IN |
+                               USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               REQ_02_GET_IR_CODE, 0, 0, buf, 1);
+
+                       msleep(10);
+
+                       dprintk("read data=%02x\n", buf[0]);
+                       if (rc < 0)
+                               return rc;
+
+                       poll_result->rc_data = buf[0];
+               } else {
+                       rc = tm6000_read_write_usb(dev, USB_DIR_IN |
+                               USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               REQ_02_GET_IR_CODE, 0, 0, buf, 2);
+
+                       msleep(10);
+
+                       dprintk("read data=%04x\n", buf[0] | buf[1] << 8);
+                       if (rc < 0)
+                               return rc;
+
+                       poll_result->rc_data = buf[0] | buf[1] << 8;
+               }
+               if ((poll_result->rc_data & 0x00ff) != 0xff)
+                       ir->key = 1;
+       }
+       return 0;
+}
+
+static void tm6000_ir_handle_key(struct tm6000_IR *ir)
+{
+       struct tm6000_core *dev = ir->dev;
+       int result;
+       struct tm6000_ir_poll_result poll_result;
+
+       /* read the registers containing the IR status */
+       result = ir->get_key(ir, &poll_result);
+       if (result < 0) {
+               printk(KERN_INFO "ir->get_key() failed %d\n", result);
+               return;
+       }
+
+       dprintk("ir->get_key result data=%04x\n", poll_result.rc_data);
+
+       if (ir->pwled) {
+               if (ir->pwledcnt >= PWLED_OFF) {
+                       ir->pwled = 0;
+                       ir->pwledcnt = 0;
+                       tm6000_flash_led(dev, 1);
+               } else
+                       ir->pwledcnt += 1;
+       }
+
+       if (ir->key) {
+               rc_keydown(ir->rc, poll_result.rc_data, 0);
+               ir->key = 0;
+               ir->pwled = 1;
+               ir->pwledcnt = 0;
+               tm6000_flash_led(dev, 0);
+       }
+       return;
+}
+
+static void tm6000_ir_work(struct work_struct *work)
+{
+       struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
+
+       tm6000_ir_handle_key(ir);
+       schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
+}
+
+static int tm6000_ir_start(struct rc_dev *rc)
+{
+       struct tm6000_IR *ir = rc->priv;
+
+       INIT_DELAYED_WORK(&ir->work, tm6000_ir_work);
+       schedule_delayed_work(&ir->work, 0);
+
+       return 0;
+}
+
+static void tm6000_ir_stop(struct rc_dev *rc)
+{
+       struct tm6000_IR *ir = rc->priv;
+
+       cancel_delayed_work_sync(&ir->work);
+}
+
+static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
+{
+       struct tm6000_IR *ir = rc->priv;
+
+       if (!ir)
+               return 0;
+
+       if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC))
+               ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff);
+
+       ir->get_key = default_polling_getkey;
+       ir->rc_type = rc_type;
+
+       tm6000_ir_config(ir);
+       /* TODO */
+       return 0;
+}
+
+int tm6000_ir_int_start(struct tm6000_core *dev)
+{
+       struct tm6000_IR *ir = dev->ir;
+       int pipe, size;
+       int err = -ENOMEM;
+
+
+       if (!ir)
+               return -ENODEV;
+
+       ir->int_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!ir->int_urb)
+               return -ENOMEM;
+
+       pipe = usb_rcvintpipe(dev->udev,
+               dev->int_in.endp->desc.bEndpointAddress
+               & USB_ENDPOINT_NUMBER_MASK);
+
+       size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
+       dprintk("IR max size: %d\n", size);
+
+       ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
+       if (ir->int_urb->transfer_buffer == NULL) {
+               usb_free_urb(ir->int_urb);
+               return err;
+       }
+       dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval);
+       usb_fill_int_urb(ir->int_urb, dev->udev, pipe,
+               ir->int_urb->transfer_buffer, size,
+               tm6000_ir_urb_received, dev,
+               dev->int_in.endp->desc.bInterval);
+       err = usb_submit_urb(ir->int_urb, GFP_KERNEL);
+       if (err) {
+               kfree(ir->int_urb->transfer_buffer);
+               usb_free_urb(ir->int_urb);
+               return err;
+       }
+       ir->urb_data = kzalloc(size, GFP_KERNEL);
+
+       return 0;
+}
+
+void tm6000_ir_int_stop(struct tm6000_core *dev)
+{
+       struct tm6000_IR *ir = dev->ir;
+
+       if (!ir)
+               return;
+
+       usb_kill_urb(ir->int_urb);
+       kfree(ir->int_urb->transfer_buffer);
+       usb_free_urb(ir->int_urb);
+       ir->int_urb = NULL;
+       kfree(ir->urb_data);
+       ir->urb_data = NULL;
+}
+
+int tm6000_ir_init(struct tm6000_core *dev)
+{
+       struct tm6000_IR *ir;
+       struct rc_dev *rc;
+       int err = -ENOMEM;
+
+       if (!enable_ir)
+               return -ENODEV;
+
+       if (!dev->caps.has_remote)
+               return 0;
+
+       if (!dev->ir_codes)
+               return 0;
+
+       ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+       rc = rc_allocate_device();
+       if (!ir || !rc)
+               goto out;
+
+       /* record handles to ourself */
+       ir->dev = dev;
+       dev->ir = ir;
+       ir->rc = rc;
+
+       /* input einrichten */
+       rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
+       rc->priv = ir;
+       rc->change_protocol = tm6000_ir_change_protocol;
+       rc->open = tm6000_ir_start;
+       rc->close = tm6000_ir_stop;
+       rc->driver_type = RC_DRIVER_SCANCODE;
+
+       ir->polling = 50;
+       ir->pwled = 0;
+       ir->pwledcnt = 0;
+
+
+       snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)",
+                                               dev->name);
+
+       usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
+       strlcat(ir->phys, "/input0", sizeof(ir->phys));
+
+       tm6000_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
+
+       rc->input_name = ir->name;
+       rc->input_phys = ir->phys;
+       rc->input_id.bustype = BUS_USB;
+       rc->input_id.version = 1;
+       rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
+       rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
+       rc->map_name = dev->ir_codes;
+       rc->driver_name = "tm6000";
+       rc->dev.parent = &dev->udev->dev;
+
+       if (&dev->int_in) {
+               dprintk("IR over int\n");
+
+               err = tm6000_ir_int_start(dev);
+
+               if (err)
+                       goto out;
+       }
+
+       /* ir register */
+       err = rc_register_device(rc);
+       if (err)
+               goto out;
+
+       return 0;
+
+out:
+       dev->ir = NULL;
+       rc_free_device(rc);
+       kfree(ir);
+       return err;
+}
+
+int tm6000_ir_fini(struct tm6000_core *dev)
+{
+       struct tm6000_IR *ir = dev->ir;
+
+       /* skip detach on non attached board */
+
+       if (!ir)
+               return 0;
+
+       rc_unregister_device(ir->rc);
+
+       if (ir->int_urb)
+               tm6000_ir_int_stop(dev);
+
+       kfree(ir);
+       dev->ir = NULL;
+
+       return 0;
+}
diff --git a/drivers/media/video/tm6000/tm6000-regs.h b/drivers/media/video/tm6000/tm6000-regs.h
new file mode 100644 (file)
index 0000000..7f491b6
--- /dev/null
@@ -0,0 +1,600 @@
+/*
+ *  tm6000-regs.h - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Define TV Master TM5600/TM6000/TM6010 Request codes
+ */
+#define REQ_00_SET_IR_VALUE            0
+#define REQ_01_SET_WAKEUP_IRCODE       1
+#define REQ_02_GET_IR_CODE             2
+#define REQ_03_SET_GET_MCU_PIN         3
+#define REQ_04_EN_DISABLE_MCU_INT      4
+#define REQ_05_SET_GET_USBREG          5
+       /* Write: RegNum, Value, 0 */
+       /* Read : RegNum, Value, 1, RegStatus */
+#define REQ_06_SET_GET_USBREG_BIT      6
+#define REQ_07_SET_GET_AVREG           7
+       /* Write: RegNum, Value, 0 */
+       /* Read : RegNum, Value, 1, RegStatus */
+#define REQ_08_SET_GET_AVREG_BIT       8
+#define REQ_09_SET_GET_TUNER_FQ                9
+#define REQ_10_SET_TUNER_SYSTEM                10
+#define REQ_11_SET_EEPROM_ADDR         11
+#define REQ_12_SET_GET_EEPROMBYTE      12
+#define REQ_13_GET_EEPROM_SEQREAD      13
+#define REQ_14_SET_GET_I2C_WR2_RDN     14
+#define REQ_15_SET_GET_I2CBYTE         15
+       /* Write: Subaddr, Slave Addr, value, 0 */
+       /* Read : Subaddr, Slave Addr, value, 1 */
+#define REQ_16_SET_GET_I2C_WR1_RDN     16
+       /* Subaddr, Slave Addr, 0, length */
+#define REQ_17_SET_GET_I2CFP           17
+       /* Write: Slave Addr, register, value */
+       /* Read : Slave Addr, register, 2, data */
+#define REQ_20_DATA_TRANSFER           20
+#define REQ_30_I2C_WRITE               30
+#define REQ_31_I2C_READ                        31
+#define REQ_35_AFTEK_TUNER_READ                35
+#define REQ_40_GET_VERSION             40
+#define REQ_50_SET_START               50
+#define REQ_51_SET_STOP                        51
+#define REQ_52_TRANSMIT_DATA           52
+#define REQ_53_SPI_INITIAL             53
+#define REQ_54_SPI_SETSTART            54
+#define REQ_55_SPI_INOUTDATA           55
+#define REQ_56_SPI_SETSTOP             56
+
+/*
+ * Define TV Master TM5600/TM6000/TM6010 GPIO lines
+ */
+
+#define TM6000_GPIO_CLK                0x101
+#define TM6000_GPIO_DATA       0x100
+
+#define TM6000_GPIO_1          0x102
+#define TM6000_GPIO_2          0x103
+#define TM6000_GPIO_3          0x104
+#define TM6000_GPIO_4          0x300
+#define TM6000_GPIO_5          0x301
+#define TM6000_GPIO_6          0x304
+#define TM6000_GPIO_7          0x305
+
+/* tm6010 defines GPIO with different values */
+#define TM6010_GPIO_0      0x0102
+#define TM6010_GPIO_1      0x0103
+#define TM6010_GPIO_2      0x0104
+#define TM6010_GPIO_3      0x0105
+#define TM6010_GPIO_4      0x0106
+#define TM6010_GPIO_5      0x0107
+#define TM6010_GPIO_6      0x0300
+#define TM6010_GPIO_7      0x0301
+#define TM6010_GPIO_9      0x0305
+/*
+ * Define TV Master TM5600/TM6000/TM6010 URB message codes and length
+ */
+
+enum {
+       TM6000_URB_MSG_VIDEO = 1,
+       TM6000_URB_MSG_AUDIO,
+       TM6000_URB_MSG_VBI,
+       TM6000_URB_MSG_PTS,
+       TM6000_URB_MSG_ERR,
+};
+
+/* Define specific TM6000 Video decoder registers */
+#define TM6000_REQ07_RD8_TEST_SEL                      0x07, 0xd8
+#define TM6000_REQ07_RD9_A_SIM_SEL                     0x07, 0xd9
+#define TM6000_REQ07_RDA_CLK_SEL                       0x07, 0xda
+#define TM6000_REQ07_RDB_OUT_SEL                       0x07, 0xdb
+#define TM6000_REQ07_RDC_NSEL_I2S                      0x07, 0xdc
+#define TM6000_REQ07_RDD_GPIO2_MDRV                    0x07, 0xdd
+#define TM6000_REQ07_RDE_GPIO1_MDRV                    0x07, 0xde
+#define TM6000_REQ07_RDF_PWDOWN_ACLK                   0x07, 0xdf
+#define TM6000_REQ07_RE0_VADC_REF_CTL                  0x07, 0xe0
+#define TM6000_REQ07_RE1_VADC_DACLIMP                  0x07, 0xe1
+#define TM6000_REQ07_RE2_VADC_STATUS_CTL               0x07, 0xe2
+#define TM6000_REQ07_RE3_VADC_INP_LPF_SEL1             0x07, 0xe3
+#define TM6000_REQ07_RE4_VADC_TARGET1                  0x07, 0xe4
+#define TM6000_REQ07_RE5_VADC_INP_LPF_SEL2             0x07, 0xe5
+#define TM6000_REQ07_RE6_VADC_TARGET2                  0x07, 0xe6
+#define TM6000_REQ07_RE7_VADC_AGAIN_CTL                        0x07, 0xe7
+#define TM6000_REQ07_RE8_VADC_PWDOWN_CTL               0x07, 0xe8
+#define TM6000_REQ07_RE9_VADC_INPUT_CTL1               0x07, 0xe9
+#define TM6000_REQ07_REA_VADC_INPUT_CTL2               0x07, 0xea
+#define TM6000_REQ07_REB_VADC_AADC_MODE                        0x07, 0xeb
+#define TM6000_REQ07_REC_VADC_AADC_LVOL                        0x07, 0xec
+#define TM6000_REQ07_RED_VADC_AADC_RVOL                        0x07, 0xed
+#define TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL         0x07, 0xee
+#define TM6000_REQ07_REF_VADC_GAIN_MAP_CTL             0x07, 0xef
+#define TM6000_REQ07_RFD_BIST_ERR_VST_LOW              0x07, 0xfd
+#define TM6000_REQ07_RFE_BIST_ERR_VST_HIGH             0x07, 0xfe
+
+/* Define TM6000/TM6010 Video decoder registers */
+#define TM6010_REQ07_R00_VIDEO_CONTROL0                        0x07, 0x00
+#define TM6010_REQ07_R01_VIDEO_CONTROL1                        0x07, 0x01
+#define TM6010_REQ07_R02_VIDEO_CONTROL2                        0x07, 0x02
+#define TM6010_REQ07_R03_YC_SEP_CONTROL                        0x07, 0x03
+#define TM6010_REQ07_R04_LUMA_HAGC_CONTROL             0x07, 0x04
+#define TM6010_REQ07_R05_NOISE_THRESHOLD               0x07, 0x05
+#define TM6010_REQ07_R06_AGC_GATE_THRESHOLD            0x07, 0x06
+#define TM6010_REQ07_R07_OUTPUT_CONTROL                        0x07, 0x07
+#define TM6010_REQ07_R08_LUMA_CONTRAST_ADJ             0x07, 0x08
+#define TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ           0x07, 0x09
+#define TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ         0x07, 0x0a
+#define TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ          0x07, 0x0b
+#define TM6010_REQ07_R0C_CHROMA_AGC_CONTROL            0x07, 0x0c
+#define TM6010_REQ07_R0D_CHROMA_KILL_LEVEL             0x07, 0x0d
+#define TM6010_REQ07_R0F_CHROMA_AUTO_POSITION          0x07, 0x0f
+#define TM6010_REQ07_R10_AGC_PEAK_NOMINAL              0x07, 0x10
+#define TM6010_REQ07_R11_AGC_PEAK_CONTROL              0x07, 0x11
+#define TM6010_REQ07_R12_AGC_GATE_STARTH               0x07, 0x12
+#define TM6010_REQ07_R13_AGC_GATE_STARTL               0x07, 0x13
+#define TM6010_REQ07_R14_AGC_GATE_WIDTH                        0x07, 0x14
+#define TM6010_REQ07_R15_AGC_BP_DELAY                  0x07, 0x15
+#define TM6010_REQ07_R16_LOCK_COUNT                    0x07, 0x16
+#define TM6010_REQ07_R17_HLOOP_MAXSTATE                        0x07, 0x17
+#define TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3         0x07, 0x18
+#define TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2         0x07, 0x19
+#define TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1         0x07, 0x1a
+#define TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0         0x07, 0x1b
+#define TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3          0x07, 0x1c
+#define TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2          0x07, 0x1d
+#define TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1          0x07, 0x1e
+#define TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0          0x07, 0x1f
+#define TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME                0x07, 0x20
+#define TM6010_REQ07_R21_HSYNC_PHASE_OFFSET            0x07, 0x21
+#define TM6010_REQ07_R22_HSYNC_PLL_START_TIME          0x07, 0x22
+#define TM6010_REQ07_R23_HSYNC_PLL_END_TIME            0x07, 0x23
+#define TM6010_REQ07_R24_HSYNC_TIP_START_TIME          0x07, 0x24
+#define TM6010_REQ07_R25_HSYNC_TIP_END_TIME            0x07, 0x25
+#define TM6010_REQ07_R26_HSYNC_RISING_EDGE_START       0x07, 0x26
+#define TM6010_REQ07_R27_HSYNC_RISING_EDGE_END         0x07, 0x27
+#define TM6010_REQ07_R28_BACKPORCH_START               0x07, 0x28
+#define TM6010_REQ07_R29_BACKPORCH_END                 0x07, 0x29
+#define TM6010_REQ07_R2A_HSYNC_FILTER_START            0x07, 0x2a
+#define TM6010_REQ07_R2B_HSYNC_FILTER_END              0x07, 0x2b
+#define TM6010_REQ07_R2C_CHROMA_BURST_START            0x07, 0x2c
+#define TM6010_REQ07_R2D_CHROMA_BURST_END              0x07, 0x2d
+#define TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART           0x07, 0x2e
+#define TM6010_REQ07_R2F_ACTIVE_VIDEO_HWIDTH           0x07, 0x2f
+#define TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART           0x07, 0x30
+#define TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT           0x07, 0x31
+#define TM6010_REQ07_R32_VSYNC_HLOCK_MIN               0x07, 0x32
+#define TM6010_REQ07_R33_VSYNC_HLOCK_MAX               0x07, 0x33
+#define TM6010_REQ07_R34_VSYNC_AGC_MIN                 0x07, 0x34
+#define TM6010_REQ07_R35_VSYNC_AGC_MAX                 0x07, 0x35
+#define TM6010_REQ07_R36_VSYNC_VBI_MIN                 0x07, 0x36
+#define TM6010_REQ07_R37_VSYNC_VBI_MAX                 0x07, 0x37
+#define TM6010_REQ07_R38_VSYNC_THRESHOLD               0x07, 0x38
+#define TM6010_REQ07_R39_VSYNC_TIME_CONSTANT           0x07, 0x39
+#define TM6010_REQ07_R3A_STATUS1                       0x07, 0x3a
+#define TM6010_REQ07_R3B_STATUS2                       0x07, 0x3b
+#define TM6010_REQ07_R3C_STATUS3                       0x07, 0x3c
+#define TM6010_REQ07_R3F_RESET                         0x07, 0x3f
+#define TM6010_REQ07_R40_TELETEXT_VBI_CODE0            0x07, 0x40
+#define TM6010_REQ07_R41_TELETEXT_VBI_CODE1            0x07, 0x41
+#define TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL           0x07, 0x42
+#define TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7           0x07, 0x43
+#define TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8           0x07, 0x44
+#define TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9           0x07, 0x45
+#define TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10          0x07, 0x46
+#define TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11          0x07, 0x47
+#define TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12          0x07, 0x48
+#define TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13          0x07, 0x49
+#define TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14          0x07, 0x4a
+#define TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15          0x07, 0x4b
+#define TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16          0x07, 0x4c
+#define TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17          0x07, 0x4d
+#define TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18          0x07, 0x4e
+#define TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19          0x07, 0x4f
+#define TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20          0x07, 0x50
+#define TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21          0x07, 0x51
+#define TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22          0x07, 0x52
+#define TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23          0x07, 0x53
+#define TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES          0x07, 0x54
+#define TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN          0x07, 0x55
+#define TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN                0x07, 0x56
+#define TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN                0x07, 0x57
+#define TM6010_REQ07_R58_VBI_CAPTION_DTO1              0x07, 0x58
+#define TM6010_REQ07_R59_VBI_CAPTION_DTO0              0x07, 0x59
+#define TM6010_REQ07_R5A_VBI_TELETEXT_DTO1             0x07, 0x5a
+#define TM6010_REQ07_R5B_VBI_TELETEXT_DTO0             0x07, 0x5b
+#define TM6010_REQ07_R5C_VBI_WSS625_DTO1               0x07, 0x5c
+#define TM6010_REQ07_R5D_VBI_WSS625_DTO0               0x07, 0x5d
+#define TM6010_REQ07_R5E_VBI_CAPTION_FRAME_START       0x07, 0x5e
+#define TM6010_REQ07_R5F_VBI_WSS625_FRAME_START                0x07, 0x5f
+#define TM6010_REQ07_R60_TELETEXT_FRAME_START          0x07, 0x60
+#define TM6010_REQ07_R61_VBI_CCDATA1                   0x07, 0x61
+#define TM6010_REQ07_R62_VBI_CCDATA2                   0x07, 0x62
+#define TM6010_REQ07_R63_VBI_WSS625_DATA1              0x07, 0x63
+#define TM6010_REQ07_R64_VBI_WSS625_DATA2              0x07, 0x64
+#define TM6010_REQ07_R65_VBI_DATA_STATUS               0x07, 0x65
+#define TM6010_REQ07_R66_VBI_CAPTION_START             0x07, 0x66
+#define TM6010_REQ07_R67_VBI_WSS625_START              0x07, 0x67
+#define TM6010_REQ07_R68_VBI_TELETEXT_START            0x07, 0x68
+#define TM6010_REQ07_R70_HSYNC_DTO_INC_STATUS3         0x07, 0x70
+#define TM6010_REQ07_R71_HSYNC_DTO_INC_STATUS2         0x07, 0x71
+#define TM6010_REQ07_R72_HSYNC_DTO_INC_STATUS1         0x07, 0x72
+#define TM6010_REQ07_R73_HSYNC_DTO_INC_STATUS0         0x07, 0x73
+#define TM6010_REQ07_R74_CHROMA_DTO_INC_STATUS3                0x07, 0x74
+#define TM6010_REQ07_R75_CHROMA_DTO_INC_STATUS2                0x07, 0x75
+#define TM6010_REQ07_R76_CHROMA_DTO_INC_STATUS1                0x07, 0x76
+#define TM6010_REQ07_R77_CHROMA_DTO_INC_STATUS0                0x07, 0x77
+#define TM6010_REQ07_R78_AGC_AGAIN_STATUS              0x07, 0x78
+#define TM6010_REQ07_R79_AGC_DGAIN_STATUS              0x07, 0x79
+#define TM6010_REQ07_R7A_CHROMA_MAG_STATUS             0x07, 0x7a
+#define TM6010_REQ07_R7B_CHROMA_GAIN_STATUS1           0x07, 0x7b
+#define TM6010_REQ07_R7C_CHROMA_GAIN_STATUS0           0x07, 0x7c
+#define TM6010_REQ07_R7D_CORDIC_FREQ_STATUS            0x07, 0x7d
+#define TM6010_REQ07_R7F_STATUS_NOISE                  0x07, 0x7f
+#define TM6010_REQ07_R80_COMB_FILTER_TRESHOLD          0x07, 0x80
+#define TM6010_REQ07_R82_COMB_FILTER_CONFIG            0x07, 0x82
+#define TM6010_REQ07_R83_CHROMA_LOCK_CONFIG            0x07, 0x83
+#define TM6010_REQ07_R84_NOISE_NTSC_C                  0x07, 0x84
+#define TM6010_REQ07_R85_NOISE_PAL_C                   0x07, 0x85
+#define TM6010_REQ07_R86_NOISE_PHASE_C                 0x07, 0x86
+#define TM6010_REQ07_R87_NOISE_PHASE_Y                 0x07, 0x87
+#define TM6010_REQ07_R8A_CHROMA_LOOPFILTER_STATE       0x07, 0x8a
+#define TM6010_REQ07_R8B_CHROMA_HRESAMPLER             0x07, 0x8b
+#define TM6010_REQ07_R8D_CPUMP_DELAY_ADJ               0x07, 0x8d
+#define TM6010_REQ07_R8E_CPUMP_ADJ                     0x07, 0x8e
+#define TM6010_REQ07_R8F_CPUMP_DELAY                   0x07, 0x8f
+
+/* Define TM6000/TM6010 Miscellaneous registers */
+#define TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE           0x07, 0xc0
+#define TM6010_REQ07_RC1_TRESHOLD                      0x07, 0xc1
+#define TM6010_REQ07_RC2_HSYNC_WIDTH                   0x07, 0xc2
+#define TM6010_REQ07_RC3_HSTART1                       0x07, 0xc3
+#define TM6010_REQ07_RC4_HSTART0                       0x07, 0xc4
+#define TM6010_REQ07_RC5_HEND1                         0x07, 0xc5
+#define TM6010_REQ07_RC6_HEND0                         0x07, 0xc6
+#define TM6010_REQ07_RC7_VSTART1                       0x07, 0xc7
+#define TM6010_REQ07_RC8_VSTART0                       0x07, 0xc8
+#define TM6010_REQ07_RC9_VEND1                         0x07, 0xc9
+#define TM6010_REQ07_RCA_VEND0                         0x07, 0xca
+#define TM6010_REQ07_RCB_DELAY                         0x07, 0xcb
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RCC_ACTIVE_IF                     0x07, 0xcc
+#define TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE (1 << 5)
+#define TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE (1 << 6)
+#define TM6010_REQ07_RD0_USB_PERIPHERY_CONTROL         0x07, 0xd0
+#define TM6010_REQ07_RD1_ADDR_FOR_REQ1                 0x07, 0xd1
+#define TM6010_REQ07_RD2_ADDR_FOR_REQ2                 0x07, 0xd2
+#define TM6010_REQ07_RD3_ADDR_FOR_REQ3                 0x07, 0xd3
+#define TM6010_REQ07_RD4_ADDR_FOR_REQ4                 0x07, 0xd4
+#define TM6010_REQ07_RD5_POWERSAVE                     0x07, 0xd5
+#define TM6010_REQ07_RD6_ENDP_REQ1_REQ2                        0x07, 0xd6
+#define TM6010_REQ07_RD7_ENDP_REQ3_REQ4                        0x07, 0xd7
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR                            0x07, 0xd8
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR_BSIZE                      0x07, 0xd9
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR_WAKEUP_SEL                 0x07, 0xda
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR_WAKEUP_ADD                 0x07, 0xdb
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR_LEADER1                    0x07, 0xdc
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR_LEADER0                    0x07, 0xdd
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR_PULSE_CNT1                 0x07, 0xde
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR_PULSE_CNT0                 0x07, 0xdf
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE0_DVIDEO_SOURCE                 0x07, 0xe0
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE0_DVIDEO_SOURCE_IF              0x07, 0xe1
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE2_OUT_SEL2                      0x07, 0xe2
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE3_OUT_SEL1                      0x07, 0xe3
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE4_OUT_SEL0                      0x07, 0xe4
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE5_REMOTE_WAKEUP                 0x07, 0xe5
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE7_PUB_GPIO                      0x07, 0xe7
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE8_TYPESEL_MOS_I2S               0x07, 0xe8
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE9_TYPESEL_MOS_TS                        0x07, 0xe9
+/* ONLY for TM6010 */
+#define TM6010_REQ07_REA_TYPESEL_MOS_CCIR              0x07, 0xea
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF0_BIST_CRC_RESULT0              0x07, 0xf0
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF1_BIST_CRC_RESULT1              0x07, 0xf1
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF2_BIST_CRC_RESULT2              0x07, 0xf2
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF3_BIST_CRC_RESULT3              0x07, 0xf3
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF4_BIST_ERR_VST2                 0x07, 0xf4
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF5_BIST_ERR_VST1                 0x07, 0xf5
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF6_BIST_ERR_VST0                 0x07, 0xf6
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF7_BIST                          0x07, 0xf7
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RFE_POWER_DOWN                    0x07, 0xfe
+#define TM6010_REQ07_RFF_SOFT_RESET                    0x07, 0xff
+
+/* Define TM6000/TM6010 USB registers */
+#define TM6010_REQ05_R00_MAIN_CTRL             0x05, 0x00
+#define TM6010_REQ05_R01_DEVADDR               0x05, 0x01
+#define TM6010_REQ05_R02_TEST                  0x05, 0x02
+#define TM6010_REQ05_R04_SOFN0                 0x05, 0x04
+#define TM6010_REQ05_R05_SOFN1                 0x05, 0x05
+#define TM6010_REQ05_R06_SOFTM0                        0x05, 0x06
+#define TM6010_REQ05_R07_SOFTM1                        0x05, 0x07
+#define TM6010_REQ05_R08_PHY_TEST              0x05, 0x08
+#define TM6010_REQ05_R09_VCTL                  0x05, 0x09
+#define TM6010_REQ05_R0A_VSTA                  0x05, 0x0a
+#define TM6010_REQ05_R0B_CX_CFG                        0x05, 0x0b
+#define TM6010_REQ05_R0C_ENDP0_REG0            0x05, 0x0c
+#define TM6010_REQ05_R10_GMASK                 0x05, 0x10
+#define TM6010_REQ05_R11_IMASK0                        0x05, 0x11
+#define TM6010_REQ05_R12_IMASK1                        0x05, 0x12
+#define TM6010_REQ05_R13_IMASK2                        0x05, 0x13
+#define TM6010_REQ05_R14_IMASK3                        0x05, 0x14
+#define TM6010_REQ05_R15_IMASK4                        0x05, 0x15
+#define TM6010_REQ05_R16_IMASK5                        0x05, 0x16
+#define TM6010_REQ05_R17_IMASK6                        0x05, 0x17
+#define TM6010_REQ05_R18_IMASK7                        0x05, 0x18
+#define TM6010_REQ05_R19_ZEROP0                        0x05, 0x19
+#define TM6010_REQ05_R1A_ZEROP1                        0x05, 0x1a
+#define TM6010_REQ05_R1C_FIFO_EMP0             0x05, 0x1c
+#define TM6010_REQ05_R1D_FIFO_EMP1             0x05, 0x1d
+#define TM6010_REQ05_R20_IRQ_GROUP             0x05, 0x20
+#define TM6010_REQ05_R21_IRQ_SOURCE0           0x05, 0x21
+#define TM6010_REQ05_R22_IRQ_SOURCE1           0x05, 0x22
+#define TM6010_REQ05_R23_IRQ_SOURCE2           0x05, 0x23
+#define TM6010_REQ05_R24_IRQ_SOURCE3           0x05, 0x24
+#define TM6010_REQ05_R25_IRQ_SOURCE4           0x05, 0x25
+#define TM6010_REQ05_R26_IRQ_SOURCE5           0x05, 0x26
+#define TM6010_REQ05_R27_IRQ_SOURCE6           0x05, 0x27
+#define TM6010_REQ05_R28_IRQ_SOURCE7           0x05, 0x28
+#define TM6010_REQ05_R29_SEQ_ERR0              0x05, 0x29
+#define TM6010_REQ05_R2A_SEQ_ERR1              0x05, 0x2a
+#define TM6010_REQ05_R2B_SEQ_ABORT0            0x05, 0x2b
+#define TM6010_REQ05_R2C_SEQ_ABORT1            0x05, 0x2c
+#define TM6010_REQ05_R2D_TX_ZERO0              0x05, 0x2d
+#define TM6010_REQ05_R2E_TX_ZERO1              0x05, 0x2e
+#define TM6010_REQ05_R2F_IDLE_CNT              0x05, 0x2f
+#define TM6010_REQ05_R30_FNO_P1                        0x05, 0x30
+#define TM6010_REQ05_R31_FNO_P2                        0x05, 0x31
+#define TM6010_REQ05_R32_FNO_P3                        0x05, 0x32
+#define TM6010_REQ05_R33_FNO_P4                        0x05, 0x33
+#define TM6010_REQ05_R34_FNO_P5                        0x05, 0x34
+#define TM6010_REQ05_R35_FNO_P6                        0x05, 0x35
+#define TM6010_REQ05_R36_FNO_P7                        0x05, 0x36
+#define TM6010_REQ05_R37_FNO_P8                        0x05, 0x37
+#define TM6010_REQ05_R38_FNO_P9                        0x05, 0x38
+#define TM6010_REQ05_R30_FNO_P10               0x05, 0x39
+#define TM6010_REQ05_R30_FNO_P11               0x05, 0x3a
+#define TM6010_REQ05_R30_FNO_P12               0x05, 0x3b
+#define TM6010_REQ05_R30_FNO_P13               0x05, 0x3c
+#define TM6010_REQ05_R30_FNO_P14               0x05, 0x3d
+#define TM6010_REQ05_R30_FNO_P15               0x05, 0x3e
+#define TM6010_REQ05_R40_IN_MAXPS_LOW1         0x05, 0x40
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH1                0x05, 0x41
+#define TM6010_REQ05_R42_IN_MAXPS_LOW2         0x05, 0x42
+#define TM6010_REQ05_R43_IN_MAXPS_HIGH2                0x05, 0x43
+#define TM6010_REQ05_R44_IN_MAXPS_LOW3         0x05, 0x44
+#define TM6010_REQ05_R45_IN_MAXPS_HIGH3                0x05, 0x45
+#define TM6010_REQ05_R46_IN_MAXPS_LOW4         0x05, 0x46
+#define TM6010_REQ05_R47_IN_MAXPS_HIGH4                0x05, 0x47
+#define TM6010_REQ05_R48_IN_MAXPS_LOW5         0x05, 0x48
+#define TM6010_REQ05_R49_IN_MAXPS_HIGH5                0x05, 0x49
+#define TM6010_REQ05_R4A_IN_MAXPS_LOW6         0x05, 0x4a
+#define TM6010_REQ05_R4B_IN_MAXPS_HIGH6                0x05, 0x4b
+#define TM6010_REQ05_R4C_IN_MAXPS_LOW7         0x05, 0x4c
+#define TM6010_REQ05_R4D_IN_MAXPS_HIGH7                0x05, 0x4d
+#define TM6010_REQ05_R4E_IN_MAXPS_LOW8         0x05, 0x4e
+#define TM6010_REQ05_R4F_IN_MAXPS_HIGH8                0x05, 0x4f
+#define TM6010_REQ05_R50_IN_MAXPS_LOW9         0x05, 0x50
+#define TM6010_REQ05_R51_IN_MAXPS_HIGH9                0x05, 0x51
+#define TM6010_REQ05_R40_IN_MAXPS_LOW10                0x05, 0x52
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH10       0x05, 0x53
+#define TM6010_REQ05_R40_IN_MAXPS_LOW11                0x05, 0x54
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH11       0x05, 0x55
+#define TM6010_REQ05_R40_IN_MAXPS_LOW12                0x05, 0x56
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH12       0x05, 0x57
+#define TM6010_REQ05_R40_IN_MAXPS_LOW13                0x05, 0x58
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH13       0x05, 0x59
+#define TM6010_REQ05_R40_IN_MAXPS_LOW14                0x05, 0x5a
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH14       0x05, 0x5b
+#define TM6010_REQ05_R40_IN_MAXPS_LOW15                0x05, 0x5c
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH15       0x05, 0x5d
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW1                0x05, 0x60
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH1       0x05, 0x61
+#define TM6010_REQ05_R62_OUT_MAXPS_LOW2                0x05, 0x62
+#define TM6010_REQ05_R63_OUT_MAXPS_HIGH2       0x05, 0x63
+#define TM6010_REQ05_R64_OUT_MAXPS_LOW3                0x05, 0x64
+#define TM6010_REQ05_R65_OUT_MAXPS_HIGH3       0x05, 0x65
+#define TM6010_REQ05_R66_OUT_MAXPS_LOW4                0x05, 0x66
+#define TM6010_REQ05_R67_OUT_MAXPS_HIGH4       0x05, 0x67
+#define TM6010_REQ05_R68_OUT_MAXPS_LOW5                0x05, 0x68
+#define TM6010_REQ05_R69_OUT_MAXPS_HIGH5       0x05, 0x69
+#define TM6010_REQ05_R6A_OUT_MAXPS_LOW6                0x05, 0x6a
+#define TM6010_REQ05_R6B_OUT_MAXPS_HIGH6       0x05, 0x6b
+#define TM6010_REQ05_R6C_OUT_MAXPS_LOW7                0x05, 0x6c
+#define TM6010_REQ05_R6D_OUT_MAXPS_HIGH7       0x05, 0x6d
+#define TM6010_REQ05_R6E_OUT_MAXPS_LOW8                0x05, 0x6e
+#define TM6010_REQ05_R6F_OUT_MAXPS_HIGH8       0x05, 0x6f
+#define TM6010_REQ05_R70_OUT_MAXPS_LOW9                0x05, 0x70
+#define TM6010_REQ05_R71_OUT_MAXPS_HIGH9       0x05, 0x71
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW10       0x05, 0x72
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH10      0x05, 0x73
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW11       0x05, 0x74
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH11      0x05, 0x75
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW12       0x05, 0x76
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH12      0x05, 0x77
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW13       0x05, 0x78
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH13      0x05, 0x79
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW14       0x05, 0x7a
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH14      0x05, 0x7b
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW15       0x05, 0x7c
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH15      0x05, 0x7d
+#define TM6010_REQ05_R80_FIFO0                 0x05, 0x80
+#define TM6010_REQ05_R81_FIFO1                 0x05, 0x81
+#define TM6010_REQ05_R82_FIFO2                 0x05, 0x82
+#define TM6010_REQ05_R83_FIFO3                 0x05, 0x83
+#define TM6010_REQ05_R84_FIFO4                 0x05, 0x84
+#define TM6010_REQ05_R85_FIFO5                 0x05, 0x85
+#define TM6010_REQ05_R86_FIFO6                 0x05, 0x86
+#define TM6010_REQ05_R87_FIFO7                 0x05, 0x87
+#define TM6010_REQ05_R88_FIFO8                 0x05, 0x88
+#define TM6010_REQ05_R89_FIFO9                 0x05, 0x89
+#define TM6010_REQ05_R81_FIFO10                        0x05, 0x8a
+#define TM6010_REQ05_R81_FIFO11                        0x05, 0x8b
+#define TM6010_REQ05_R81_FIFO12                        0x05, 0x8c
+#define TM6010_REQ05_R81_FIFO13                        0x05, 0x8d
+#define TM6010_REQ05_R81_FIFO14                        0x05, 0x8e
+#define TM6010_REQ05_R81_FIFO15                        0x05, 0x8f
+#define TM6010_REQ05_R90_CFG_FIFO0             0x05, 0x90
+#define TM6010_REQ05_R91_CFG_FIFO1             0x05, 0x91
+#define TM6010_REQ05_R92_CFG_FIFO2             0x05, 0x92
+#define TM6010_REQ05_R93_CFG_FIFO3             0x05, 0x93
+#define TM6010_REQ05_R94_CFG_FIFO4             0x05, 0x94
+#define TM6010_REQ05_R95_CFG_FIFO5             0x05, 0x95
+#define TM6010_REQ05_R96_CFG_FIFO6             0x05, 0x96
+#define TM6010_REQ05_R97_CFG_FIFO7             0x05, 0x97
+#define TM6010_REQ05_R98_CFG_FIFO8             0x05, 0x98
+#define TM6010_REQ05_R99_CFG_FIFO9             0x05, 0x99
+#define TM6010_REQ05_R91_CFG_FIFO10            0x05, 0x9a
+#define TM6010_REQ05_R91_CFG_FIFO11            0x05, 0x9b
+#define TM6010_REQ05_R91_CFG_FIFO12            0x05, 0x9c
+#define TM6010_REQ05_R91_CFG_FIFO13            0x05, 0x9d
+#define TM6010_REQ05_R91_CFG_FIFO14            0x05, 0x9e
+#define TM6010_REQ05_R91_CFG_FIFO15            0x05, 0x9f
+#define TM6010_REQ05_RA0_CTL_FIFO0             0x05, 0xa0
+#define TM6010_REQ05_RA1_CTL_FIFO1             0x05, 0xa1
+#define TM6010_REQ05_RA2_CTL_FIFO2             0x05, 0xa2
+#define TM6010_REQ05_RA3_CTL_FIFO3             0x05, 0xa3
+#define TM6010_REQ05_RA4_CTL_FIFO4             0x05, 0xa4
+#define TM6010_REQ05_RA5_CTL_FIFO5             0x05, 0xa5
+#define TM6010_REQ05_RA6_CTL_FIFO6             0x05, 0xa6
+#define TM6010_REQ05_RA7_CTL_FIFO7             0x05, 0xa7
+#define TM6010_REQ05_RA8_CTL_FIFO8             0x05, 0xa8
+#define TM6010_REQ05_RA9_CTL_FIFO9             0x05, 0xa9
+#define TM6010_REQ05_RA1_CTL_FIFO10            0x05, 0xaa
+#define TM6010_REQ05_RA1_CTL_FIFO11            0x05, 0xab
+#define TM6010_REQ05_RA1_CTL_FIFO12            0x05, 0xac
+#define TM6010_REQ05_RA1_CTL_FIFO13            0x05, 0xad
+#define TM6010_REQ05_RA1_CTL_FIFO14            0x05, 0xae
+#define TM6010_REQ05_RA1_CTL_FIFO15            0x05, 0xaf
+#define TM6010_REQ05_RB0_BC_LOW_FIFO0          0x05, 0xb0
+#define TM6010_REQ05_RB1_BC_LOW_FIFO1          0x05, 0xb1
+#define TM6010_REQ05_RB2_BC_LOW_FIFO2          0x05, 0xb2
+#define TM6010_REQ05_RB3_BC_LOW_FIFO3          0x05, 0xb3
+#define TM6010_REQ05_RB4_BC_LOW_FIFO4          0x05, 0xb4
+#define TM6010_REQ05_RB5_BC_LOW_FIFO5          0x05, 0xb5
+#define TM6010_REQ05_RB6_BC_LOW_FIFO6          0x05, 0xb6
+#define TM6010_REQ05_RB7_BC_LOW_FIFO7          0x05, 0xb7
+#define TM6010_REQ05_RB8_BC_LOW_FIFO8          0x05, 0xb8
+#define TM6010_REQ05_RB9_BC_LOW_FIFO9          0x05, 0xb9
+#define TM6010_REQ05_RB1_BC_LOW_FIFO10         0x05, 0xba
+#define TM6010_REQ05_RB1_BC_LOW_FIFO11         0x05, 0xbb
+#define TM6010_REQ05_RB1_BC_LOW_FIFO12         0x05, 0xbc
+#define TM6010_REQ05_RB1_BC_LOW_FIFO13         0x05, 0xbd
+#define TM6010_REQ05_RB1_BC_LOW_FIFO14         0x05, 0xbe
+#define TM6010_REQ05_RB1_BC_LOW_FIFO15         0x05, 0xbf
+#define TM6010_REQ05_RC0_DATA_FIFO0            0x05, 0xc0
+#define TM6010_REQ05_RC4_DATA_FIFO1            0x05, 0xc4
+#define TM6010_REQ05_RC8_DATA_FIFO2            0x05, 0xc8
+#define TM6010_REQ05_RCC_DATA_FIFO3            0x05, 0xcc
+#define TM6010_REQ05_RD0_DATA_FIFO4            0x05, 0xd0
+#define TM6010_REQ05_RD4_DATA_FIFO5            0x05, 0xd4
+#define TM6010_REQ05_RD8_DATA_FIFO6            0x05, 0xd8
+#define TM6010_REQ05_RDC_DATA_FIFO7            0x05, 0xdc
+#define TM6010_REQ05_RE0_DATA_FIFO8            0x05, 0xe0
+#define TM6010_REQ05_RE4_DATA_FIFO9            0x05, 0xe4
+#define TM6010_REQ05_RC4_DATA_FIFO10           0x05, 0xe8
+#define TM6010_REQ05_RC4_DATA_FIFO11           0x05, 0xec
+#define TM6010_REQ05_RC4_DATA_FIFO12           0x05, 0xf0
+#define TM6010_REQ05_RC4_DATA_FIFO13           0x05, 0xf4
+#define TM6010_REQ05_RC4_DATA_FIFO14           0x05, 0xf8
+#define TM6010_REQ05_RC4_DATA_FIFO15           0x05, 0xfc
+
+/* Define TM6010 Audio decoder registers */
+/* This core available only in TM6010 */
+#define TM6010_REQ08_R00_A_VERSION             0x08, 0x00
+#define TM6010_REQ08_R01_A_INIT                        0x08, 0x01
+#define TM6010_REQ08_R02_A_FIX_GAIN_CTRL       0x08, 0x02
+#define TM6010_REQ08_R03_A_AUTO_GAIN_CTRL      0x08, 0x03
+#define TM6010_REQ08_R04_A_SIF_AMP_CTRL                0x08, 0x04
+#define TM6010_REQ08_R05_A_STANDARD_MOD                0x08, 0x05
+#define TM6010_REQ08_R06_A_SOUND_MOD           0x08, 0x06
+#define TM6010_REQ08_R07_A_LEFT_VOL            0x08, 0x07
+#define TM6010_REQ08_R08_A_RIGHT_VOL           0x08, 0x08
+#define TM6010_REQ08_R09_A_MAIN_VOL            0x08, 0x09
+#define TM6010_REQ08_R0A_A_I2S_MOD             0x08, 0x0a
+#define TM6010_REQ08_R0B_A_ASD_THRES1          0x08, 0x0b
+#define TM6010_REQ08_R0C_A_ASD_THRES2          0x08, 0x0c
+#define TM6010_REQ08_R0D_A_AMD_THRES           0x08, 0x0d
+#define TM6010_REQ08_R0E_A_MONO_THRES1         0x08, 0x0e
+#define TM6010_REQ08_R0F_A_MONO_THRES2         0x08, 0x0f
+#define TM6010_REQ08_R10_A_MUTE_THRES1         0x08, 0x10
+#define TM6010_REQ08_R11_A_MUTE_THRES2         0x08, 0x11
+#define TM6010_REQ08_R12_A_AGC_U               0x08, 0x12
+#define TM6010_REQ08_R13_A_AGC_ERR_T           0x08, 0x13
+#define TM6010_REQ08_R14_A_AGC_GAIN_INIT       0x08, 0x14
+#define TM6010_REQ08_R15_A_AGC_STEP_THR                0x08, 0x15
+#define TM6010_REQ08_R16_A_AGC_GAIN_MAX                0x08, 0x16
+#define TM6010_REQ08_R17_A_AGC_GAIN_MIN                0x08, 0x17
+#define TM6010_REQ08_R18_A_TR_CTRL             0x08, 0x18
+#define TM6010_REQ08_R19_A_FH_2FH_GAIN         0x08, 0x19
+#define TM6010_REQ08_R1A_A_NICAM_SER_MAX       0x08, 0x1a
+#define TM6010_REQ08_R1B_A_NICAM_SER_MIN       0x08, 0x1b
+#define TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT     0x08, 0x1e
+#define TM6010_REQ08_R1F_A_TEST_INTF_SEL       0x08, 0x1f
+#define TM6010_REQ08_R20_A_TEST_PIN_SEL                0x08, 0x20
+#define TM6010_REQ08_R21_A_AGC_ERR             0x08, 0x21
+#define TM6010_REQ08_R22_A_AGC_GAIN            0x08, 0x22
+#define TM6010_REQ08_R23_A_NICAM_INFO          0x08, 0x23
+#define TM6010_REQ08_R24_A_SER                 0x08, 0x24
+#define TM6010_REQ08_R25_A_C1_AMP              0x08, 0x25
+#define TM6010_REQ08_R26_A_C2_AMP              0x08, 0x26
+#define TM6010_REQ08_R27_A_NOISE_AMP           0x08, 0x27
+#define TM6010_REQ08_R28_A_AUDIO_MODE_RES      0x08, 0x28
+
+/* Define TM6010 Video ADC registers */
+#define TM6010_REQ08_RE0_ADC_REF               0x08, 0xe0
+#define TM6010_REQ08_RE1_DAC_CLMP              0x08, 0xe1
+#define TM6010_REQ08_RE2_POWER_DOWN_CTRL1      0x08, 0xe2
+#define TM6010_REQ08_RE3_ADC_IN1_SEL           0x08, 0xe3
+#define TM6010_REQ08_RE4_ADC_IN2_SEL           0x08, 0xe4
+#define TM6010_REQ08_RE5_GAIN_PARAM            0x08, 0xe5
+#define TM6010_REQ08_RE6_POWER_DOWN_CTRL2      0x08, 0xe6
+#define TM6010_REQ08_RE7_REG_GAIN_Y            0x08, 0xe7
+#define TM6010_REQ08_RE8_REG_GAIN_C            0x08, 0xe8
+#define TM6010_REQ08_RE9_BIAS_CTRL             0x08, 0xe9
+#define TM6010_REQ08_REA_BUFF_DRV_CTRL         0x08, 0xea
+#define TM6010_REQ08_REB_SIF_GAIN_CTRL         0x08, 0xeb
+#define TM6010_REQ08_REC_REVERSE_YC_CTRL       0x08, 0xec
+#define TM6010_REQ08_RED_GAIN_SEL              0x08, 0xed
+
+/* Define TM6010 Audio ADC registers */
+#define TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG   0x08, 0xf0
+#define TM6010_REQ08_RF1_AADC_POWER_DOWN       0x08, 0xf1
+#define TM6010_REQ08_RF2_LEFT_CHANNEL_VOL      0x08, 0xf2
+#define TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL     0x08, 0xf3
diff --git a/drivers/media/video/tm6000/tm6000-stds.c b/drivers/media/video/tm6000/tm6000-stds.c
new file mode 100644 (file)
index 0000000..9a4145d
--- /dev/null
@@ -0,0 +1,659 @@
+/*
+ *  tm6000-stds.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2007 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include "tm6000.h"
+#include "tm6000-regs.h"
+
+static unsigned int tm6010_a_mode;
+module_param(tm6010_a_mode, int, 0644);
+MODULE_PARM_DESC(tm6010_a_mode, "set tm6010 sif audio mode");
+
+struct tm6000_reg_settings {
+       unsigned char req;
+       unsigned char reg;
+       unsigned char value;
+};
+
+
+struct tm6000_std_settings {
+       v4l2_std_id id;
+       struct tm6000_reg_settings *common;
+};
+
+static struct tm6000_reg_settings composite_pal_m[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x04 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x20 },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_pal_nc[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x36 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_pal[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x32 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_secam[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x38 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_ntsc[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_std_settings composite_stds[] = {
+       { .id = V4L2_STD_PAL_M, .common = composite_pal_m, },
+       { .id = V4L2_STD_PAL_Nc, .common = composite_pal_nc, },
+       { .id = V4L2_STD_PAL, .common = composite_pal, },
+       { .id = V4L2_STD_SECAM, .common = composite_secam, },
+       { .id = V4L2_STD_NTSC, .common = composite_ntsc, },
+};
+
+static struct tm6000_reg_settings svideo_pal_m[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x05 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_pal_nc[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x37 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_pal[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x33 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_secam[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x39 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_ntsc[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x01 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 },
+       { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0x8b },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_std_settings svideo_stds[] = {
+       { .id = V4L2_STD_PAL_M, .common = svideo_pal_m, },
+       { .id = V4L2_STD_PAL_Nc, .common = svideo_pal_nc, },
+       { .id = V4L2_STD_PAL, .common = svideo_pal, },
+       { .id = V4L2_STD_SECAM, .common = svideo_secam, },
+       { .id = V4L2_STD_NTSC, .common = svideo_ntsc, },
+};
+
+static int tm6000_set_audio_std(struct tm6000_core *dev)
+{
+       uint8_t areg_02 = 0x04; /* GC1 Fixed gain 0dB */
+       uint8_t areg_05 = 0x01; /* Auto 4.5 = M Japan, Auto 6.5 = DK */
+       uint8_t areg_06 = 0x02; /* Auto de-emphasis, mannual channel mode */
+       uint8_t nicam_flag = 0; /* No NICAM */
+
+       if (dev->radio) {
+               tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00);
+               tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, 0x04);
+               tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00);
+               tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0x80);
+               tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, 0x0c);
+               /* set mono or stereo */
+               if (dev->amode == V4L2_TUNER_MODE_MONO)
+                       tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x00);
+               else if (dev->amode == V4L2_TUNER_MODE_STEREO)
+                       tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x02);
+               tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x18);
+               tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x0a);
+               tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x40);
+               tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe);
+               tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13);
+               tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80);
+               tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0xff);
+               return 0;
+       }
+
+       switch (tm6010_a_mode) {
+       /* auto */
+       case 0:
+               switch (dev->norm) {
+               case V4L2_STD_NTSC_M_KR:
+                       areg_05 |= 0x00;
+                       break;
+               case V4L2_STD_NTSC_M_JP:
+                       areg_05 |= 0x40;
+                       break;
+               case V4L2_STD_NTSC_M:
+               case V4L2_STD_PAL_M:
+               case V4L2_STD_PAL_N:
+                       areg_05 |= 0x20;
+                       break;
+               case V4L2_STD_PAL_Nc:
+                       areg_05 |= 0x60;
+                       break;
+               case V4L2_STD_SECAM_L:
+                       areg_05 |= 0x00;
+                       break;
+               case V4L2_STD_DK:
+                       areg_05 |= 0x10;
+                       break;
+               }
+               break;
+       /* A2 */
+       case 1:
+               switch (dev->norm) {
+               case V4L2_STD_B:
+               case V4L2_STD_GH:
+                       areg_05 = 0x05;
+                       break;
+               case V4L2_STD_DK:
+                       areg_05 = 0x09;
+                       break;
+               }
+               break;
+       /* NICAM */
+       case 2:
+               switch (dev->norm) {
+               case V4L2_STD_B:
+               case V4L2_STD_GH:
+                       areg_05 = 0x07;
+                       break;
+               case V4L2_STD_DK:
+                       areg_05 = 0x06;
+                       break;
+               case V4L2_STD_PAL_I:
+                       areg_05 = 0x08;
+                       break;
+               case V4L2_STD_SECAM_L:
+                       areg_05 = 0x0a;
+                       areg_02 = 0x02;
+                       break;
+               }
+               nicam_flag = 1;
+               break;
+       /* other */
+       case 3:
+               switch (dev->norm) {
+               /* DK3_A2 */
+               case V4L2_STD_DK:
+                       areg_05 = 0x0b;
+                       break;
+               /* Korea */
+               case V4L2_STD_NTSC_M_KR:
+                       areg_05 = 0x04;
+                       break;
+               /* EIAJ */
+               case V4L2_STD_NTSC_M_JP:
+                       areg_05 = 0x03;
+                       break;
+               default:
+                       areg_05 = 0x02;
+                       break;
+               }
+               break;
+       }
+
+       tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00);
+       tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, areg_02);
+       tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00);
+       tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0xa0);
+       tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, areg_05);
+       tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, areg_06);
+       tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, 0x00);
+       tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, 0x00);
+       tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x08);
+       tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, 0x91);
+       tm6000_set_reg(dev, TM6010_REQ08_R0B_A_ASD_THRES1, 0x20);
+       tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x12);
+       tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x20);
+       tm6000_set_reg(dev, TM6010_REQ08_R0E_A_MONO_THRES1, 0xf0);
+       tm6000_set_reg(dev, TM6010_REQ08_R0F_A_MONO_THRES2, 0x80);
+       tm6000_set_reg(dev, TM6010_REQ08_R10_A_MUTE_THRES1, 0xc0);
+       tm6000_set_reg(dev, TM6010_REQ08_R11_A_MUTE_THRES2, 0x80);
+       tm6000_set_reg(dev, TM6010_REQ08_R12_A_AGC_U, 0x12);
+       tm6000_set_reg(dev, TM6010_REQ08_R13_A_AGC_ERR_T, 0xfe);
+       tm6000_set_reg(dev, TM6010_REQ08_R14_A_AGC_GAIN_INIT, 0x20);
+       tm6000_set_reg(dev, TM6010_REQ08_R15_A_AGC_STEP_THR, 0x14);
+       tm6000_set_reg(dev, TM6010_REQ08_R16_A_AGC_GAIN_MAX, 0xfe);
+       tm6000_set_reg(dev, TM6010_REQ08_R17_A_AGC_GAIN_MIN, 0x01);
+       tm6000_set_reg(dev, TM6010_REQ08_R18_A_TR_CTRL, 0xa0);
+       tm6000_set_reg(dev, TM6010_REQ08_R19_A_FH_2FH_GAIN, 0x32);
+       tm6000_set_reg(dev, TM6010_REQ08_R1A_A_NICAM_SER_MAX, 0x64);
+       tm6000_set_reg(dev, TM6010_REQ08_R1B_A_NICAM_SER_MIN, 0x20);
+       tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1c, 0x00);
+       tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1d, 0x00);
+       tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13);
+       tm6000_set_reg(dev, TM6010_REQ08_R1F_A_TEST_INTF_SEL, 0x00);
+       tm6000_set_reg(dev, TM6010_REQ08_R20_A_TEST_PIN_SEL, 0x00);
+       tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80);
+
+       return 0;
+}
+
+void tm6000_get_std_res(struct tm6000_core *dev)
+{
+       /* Currently, those are the only supported resoltions */
+       if (dev->norm & V4L2_STD_525_60)
+               dev->height = 480;
+       else
+               dev->height = 576;
+
+       dev->width = 720;
+}
+
+static int tm6000_load_std(struct tm6000_core *dev, struct tm6000_reg_settings *set)
+{
+       int i, rc;
+
+       /* Load board's initialization table */
+       for (i = 0; set[i].req; i++) {
+               rc = tm6000_set_reg(dev, set[i].req, set[i].reg, set[i].value);
+               if (rc < 0) {
+                       printk(KERN_ERR "Error %i while setting "
+                              "req %d, reg %d to value %d\n",
+                              rc, set[i].req, set[i].reg, set[i].value);
+                       return rc;
+               }
+       }
+
+       return 0;
+}
+
+int tm6000_set_standard(struct tm6000_core *dev)
+{
+       struct tm6000_input *input;
+       int i, rc = 0;
+       u8 reg_07_fe = 0x8a;
+       u8 reg_08_f1 = 0xfc;
+       u8 reg_08_e2 = 0xf0;
+       u8 reg_08_e6 = 0x0f;
+
+       tm6000_get_std_res(dev);
+
+       if (!dev->radio)
+               input = &dev->vinput[dev->input];
+       else
+               input = &dev->rinput;
+
+       if (dev->dev_type == TM6010) {
+               switch (input->vmux) {
+               case TM6000_VMUX_VIDEO_A:
+                       tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4);
+                       tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1);
+                       tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0);
+                       tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
+                       tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8);
+                       reg_07_fe |= 0x01;
+                       break;
+               case TM6000_VMUX_VIDEO_B:
+                       tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8);
+                       tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1);
+                       tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0);
+                       tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
+                       tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8);
+                       reg_07_fe |= 0x01;
+                       break;
+               case TM6000_VMUX_VIDEO_AB:
+                       tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc);
+                       tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8);
+                       reg_08_e6 = 0x00;
+                       tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2);
+                       tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0);
+                       tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
+                       tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe0);
+                       break;
+               default:
+                       break;
+               }
+               switch (input->amux) {
+               case TM6000_AMUX_ADC1:
+                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+                               0x00, 0x0f);
+                       break;
+               case TM6000_AMUX_ADC2:
+                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+                               0x08, 0x0f);
+                       break;
+               case TM6000_AMUX_SIF1:
+                       reg_08_e2 |= 0x02;
+                       reg_08_e6 = 0x08;
+                       reg_07_fe |= 0x40;
+                       reg_08_f1 |= 0x02;
+                       tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3);
+                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+                               0x02, 0x0f);
+                       break;
+               case TM6000_AMUX_SIF2:
+                       reg_08_e2 |= 0x02;
+                       reg_08_e6 = 0x08;
+                       reg_07_fe |= 0x40;
+                       reg_08_f1 |= 0x02;
+                       tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf7);
+                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+                               0x02, 0x0f);
+                       break;
+               default:
+                       break;
+               }
+               tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, reg_08_e2);
+               tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, reg_08_e6);
+               tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, reg_08_f1);
+               tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, reg_07_fe);
+       } else {
+               switch (input->vmux) {
+               case TM6000_VMUX_VIDEO_A:
+                       tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10);
+                       tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00);
+                       tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f);
+                       tm6000_set_reg(dev,
+                           REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0);
+                       break;
+               case TM6000_VMUX_VIDEO_B:
+                       tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x00);
+                       tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00);
+                       tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f);
+                       tm6000_set_reg(dev,
+                           REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0);
+                       break;
+               case TM6000_VMUX_VIDEO_AB:
+                       tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10);
+                       tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x10);
+                       tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00);
+                       tm6000_set_reg(dev,
+                           REQ_03_SET_GET_MCU_PIN, input->v_gpio, 1);
+                       break;
+               default:
+                       break;
+               }
+               switch (input->amux) {
+               case TM6000_AMUX_ADC1:
+                       tm6000_set_reg_mask(dev,
+                               TM6000_REQ07_REB_VADC_AADC_MODE, 0x00, 0x0f);
+                       break;
+               case TM6000_AMUX_ADC2:
+                       tm6000_set_reg_mask(dev,
+                               TM6000_REQ07_REB_VADC_AADC_MODE, 0x04, 0x0f);
+                       break;
+               default:
+                       break;
+               }
+       }
+       if (input->type == TM6000_INPUT_SVIDEO) {
+               for (i = 0; i < ARRAY_SIZE(svideo_stds); i++) {
+                       if (dev->norm & svideo_stds[i].id) {
+                               rc = tm6000_load_std(dev, svideo_stds[i].common);
+                               goto ret;
+                       }
+               }
+               return -EINVAL;
+       } else {
+               for (i = 0; i < ARRAY_SIZE(composite_stds); i++) {
+                       if (dev->norm & composite_stds[i].id) {
+                               rc = tm6000_load_std(dev, composite_stds[i].common);
+                               goto ret;
+                       }
+               }
+               return -EINVAL;
+       }
+
+ret:
+       if (rc < 0)
+               return rc;
+
+       if ((dev->dev_type == TM6010) &&
+           ((input->amux == TM6000_AMUX_SIF1) ||
+           (input->amux == TM6000_AMUX_SIF2)))
+               tm6000_set_audio_std(dev);
+
+       msleep(40);
+
+       return 0;
+}
diff --git a/drivers/media/video/tm6000/tm6000-usb-isoc.h b/drivers/media/video/tm6000/tm6000-usb-isoc.h
new file mode 100644 (file)
index 0000000..99d15a5
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  tm6000-buf.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/videodev2.h>
+
+#define TM6000_URB_MSG_LEN 180
+
+struct usb_isoc_ctl {
+               /* max packet size of isoc transaction */
+       int                             max_pkt_size;
+
+               /* number of allocated urbs */
+       int                             num_bufs;
+
+               /* urb for isoc transfers */
+       struct urb                      **urb;
+
+               /* transfer buffers for isoc transfer */
+       char                            **transfer_buffer;
+
+               /* Last buffer command and region */
+       u8                              cmd;
+       int                             pos, size, pktsize;
+
+               /* Last field: ODD or EVEN? */
+       int                             vfield, field;
+
+               /* Stores incomplete commands */
+       u32                             tmp_buf;
+       int                             tmp_buf_len;
+
+               /* Stores already requested buffers */
+       struct tm6000_buffer            *buf;
+};
diff --git a/drivers/media/video/tm6000/tm6000-video.c b/drivers/media/video/tm6000/tm6000-video.c
new file mode 100644 (file)
index 0000000..1e5ace0
--- /dev/null
@@ -0,0 +1,1813 @@
+/*
+ *   tm6000-video.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ *     - Fixed module load/unload
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/random.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-ioctl.h>
+#include <media/tuner.h>
+#include <linux/interrupt.h>
+#include <linux/kthread.h>
+#include <linux/highmem.h>
+#include <linux/freezer.h>
+
+#include "tm6000-regs.h"
+#include "tm6000.h"
+
+#define BUFFER_TIMEOUT     msecs_to_jiffies(2000)  /* 2 seconds */
+
+/* Limits minimum and default number of buffers */
+#define TM6000_MIN_BUF 4
+#define TM6000_DEF_BUF 8
+
+#define TM6000_MAX_ISO_PACKETS 46      /* Max number of ISO packets */
+
+/* Declare static vars that will be used as parameters */
+static unsigned int vid_limit = 16;    /* Video memory limit, in Mb */
+static int video_nr = -1;              /* /dev/videoN, -1 for autodetect */
+static int radio_nr = -1;              /* /dev/radioN, -1 for autodetect */
+
+/* Debug level */
+int tm6000_debug;
+EXPORT_SYMBOL_GPL(tm6000_debug);
+
+static const struct v4l2_queryctrl no_ctrl = {
+       .name  = "42",
+       .flags = V4L2_CTRL_FLAG_DISABLED,
+};
+
+/* supported controls */
+static struct v4l2_queryctrl tm6000_qctrl[] = {
+       {
+               .id            = V4L2_CID_BRIGHTNESS,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Brightness",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 1,
+               .default_value = 54,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_CONTRAST,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Contrast",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 0x1,
+               .default_value = 119,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_SATURATION,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Saturation",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 0x1,
+               .default_value = 112,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_HUE,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Hue",
+               .minimum       = -128,
+               .maximum       = 127,
+               .step          = 0x1,
+               .default_value = 0,
+               .flags         = 0,
+       },
+               /* --- audio --- */
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       }, {
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .name          = "Volume",
+               .minimum       = -15,
+               .maximum       = 15,
+               .step          = 1,
+               .default_value = 0,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       }
+};
+
+static const unsigned int CTRLS = ARRAY_SIZE(tm6000_qctrl);
+static int qctl_regs[ARRAY_SIZE(tm6000_qctrl)];
+
+static struct tm6000_fmt format[] = {
+       {
+               .name     = "4:2:2, packed, YVY2",
+               .fourcc   = V4L2_PIX_FMT_YUYV,
+               .depth    = 16,
+       }, {
+               .name     = "4:2:2, packed, UYVY",
+               .fourcc   = V4L2_PIX_FMT_UYVY,
+               .depth    = 16,
+       }, {
+               .name     = "A/V + VBI mux packet",
+               .fourcc   = V4L2_PIX_FMT_TM6000,
+               .depth    = 16,
+       }
+};
+
+static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id)
+{
+       unsigned int i;
+
+       for (i = 0; i < CTRLS; i++)
+               if (tm6000_qctrl[i].id == id)
+                       return tm6000_qctrl+i;
+       return NULL;
+}
+
+/* ------------------------------------------------------------------
+ *     DMA and thread functions
+ * ------------------------------------------------------------------
+ */
+
+#define norm_maxw(a) 720
+#define norm_maxh(a) 576
+
+#define norm_minw(a) norm_maxw(a)
+#define norm_minh(a) norm_maxh(a)
+
+/*
+ * video-buf generic routine to get the next available buffer
+ */
+static inline void get_next_buf(struct tm6000_dmaqueue *dma_q,
+                              struct tm6000_buffer   **buf)
+{
+       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+       char *outp;
+
+       if (list_empty(&dma_q->active)) {
+               dprintk(dev, V4L2_DEBUG_QUEUE, "No active queue to serve\n");
+               *buf = NULL;
+               return;
+       }
+
+       *buf = list_entry(dma_q->active.next,
+                       struct tm6000_buffer, vb.queue);
+
+       /* Cleans up buffer - Useful for testing for frame/URB loss */
+       outp = videobuf_to_vmalloc(&(*buf)->vb);
+
+       return;
+}
+
+/*
+ * Announces that a buffer were filled and request the next
+ */
+static inline void buffer_filled(struct tm6000_core *dev,
+                                struct tm6000_dmaqueue *dma_q,
+                                struct tm6000_buffer *buf)
+{
+       /* Advice that buffer was filled */
+       dprintk(dev, V4L2_DEBUG_ISOC, "[%p/%d] wakeup\n", buf, buf->vb.i);
+       buf->vb.state = VIDEOBUF_DONE;
+       buf->vb.field_count++;
+       do_gettimeofday(&buf->vb.ts);
+
+       list_del(&buf->vb.queue);
+       wake_up(&buf->vb.done);
+}
+
+/*
+ * Identify the tm5600/6000 buffer header type and properly handles
+ */
+static int copy_streams(u8 *data, unsigned long len,
+                       struct urb *urb)
+{
+       struct tm6000_dmaqueue  *dma_q = urb->context;
+       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+       u8 *ptr = data, *endp = data+len, c;
+       unsigned long header = 0;
+       int rc = 0;
+       unsigned int cmd, cpysize, pktsize, size, field, block, line, pos = 0;
+       struct tm6000_buffer *vbuf = NULL;
+       char *voutp = NULL;
+       unsigned int linewidth;
+
+       if (!dev->radio) {
+               /* get video buffer */
+               get_next_buf(dma_q, &vbuf);
+
+               if (!vbuf)
+                       return rc;
+               voutp = videobuf_to_vmalloc(&vbuf->vb);
+
+               if (!voutp)
+                       return 0;
+       }
+
+       for (ptr = data; ptr < endp;) {
+               if (!dev->isoc_ctl.cmd) {
+                       /* Header */
+                       if (dev->isoc_ctl.tmp_buf_len > 0) {
+                               /* from last urb or packet */
+                               header = dev->isoc_ctl.tmp_buf;
+                               if (4 - dev->isoc_ctl.tmp_buf_len > 0) {
+                                       memcpy((u8 *)&header +
+                                               dev->isoc_ctl.tmp_buf_len,
+                                               ptr,
+                                               4 - dev->isoc_ctl.tmp_buf_len);
+                                       ptr += 4 - dev->isoc_ctl.tmp_buf_len;
+                               }
+                               dev->isoc_ctl.tmp_buf_len = 0;
+                       } else {
+                               if (ptr + 3 >= endp) {
+                                       /* have incomplete header */
+                                       dev->isoc_ctl.tmp_buf_len = endp - ptr;
+                                       memcpy(&dev->isoc_ctl.tmp_buf, ptr,
+                                               dev->isoc_ctl.tmp_buf_len);
+                                       return rc;
+                               }
+                               /* Seek for sync */
+                               for (; ptr < endp - 3; ptr++) {
+                                       if (*(ptr + 3) == 0x47)
+                                               break;
+                               }
+                               /* Get message header */
+                               header = *(unsigned long *)ptr;
+                               ptr += 4;
+                       }
+
+                       /* split the header fields */
+                       c = (header >> 24) & 0xff;
+                       size = ((header & 0x7e) << 1);
+                       if (size > 0)
+                               size -= 4;
+                       block = (header >> 7) & 0xf;
+                       field = (header >> 11) & 0x1;
+                       line  = (header >> 12) & 0x1ff;
+                       cmd   = (header >> 21) & 0x7;
+                       /* Validates haeder fields */
+                       if (size > TM6000_URB_MSG_LEN)
+                               size = TM6000_URB_MSG_LEN;
+                       pktsize = TM6000_URB_MSG_LEN;
+                       /*
+                        * calculate position in buffer and change the buffer
+                        */
+                       switch (cmd) {
+                       case TM6000_URB_MSG_VIDEO:
+                               if (!dev->radio) {
+                                       if ((dev->isoc_ctl.vfield != field) &&
+                                               (field == 1)) {
+                                               /*
+                                                * Announces that a new buffer
+                                                * were filled
+                                                */
+                                               buffer_filled(dev, dma_q, vbuf);
+                                               dprintk(dev, V4L2_DEBUG_ISOC,
+                                                       "new buffer filled\n");
+                                               get_next_buf(dma_q, &vbuf);
+                                               if (!vbuf)
+                                                       return rc;
+                                               voutp = videobuf_to_vmalloc(&vbuf->vb);
+                                               if (!voutp)
+                                                       return rc;
+                                               memset(voutp, 0, vbuf->vb.size);
+                                       }
+                                       linewidth = vbuf->vb.width << 1;
+                                       pos = ((line << 1) - field - 1) *
+                                       linewidth + block * TM6000_URB_MSG_LEN;
+                                       /* Don't allow to write out of the buffer */
+                                       if (pos + size > vbuf->vb.size)
+                                               cmd = TM6000_URB_MSG_ERR;
+                                       dev->isoc_ctl.vfield = field;
+                               }
+                               break;
+                       case TM6000_URB_MSG_VBI:
+                               break;
+                       case TM6000_URB_MSG_AUDIO:
+                       case TM6000_URB_MSG_PTS:
+                               size = pktsize; /* Size is always 180 bytes */
+                               break;
+                       }
+               } else {
+                       /* Continue the last copy */
+                       cmd = dev->isoc_ctl.cmd;
+                       size = dev->isoc_ctl.size;
+                       pos = dev->isoc_ctl.pos;
+                       pktsize = dev->isoc_ctl.pktsize;
+                       field = dev->isoc_ctl.field;
+               }
+               cpysize = (endp - ptr > size) ? size : endp - ptr;
+               if (cpysize) {
+                       /* copy data in different buffers */
+                       switch (cmd) {
+                       case TM6000_URB_MSG_VIDEO:
+                               /* Fills video buffer */
+                               if (vbuf)
+                                       memcpy(&voutp[pos], ptr, cpysize);
+                               break;
+                       case TM6000_URB_MSG_AUDIO: {
+                               int i;
+                               for (i = 0; i < cpysize; i += 2)
+                                       swab16s((u16 *)(ptr + i));
+
+                               tm6000_call_fillbuf(dev, TM6000_AUDIO, ptr, cpysize);
+                               break;
+                       }
+                       case TM6000_URB_MSG_VBI:
+                               /* Need some code to copy vbi buffer */
+                               break;
+                       case TM6000_URB_MSG_PTS: {
+                               /* Need some code to copy pts */
+                               u32 pts;
+                               pts = *(u32 *)ptr;
+                               dprintk(dev, V4L2_DEBUG_ISOC, "field %d, PTS %x",
+                                       field, pts);
+                               break;
+                       }
+                       }
+               }
+               if (ptr + pktsize > endp) {
+                       /*
+                        * End of URB packet, but cmd processing is not
+                        * complete. Preserve the state for a next packet
+                        */
+                       dev->isoc_ctl.pos = pos + cpysize;
+                       dev->isoc_ctl.size = size - cpysize;
+                       dev->isoc_ctl.cmd = cmd;
+                       dev->isoc_ctl.field = field;
+                       dev->isoc_ctl.pktsize = pktsize - (endp - ptr);
+                       ptr += endp - ptr;
+               } else {
+                       dev->isoc_ctl.cmd = 0;
+                       ptr += pktsize;
+               }
+       }
+       return 0;
+}
+
+/*
+ * Identify the tm5600/6000 buffer header type and properly handles
+ */
+static int copy_multiplexed(u8 *ptr, unsigned long len,
+                       struct urb *urb)
+{
+       struct tm6000_dmaqueue  *dma_q = urb->context;
+       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+       unsigned int pos = dev->isoc_ctl.pos, cpysize;
+       int rc = 1;
+       struct tm6000_buffer *buf;
+       char *outp = NULL;
+
+       get_next_buf(dma_q, &buf);
+       if (buf)
+               outp = videobuf_to_vmalloc(&buf->vb);
+
+       if (!outp)
+               return 0;
+
+       while (len > 0) {
+               cpysize = min(len, buf->vb.size-pos);
+               memcpy(&outp[pos], ptr, cpysize);
+               pos += cpysize;
+               ptr += cpysize;
+               len -= cpysize;
+               if (pos >= buf->vb.size) {
+                       pos = 0;
+                       /* Announces that a new buffer were filled */
+                       buffer_filled(dev, dma_q, buf);
+                       dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n");
+                       get_next_buf(dma_q, &buf);
+                       if (!buf)
+                               break;
+                       outp = videobuf_to_vmalloc(&(buf->vb));
+                       if (!outp)
+                               return rc;
+                       pos = 0;
+               }
+       }
+
+       dev->isoc_ctl.pos = pos;
+       return rc;
+}
+
+static inline void print_err_status(struct tm6000_core *dev,
+                                    int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+       if (packet < 0) {
+               dprintk(dev, V4L2_DEBUG_QUEUE, "URB status %d [%s].\n",
+                       status, errmsg);
+       } else {
+               dprintk(dev, V4L2_DEBUG_QUEUE, "URB packet %d, status %d [%s].\n",
+                       packet, status, errmsg);
+       }
+}
+
+
+/*
+ * Controls the isoc copy of each urb packet
+ */
+static inline int tm6000_isoc_copy(struct urb *urb)
+{
+       struct tm6000_dmaqueue  *dma_q = urb->context;
+       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+       int i, len = 0, rc = 1, status;
+       char *p;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               return 0;
+       }
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               status = urb->iso_frame_desc[i].status;
+
+               if (status < 0) {
+                       print_err_status(dev, i, status);
+                       continue;
+               }
+
+               len = urb->iso_frame_desc[i].actual_length;
+
+               if (len > 0) {
+                       p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+                       if (!urb->iso_frame_desc[i].status) {
+                               if ((dev->fourcc) == V4L2_PIX_FMT_TM6000) {
+                                       rc = copy_multiplexed(p, len, urb);
+                                       if (rc <= 0)
+                                               return rc;
+                               } else {
+                                       copy_streams(p, len, urb);
+                               }
+                       }
+               }
+       }
+       return rc;
+}
+
+/* ------------------------------------------------------------------
+ *     URB control
+ * ------------------------------------------------------------------
+ */
+
+/*
+ * IRQ callback, called by URB callback
+ */
+static void tm6000_irq_callback(struct urb *urb)
+{
+       struct tm6000_dmaqueue  *dma_q = urb->context;
+       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+       int i;
+
+       switch (urb->status) {
+       case 0:
+       case -ETIMEDOUT:
+               break;
+
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+
+       default:
+               tm6000_err("urb completion error %d.\n", urb->status);
+               break;
+       }
+
+       spin_lock(&dev->slock);
+       tm6000_isoc_copy(urb);
+       spin_unlock(&dev->slock);
+
+       /* Reset urb buffers */
+       for (i = 0; i < urb->number_of_packets; i++) {
+               urb->iso_frame_desc[i].status = 0;
+               urb->iso_frame_desc[i].actual_length = 0;
+       }
+
+       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (urb->status)
+               tm6000_err("urb resubmit failed (error=%i)\n",
+                       urb->status);
+}
+
+/*
+ * Stop and Deallocate URBs
+ */
+static void tm6000_uninit_isoc(struct tm6000_core *dev)
+{
+       struct urb *urb;
+       int i;
+
+       dev->isoc_ctl.buf = NULL;
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+               urb = dev->isoc_ctl.urb[i];
+               if (urb) {
+                       usb_kill_urb(urb);
+                       usb_unlink_urb(urb);
+                       if (dev->isoc_ctl.transfer_buffer[i]) {
+                               usb_free_coherent(dev->udev,
+                                               urb->transfer_buffer_length,
+                                               dev->isoc_ctl.transfer_buffer[i],
+                                               urb->transfer_dma);
+                       }
+                       usb_free_urb(urb);
+                       dev->isoc_ctl.urb[i] = NULL;
+               }
+               dev->isoc_ctl.transfer_buffer[i] = NULL;
+       }
+
+       kfree(dev->isoc_ctl.urb);
+       kfree(dev->isoc_ctl.transfer_buffer);
+
+       dev->isoc_ctl.urb = NULL;
+       dev->isoc_ctl.transfer_buffer = NULL;
+       dev->isoc_ctl.num_bufs = 0;
+}
+
+/*
+ * Allocate URBs and start IRQ
+ */
+static int tm6000_prepare_isoc(struct tm6000_core *dev)
+{
+       struct tm6000_dmaqueue *dma_q = &dev->vidq;
+       int i, j, sb_size, pipe, size, max_packets, num_bufs = 8;
+       struct urb *urb;
+
+       /* De-allocates all pending stuff */
+       tm6000_uninit_isoc(dev);
+       /* Stop interrupt USB pipe */
+       tm6000_ir_int_stop(dev);
+
+       usb_set_interface(dev->udev,
+                         dev->isoc_in.bInterfaceNumber,
+                         dev->isoc_in.bAlternateSetting);
+
+       /* Start interrupt USB pipe */
+       tm6000_ir_int_start(dev);
+
+       pipe = usb_rcvisocpipe(dev->udev,
+                              dev->isoc_in.endp->desc.bEndpointAddress &
+                              USB_ENDPOINT_NUMBER_MASK);
+
+       size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
+
+       if (size > dev->isoc_in.maxsize)
+               size = dev->isoc_in.maxsize;
+
+       dev->isoc_ctl.max_pkt_size = size;
+
+       max_packets = TM6000_MAX_ISO_PACKETS;
+       sb_size = max_packets * size;
+
+       dev->isoc_ctl.num_bufs = num_bufs;
+
+       dev->isoc_ctl.urb = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
+       if (!dev->isoc_ctl.urb) {
+               tm6000_err("cannot alloc memory for usb buffers\n");
+               return -ENOMEM;
+       }
+
+       dev->isoc_ctl.transfer_buffer = kmalloc(sizeof(void *)*num_bufs,
+                                  GFP_KERNEL);
+       if (!dev->isoc_ctl.transfer_buffer) {
+               tm6000_err("cannot allocate memory for usbtransfer\n");
+               kfree(dev->isoc_ctl.urb);
+               return -ENOMEM;
+       }
+
+       dprintk(dev, V4L2_DEBUG_QUEUE, "Allocating %d x %d packets"
+                   " (%d bytes) of %d bytes each to handle %u size\n",
+                   max_packets, num_bufs, sb_size,
+                   dev->isoc_in.maxsize, size);
+
+       /* allocate urbs and transfer buffers */
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+               urb = usb_alloc_urb(max_packets, GFP_KERNEL);
+               if (!urb) {
+                       tm6000_err("cannot alloc isoc_ctl.urb %i\n", i);
+                       tm6000_uninit_isoc(dev);
+                       usb_free_urb(urb);
+                       return -ENOMEM;
+               }
+               dev->isoc_ctl.urb[i] = urb;
+
+               dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev,
+                       sb_size, GFP_KERNEL, &urb->transfer_dma);
+               if (!dev->isoc_ctl.transfer_buffer[i]) {
+                       tm6000_err("unable to allocate %i bytes for transfer"
+                                       " buffer %i%s\n",
+                                       sb_size, i,
+                                       in_interrupt() ? " while in int" : "");
+                       tm6000_uninit_isoc(dev);
+                       return -ENOMEM;
+               }
+               memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
+
+               usb_fill_bulk_urb(urb, dev->udev, pipe,
+                                 dev->isoc_ctl.transfer_buffer[i], sb_size,
+                                 tm6000_irq_callback, dma_q);
+               urb->interval = dev->isoc_in.endp->desc.bInterval;
+               urb->number_of_packets = max_packets;
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+
+               for (j = 0; j < max_packets; j++) {
+                       urb->iso_frame_desc[j].offset = size * j;
+                       urb->iso_frame_desc[j].length = size;
+               }
+       }
+
+       return 0;
+}
+
+static int tm6000_start_thread(struct tm6000_core *dev)
+{
+       struct tm6000_dmaqueue *dma_q = &dev->vidq;
+       int i;
+
+       dma_q->frame = 0;
+       dma_q->ini_jiffies = jiffies;
+
+       init_waitqueue_head(&dma_q->wq);
+
+       /* submit urbs and enables IRQ */
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+               int rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
+               if (rc) {
+                       tm6000_err("submit of urb %i failed (error=%i)\n", i,
+                                  rc);
+                       tm6000_uninit_isoc(dev);
+                       return rc;
+               }
+       }
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------
+ *     Videobuf operations
+ * ------------------------------------------------------------------
+ */
+
+static int
+buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
+{
+       struct tm6000_fh *fh = vq->priv_data;
+
+       *size = fh->fmt->depth * fh->width * fh->height >> 3;
+       if (0 == *count)
+               *count = TM6000_DEF_BUF;
+
+       if (*count < TM6000_MIN_BUF)
+               *count = TM6000_MIN_BUF;
+
+       while (*size * *count > vid_limit * 1024 * 1024)
+               (*count)--;
+
+       return 0;
+}
+
+static void free_buffer(struct videobuf_queue *vq, struct tm6000_buffer *buf)
+{
+       struct tm6000_fh *fh = vq->priv_data;
+       struct tm6000_core   *dev = fh->dev;
+       unsigned long flags;
+
+       if (in_interrupt())
+               BUG();
+
+       /* We used to wait for the buffer to finish here, but this didn't work
+          because, as we were keeping the state as VIDEOBUF_QUEUED,
+          videobuf_queue_cancel marked it as finished for us.
+          (Also, it could wedge forever if the hardware was misconfigured.)
+
+          This should be safe; by the time we get here, the buffer isn't
+          queued anymore. If we ever start marking the buffers as
+          VIDEOBUF_ACTIVE, it won't be, though.
+       */
+       spin_lock_irqsave(&dev->slock, flags);
+       if (dev->isoc_ctl.buf == buf)
+               dev->isoc_ctl.buf = NULL;
+       spin_unlock_irqrestore(&dev->slock, flags);
+
+       videobuf_vmalloc_free(&buf->vb);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int
+buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+                                               enum v4l2_field field)
+{
+       struct tm6000_fh     *fh  = vq->priv_data;
+       struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb);
+       struct tm6000_core   *dev = fh->dev;
+       int rc = 0;
+
+       BUG_ON(NULL == fh->fmt);
+
+
+       /* FIXME: It assumes depth=2 */
+       /* The only currently supported format is 16 bits/pixel */
+       buf->vb.size = fh->fmt->depth*fh->width*fh->height >> 3;
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+               return -EINVAL;
+
+       if (buf->fmt       != fh->fmt    ||
+           buf->vb.width  != fh->width  ||
+           buf->vb.height != fh->height ||
+           buf->vb.field  != field) {
+               buf->fmt       = fh->fmt;
+               buf->vb.width  = fh->width;
+               buf->vb.height = fh->height;
+               buf->vb.field  = field;
+               buf->vb.state = VIDEOBUF_NEEDS_INIT;
+       }
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               rc = videobuf_iolock(vq, &buf->vb, NULL);
+               if (rc != 0)
+                       goto fail;
+       }
+
+       if (!dev->isoc_ctl.num_bufs) {
+               rc = tm6000_prepare_isoc(dev);
+               if (rc < 0)
+                       goto fail;
+
+               rc = tm6000_start_thread(dev);
+               if (rc < 0)
+                       goto fail;
+
+       }
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+fail:
+       free_buffer(vq, buf);
+       return rc;
+}
+
+static void
+buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct tm6000_buffer    *buf     = container_of(vb, struct tm6000_buffer, vb);
+       struct tm6000_fh        *fh      = vq->priv_data;
+       struct tm6000_core      *dev     = fh->dev;
+       struct tm6000_dmaqueue  *vidq    = &dev->vidq;
+
+       buf->vb.state = VIDEOBUF_QUEUED;
+       list_add_tail(&buf->vb.queue, &vidq->active);
+}
+
+static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct tm6000_buffer   *buf  = container_of(vb, struct tm6000_buffer, vb);
+
+       free_buffer(vq, buf);
+}
+
+static struct videobuf_queue_ops tm6000_video_qops = {
+       .buf_setup      = buffer_setup,
+       .buf_prepare    = buffer_prepare,
+       .buf_queue      = buffer_queue,
+       .buf_release    = buffer_release,
+};
+
+/* ------------------------------------------------------------------
+ *     IOCTL handling
+ * ------------------------------------------------------------------
+ */
+
+static bool is_res_read(struct tm6000_core *dev, struct tm6000_fh *fh)
+{
+       /* Is the current fh handling it? if so, that's OK */
+       if (dev->resources == fh && dev->is_res_read)
+               return true;
+
+       return false;
+}
+
+static bool is_res_streaming(struct tm6000_core *dev, struct tm6000_fh *fh)
+{
+       /* Is the current fh handling it? if so, that's OK */
+       if (dev->resources == fh)
+               return true;
+
+       return false;
+}
+
+static bool res_get(struct tm6000_core *dev, struct tm6000_fh *fh,
+                  bool is_res_read)
+{
+       /* Is the current fh handling it? if so, that's OK */
+       if (dev->resources == fh && dev->is_res_read == is_res_read)
+               return true;
+
+       /* is it free? */
+       if (dev->resources)
+               return false;
+
+       /* grab it */
+       dev->resources = fh;
+       dev->is_res_read = is_res_read;
+       dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: get\n");
+       return true;
+}
+
+static void res_free(struct tm6000_core *dev, struct tm6000_fh *fh)
+{
+       /* Is the current fh handling it? if so, that's OK */
+       if (dev->resources != fh)
+               return;
+
+       dev->resources = NULL;
+       dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: put\n");
+}
+
+/* ------------------------------------------------------------------
+ *     IOCTL vidioc handling
+ * ------------------------------------------------------------------
+ */
+static int vidioc_querycap(struct file *file, void  *priv,
+                                       struct v4l2_capability *cap)
+{
+       struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
+
+       strlcpy(cap->driver, "tm6000", sizeof(cap->driver));
+       strlcpy(cap->card, "Trident TVMaster TM5600/6000/6010", sizeof(cap->card));
+       cap->version = TM6000_VERSION;
+       cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
+                               V4L2_CAP_STREAMING     |
+                               V4L2_CAP_AUDIO         |
+                               V4L2_CAP_READWRITE;
+
+       if (dev->tuner_type != TUNER_ABSENT)
+               cap->capabilities |= V4L2_CAP_TUNER;
+
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+       if (unlikely(f->index >= ARRAY_SIZE(format)))
+               return -EINVAL;
+
+       strlcpy(f->description, format[f->index].name, sizeof(f->description));
+       f->pixelformat = format[f->index].fourcc;
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct tm6000_fh  *fh = priv;
+
+       f->fmt.pix.width        = fh->width;
+       f->fmt.pix.height       = fh->height;
+       f->fmt.pix.field        = fh->vb_vidq.field;
+       f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fh->fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return 0;
+}
+
+static struct tm6000_fmt *format_by_fourcc(unsigned int fourcc)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(format); i++)
+               if (format[i].fourcc == fourcc)
+                       return format+i;
+       return NULL;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                       struct v4l2_format *f)
+{
+       struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
+       struct tm6000_fmt *fmt;
+       enum v4l2_field field;
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       if (NULL == fmt) {
+               dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Fourcc format (0x%08x)"
+                               " invalid.\n", f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       field = f->fmt.pix.field;
+
+       if (field == V4L2_FIELD_ANY)
+               field = V4L2_FIELD_SEQ_TB;
+       else if (V4L2_FIELD_INTERLACED != field) {
+               dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Field type invalid.\n");
+               return -EINVAL;
+       }
+
+       tm6000_get_std_res(dev);
+
+       f->fmt.pix.width  = dev->width;
+       f->fmt.pix.height = dev->height;
+
+       f->fmt.pix.width &= ~0x01;
+
+       f->fmt.pix.field = field;
+
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return 0;
+}
+
+/*FIXME: This seems to be generic enough to be at videodev2 */
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct tm6000_fh  *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+       int ret = vidioc_try_fmt_vid_cap(file, fh, f);
+       if (ret < 0)
+               return ret;
+
+       fh->fmt           = format_by_fourcc(f->fmt.pix.pixelformat);
+       fh->width         = f->fmt.pix.width;
+       fh->height        = f->fmt.pix.height;
+       fh->vb_vidq.field = f->fmt.pix.field;
+       fh->type          = f->type;
+
+       dev->fourcc       = f->fmt.pix.pixelformat;
+
+       tm6000_set_fourcc_format(dev);
+
+       return 0;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+                          struct v4l2_requestbuffers *p)
+{
+       struct tm6000_fh  *fh = priv;
+
+       return videobuf_reqbufs(&fh->vb_vidq, p);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+                           struct v4l2_buffer *p)
+{
+       struct tm6000_fh  *fh = priv;
+
+       return videobuf_querybuf(&fh->vb_vidq, p);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct tm6000_fh  *fh = priv;
+
+       return videobuf_qbuf(&fh->vb_vidq, p);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct tm6000_fh  *fh = priv;
+
+       return videobuf_dqbuf(&fh->vb_vidq, p,
+                               file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct tm6000_fh *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (i != fh->type)
+               return -EINVAL;
+
+       if (!res_get(dev, fh, false))
+               return -EBUSY;
+       return videobuf_streamon(&fh->vb_vidq);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct tm6000_fh *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (i != fh->type)
+               return -EINVAL;
+
+       videobuf_streamoff(&fh->vb_vidq);
+       res_free(dev, fh);
+
+       return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+       int rc = 0;
+       struct tm6000_fh *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       dev->norm = *norm;
+       rc = tm6000_init_analog_mode(dev);
+
+       fh->width  = dev->width;
+       fh->height = dev->height;
+
+       if (rc < 0)
+               return rc;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
+
+       return 0;
+}
+
+static const char *iname[] = {
+       [TM6000_INPUT_TV] = "Television",
+       [TM6000_INPUT_COMPOSITE1] = "Composite 1",
+       [TM6000_INPUT_COMPOSITE2] = "Composite 2",
+       [TM6000_INPUT_SVIDEO] = "S-Video",
+};
+
+static int vidioc_enum_input(struct file *file, void *priv,
+                               struct v4l2_input *i)
+{
+       struct tm6000_fh   *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+       unsigned int n;
+
+       n = i->index;
+       if (n >= 3)
+               return -EINVAL;
+
+       if (!dev->vinput[n].type)
+               return -EINVAL;
+
+       i->index = n;
+
+       if (dev->vinput[n].type == TM6000_INPUT_TV)
+               i->type = V4L2_INPUT_TYPE_TUNER;
+       else
+               i->type = V4L2_INPUT_TYPE_CAMERA;
+
+       strcpy(i->name, iname[dev->vinput[n].type]);
+
+       i->std = TM6000_STD;
+
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct tm6000_fh   *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       *i = dev->input;
+
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       struct tm6000_fh   *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+       int rc = 0;
+
+       if (i >= 3)
+               return -EINVAL;
+       if (!dev->vinput[i].type)
+               return -EINVAL;
+
+       dev->input = i;
+
+       rc = vidioc_s_std(file, priv, &dev->vfd->current_norm);
+
+       return rc;
+}
+
+/* --- controls ---------------------------------------------- */
+static int vidioc_queryctrl(struct file *file, void *priv,
+                               struct v4l2_queryctrl *qc)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)
+               if (qc->id && qc->id == tm6000_qctrl[i].id) {
+                       memcpy(qc, &(tm6000_qctrl[i]),
+                               sizeof(*qc));
+                       return 0;
+               }
+
+       return -EINVAL;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctrl)
+{
+       struct tm6000_fh  *fh = priv;
+       struct tm6000_core *dev    = fh->dev;
+       int  val;
+
+       /* FIXME: Probably, those won't work! Maybe we need shadow regs */
+       switch (ctrl->id) {
+       case V4L2_CID_CONTRAST:
+               val = tm6000_get_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0);
+               break;
+       case V4L2_CID_BRIGHTNESS:
+               val = tm6000_get_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0);
+               return 0;
+       case V4L2_CID_SATURATION:
+               val = tm6000_get_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0);
+               return 0;
+       case V4L2_CID_HUE:
+               val = tm6000_get_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, 0);
+               return 0;
+       case V4L2_CID_AUDIO_MUTE:
+               val = dev->ctl_mute;
+               return 0;
+       case V4L2_CID_AUDIO_VOLUME:
+               val = dev->ctl_volume;
+               return 0;
+       default:
+               return -EINVAL;
+       }
+
+       if (val < 0)
+               return val;
+
+       ctrl->value = val;
+
+       return 0;
+}
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctrl)
+{
+       struct tm6000_fh   *fh  = priv;
+       struct tm6000_core *dev = fh->dev;
+       u8  val = ctrl->value;
+
+       switch (ctrl->id) {
+       case V4L2_CID_CONTRAST:
+               tm6000_set_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, val);
+               return 0;
+       case V4L2_CID_BRIGHTNESS:
+               tm6000_set_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, val);
+               return 0;
+       case V4L2_CID_SATURATION:
+               tm6000_set_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, val);
+               return 0;
+       case V4L2_CID_HUE:
+               tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val);
+               return 0;
+       case V4L2_CID_AUDIO_MUTE:
+               dev->ctl_mute = val;
+               tm6000_tvaudio_set_mute(dev, val);
+               return 0;
+       case V4L2_CID_AUDIO_VOLUME:
+               dev->ctl_volume = val;
+               tm6000_set_volume(dev, val);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct tm6000_fh   *fh  = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (unlikely(UNSET == dev->tuner_type))
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+
+       strcpy(t->name, "Television");
+       t->type       = V4L2_TUNER_ANALOG_TV;
+       t->capability = V4L2_TUNER_CAP_NORM;
+       t->rangehigh  = 0xffffffffUL;
+       t->rxsubchans = V4L2_TUNER_SUB_STEREO;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
+
+       t->audmode = dev->amode;
+
+       return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct tm6000_fh   *fh  = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (UNSET == dev->tuner_type)
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+
+       dev->amode = t->audmode;
+       dprintk(dev, 3, "audio mode: %x\n", t->audmode);
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
+
+       return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct tm6000_fh   *fh  = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (unlikely(UNSET == dev->tuner_type))
+               return -EINVAL;
+
+       f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+       f->frequency = dev->freq;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, f);
+
+       return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct tm6000_fh   *fh  = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (unlikely(UNSET == dev->tuner_type))
+               return -EINVAL;
+       if (unlikely(f->tuner != 0))
+               return -EINVAL;
+       if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type)
+               return -EINVAL;
+       if (1 == fh->radio && V4L2_TUNER_RADIO != f->type)
+               return -EINVAL;
+
+       dev->freq = f->frequency;
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f);
+
+       return 0;
+}
+
+static int radio_querycap(struct file *file, void *priv,
+                                       struct v4l2_capability *cap)
+{
+       struct tm6000_fh *fh = file->private_data;
+       struct tm6000_core *dev = fh->dev;
+
+       strcpy(cap->driver, "tm6000");
+       strlcpy(cap->card, dev->name, sizeof(dev->name));
+       sprintf(cap->bus_info, "USB%04x:%04x",
+               le16_to_cpu(dev->udev->descriptor.idVendor),
+               le16_to_cpu(dev->udev->descriptor.idProduct));
+       cap->version = dev->dev_type;
+       cap->capabilities = V4L2_CAP_TUNER |
+                       V4L2_CAP_AUDIO     |
+                       V4L2_CAP_RADIO     |
+                       V4L2_CAP_READWRITE |
+                       V4L2_CAP_STREAMING;
+
+       return 0;
+}
+
+static int radio_g_tuner(struct file *file, void *priv,
+                                       struct v4l2_tuner *t)
+{
+       struct tm6000_fh *fh = file->private_data;
+       struct tm6000_core *dev = fh->dev;
+
+       if (0 != t->index)
+               return -EINVAL;
+
+       memset(t, 0, sizeof(*t));
+       strcpy(t->name, "Radio");
+       t->type = V4L2_TUNER_RADIO;
+       t->rxsubchans = V4L2_TUNER_SUB_STEREO;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
+
+       return 0;
+}
+
+static int radio_s_tuner(struct file *file, void *priv,
+                                       struct v4l2_tuner *t)
+{
+       struct tm6000_fh *fh = file->private_data;
+       struct tm6000_core *dev = fh->dev;
+
+       if (0 != t->index)
+               return -EINVAL;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
+
+       return 0;
+}
+
+static int radio_enum_input(struct file *file, void *priv,
+                                       struct v4l2_input *i)
+{
+       struct tm6000_fh *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (i->index != 0)
+               return -EINVAL;
+
+       if (!dev->rinput.type)
+               return -EINVAL;
+
+       strcpy(i->name, "Radio");
+       i->type = V4L2_INPUT_TYPE_TUNER;
+
+       return 0;
+}
+
+static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+       struct tm6000_fh *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (dev->input != 5)
+               return -EINVAL;
+
+       *i = dev->input - 5;
+
+       return 0;
+}
+
+static int radio_g_audio(struct file *file, void *priv,
+                                       struct v4l2_audio *a)
+{
+       memset(a, 0, sizeof(*a));
+       strcpy(a->name, "Radio");
+       return 0;
+}
+
+static int radio_s_audio(struct file *file, void *priv,
+                                       struct v4l2_audio *a)
+{
+       return 0;
+}
+
+static int radio_s_input(struct file *filp, void *priv, unsigned int i)
+{
+       struct tm6000_fh *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (i)
+               return -EINVAL;
+
+       if (!dev->rinput.type)
+               return -EINVAL;
+
+       dev->input = i + 5;
+
+       return 0;
+}
+
+static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+       return 0;
+}
+
+static int radio_queryctrl(struct file *file, void *priv,
+                                       struct v4l2_queryctrl *c)
+{
+       const struct v4l2_queryctrl *ctrl;
+
+       if (c->id <  V4L2_CID_BASE ||
+           c->id >= V4L2_CID_LASTP1)
+               return -EINVAL;
+       if (c->id == V4L2_CID_AUDIO_MUTE) {
+               ctrl = ctrl_by_id(c->id);
+               *c = *ctrl;
+       } else
+               *c = no_ctrl;
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------
+       File operations for the device
+   ------------------------------------------------------------------*/
+
+static int tm6000_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct tm6000_core *dev = video_drvdata(file);
+       struct tm6000_fh *fh;
+       enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       int i, rc;
+       int radio = 0;
+
+       dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called (dev=%s)\n",
+               video_device_node_name(vdev));
+
+       switch (vdev->vfl_type) {
+       case VFL_TYPE_GRABBER:
+               type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               break;
+       case VFL_TYPE_VBI:
+               type = V4L2_BUF_TYPE_VBI_CAPTURE;
+               break;
+       case VFL_TYPE_RADIO:
+               radio = 1;
+               break;
+       }
+
+       /* If more than one user, mutex should be added */
+       dev->users++;
+
+       dprintk(dev, V4L2_DEBUG_OPEN, "open dev=%s type=%s users=%d\n",
+               video_device_node_name(vdev), v4l2_type_names[type],
+               dev->users);
+
+       /* allocate + initialize per filehandle data */
+       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+       if (NULL == fh) {
+               dev->users--;
+               return -ENOMEM;
+       }
+
+       file->private_data = fh;
+       fh->dev      = dev;
+       fh->radio    = radio;
+       dev->radio   = radio;
+       fh->type     = type;
+       dev->fourcc  = format[0].fourcc;
+
+       fh->fmt      = format_by_fourcc(dev->fourcc);
+
+       tm6000_get_std_res(dev);
+
+       fh->width = dev->width;
+       fh->height = dev->height;
+
+       dprintk(dev, V4L2_DEBUG_OPEN, "Open: fh=0x%08lx, dev=0x%08lx, "
+                                               "dev->vidq=0x%08lx\n",
+                       (unsigned long)fh, (unsigned long)dev,
+                       (unsigned long)&dev->vidq);
+       dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "
+                               "queued=%d\n", list_empty(&dev->vidq.queued));
+       dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "
+                               "active=%d\n", list_empty(&dev->vidq.active));
+
+       /* initialize hardware on analog mode */
+       rc = tm6000_init_analog_mode(dev);
+       if (rc < 0)
+               return rc;
+
+       if (dev->mode != TM6000_MODE_ANALOG) {
+               /* Put all controls at a sane state */
+               for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)
+                       qctl_regs[i] = tm6000_qctrl[i].default_value;
+
+               dev->mode = TM6000_MODE_ANALOG;
+       }
+
+       if (!fh->radio) {
+               videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops,
+                               NULL, &dev->slock,
+                               fh->type,
+                               V4L2_FIELD_INTERLACED,
+                               sizeof(struct tm6000_buffer), fh, &dev->lock);
+       } else {
+               dprintk(dev, V4L2_DEBUG_OPEN, "video_open: setting radio device\n");
+               dev->input = 5;
+               tm6000_set_audio_rinput(dev);
+               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio);
+               tm6000_prepare_isoc(dev);
+               tm6000_start_thread(dev);
+       }
+
+       return 0;
+}
+
+static ssize_t
+tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos)
+{
+       struct tm6000_fh        *fh = file->private_data;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               if (!res_get(fh->dev, fh, true))
+                       return -EBUSY;
+
+               return videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0,
+                                       file->f_flags & O_NONBLOCK);
+       }
+       return 0;
+}
+
+static unsigned int
+tm6000_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct tm6000_fh        *fh = file->private_data;
+       struct tm6000_buffer    *buf;
+
+       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
+               return POLLERR;
+
+       if (!!is_res_streaming(fh->dev, fh))
+               return POLLERR;
+
+       if (!is_res_read(fh->dev, fh)) {
+               /* streaming capture */
+               if (list_empty(&fh->vb_vidq.stream))
+                       return POLLERR;
+               buf = list_entry(fh->vb_vidq.stream.next, struct tm6000_buffer, vb.stream);
+       } else {
+               /* read() capture */
+               return videobuf_poll_stream(file, &fh->vb_vidq, wait);
+       }
+       poll_wait(file, &buf->vb.done, wait);
+       if (buf->vb.state == VIDEOBUF_DONE ||
+           buf->vb.state == VIDEOBUF_ERROR)
+               return POLLIN | POLLRDNORM;
+       return 0;
+}
+
+static int tm6000_release(struct file *file)
+{
+       struct tm6000_fh         *fh = file->private_data;
+       struct tm6000_core      *dev = fh->dev;
+       struct video_device    *vdev = video_devdata(file);
+
+       dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: close called (dev=%s, users=%d)\n",
+               video_device_node_name(vdev), dev->users);
+
+       dev->users--;
+
+       res_free(dev, fh);
+
+       if (!dev->users) {
+               int err;
+
+               tm6000_uninit_isoc(dev);
+
+               if (!fh->radio)
+                       videobuf_mmap_free(&fh->vb_vidq);
+
+               err = tm6000_reset(dev);
+               if (err < 0)
+                       dev_err(&vdev->dev, "reset failed: %d\n", err);
+       }
+
+       kfree(fh);
+
+       return 0;
+}
+
+static int tm6000_mmap(struct file *file, struct vm_area_struct * vma)
+{
+       struct tm6000_fh *fh = file->private_data;
+
+       return videobuf_mmap_mapper(&fh->vb_vidq, vma);
+}
+
+static struct v4l2_file_operations tm6000_fops = {
+       .owner = THIS_MODULE,
+       .open = tm6000_open,
+       .release = tm6000_release,
+       .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
+       .read = tm6000_read,
+       .poll = tm6000_poll,
+       .mmap = tm6000_mmap,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+       .vidioc_querycap          = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
+       .vidioc_s_std             = vidioc_s_std,
+       .vidioc_enum_input        = vidioc_enum_input,
+       .vidioc_g_input           = vidioc_g_input,
+       .vidioc_s_input           = vidioc_s_input,
+       .vidioc_queryctrl         = vidioc_queryctrl,
+       .vidioc_g_ctrl            = vidioc_g_ctrl,
+       .vidioc_s_ctrl            = vidioc_s_ctrl,
+       .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_streamon          = vidioc_streamon,
+       .vidioc_streamoff         = vidioc_streamoff,
+       .vidioc_reqbufs           = vidioc_reqbufs,
+       .vidioc_querybuf          = vidioc_querybuf,
+       .vidioc_qbuf              = vidioc_qbuf,
+       .vidioc_dqbuf             = vidioc_dqbuf,
+};
+
+static struct video_device tm6000_template = {
+       .name           = "tm6000",
+       .fops           = &tm6000_fops,
+       .ioctl_ops      = &video_ioctl_ops,
+       .release        = video_device_release,
+       .tvnorms        = TM6000_STD,
+       .current_norm   = V4L2_STD_NTSC_M,
+};
+
+static const struct v4l2_file_operations radio_fops = {
+       .owner          = THIS_MODULE,
+       .open           = tm6000_open,
+       .release        = tm6000_release,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
+       .vidioc_querycap        = radio_querycap,
+       .vidioc_g_tuner         = radio_g_tuner,
+       .vidioc_enum_input      = radio_enum_input,
+       .vidioc_g_audio         = radio_g_audio,
+       .vidioc_s_tuner         = radio_s_tuner,
+       .vidioc_s_audio         = radio_s_audio,
+       .vidioc_s_input         = radio_s_input,
+       .vidioc_s_std           = radio_s_std,
+       .vidioc_queryctrl       = radio_queryctrl,
+       .vidioc_g_input         = radio_g_input,
+       .vidioc_g_ctrl          = vidioc_g_ctrl,
+       .vidioc_s_ctrl          = vidioc_s_ctrl,
+       .vidioc_g_frequency     = vidioc_g_frequency,
+       .vidioc_s_frequency     = vidioc_s_frequency,
+};
+
+static struct video_device tm6000_radio_template = {
+       .name                   = "tm6000",
+       .fops                   = &radio_fops,
+       .ioctl_ops              = &radio_ioctl_ops,
+};
+
+/* -----------------------------------------------------------------
+ *     Initialization and module stuff
+ * ------------------------------------------------------------------
+ */
+
+static struct video_device *vdev_init(struct tm6000_core *dev,
+               const struct video_device
+               *template, const char *type_name)
+{
+       struct video_device *vfd;
+
+       vfd = video_device_alloc();
+       if (NULL == vfd)
+               return NULL;
+
+       *vfd = *template;
+       vfd->v4l2_dev = &dev->v4l2_dev;
+       vfd->release = video_device_release;
+       vfd->debug = tm6000_debug;
+       vfd->lock = &dev->lock;
+
+       snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
+
+       video_set_drvdata(vfd, dev);
+       return vfd;
+}
+
+int tm6000_v4l2_register(struct tm6000_core *dev)
+{
+       int ret = -1;
+
+       dev->vfd = vdev_init(dev, &tm6000_template, "video");
+
+       if (!dev->vfd) {
+               printk(KERN_INFO "%s: can't register video device\n",
+                      dev->name);
+               return -ENOMEM;
+       }
+
+       /* init video dma queues */
+       INIT_LIST_HEAD(&dev->vidq.active);
+       INIT_LIST_HEAD(&dev->vidq.queued);
+
+       ret = video_register_device(dev->vfd, VFL_TYPE_GRABBER, video_nr);
+
+       if (ret < 0) {
+               printk(KERN_INFO "%s: can't register video device\n",
+                      dev->name);
+               return ret;
+       }
+
+       printk(KERN_INFO "%s: registered device %s\n",
+              dev->name, video_device_node_name(dev->vfd));
+
+       if (dev->caps.has_radio) {
+               dev->radio_dev = vdev_init(dev, &tm6000_radio_template,
+                                                          "radio");
+               if (!dev->radio_dev) {
+                       printk(KERN_INFO "%s: can't register radio device\n",
+                              dev->name);
+                       return ret; /* FIXME release resource */
+               }
+
+               ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
+                                           radio_nr);
+               if (ret < 0) {
+                       printk(KERN_INFO "%s: can't register radio device\n",
+                              dev->name);
+                       return ret; /* FIXME release resource */
+               }
+
+               printk(KERN_INFO "%s: registered device %s\n",
+                      dev->name, video_device_node_name(dev->radio_dev));
+       }
+
+       printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret);
+       return ret;
+}
+
+int tm6000_v4l2_unregister(struct tm6000_core *dev)
+{
+       video_unregister_device(dev->vfd);
+
+       if (dev->radio_dev) {
+               if (video_is_registered(dev->radio_dev))
+                       video_unregister_device(dev->radio_dev);
+               else
+                       video_device_release(dev->radio_dev);
+               dev->radio_dev = NULL;
+       }
+
+       return 0;
+}
+
+int tm6000_v4l2_exit(void)
+{
+       return 0;
+}
+
+module_param(video_nr, int, 0);
+MODULE_PARM_DESC(video_nr, "Allow changing video device number");
+
+module_param_named(debug, tm6000_debug, int, 0444);
+MODULE_PARM_DESC(debug, "activates debug info");
+
+module_param(vid_limit, int, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
diff --git a/drivers/media/video/tm6000/tm6000.h b/drivers/media/video/tm6000/tm6000.h
new file mode 100644 (file)
index 0000000..2777e51
--- /dev/null
@@ -0,0 +1,398 @@
+/*
+ *  tm6000.h - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ *     - DVB-T support
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/videobuf-vmalloc.h>
+#include "tm6000-usb-isoc.h"
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <media/v4l2-device.h>
+
+#include <linux/dvb/frontend.h>
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dmxdev.h"
+
+#define TM6000_VERSION KERNEL_VERSION(0, 0, 2)
+
+/* Inputs */
+enum tm6000_itype {
+       TM6000_INPUT_TV = 1,
+       TM6000_INPUT_COMPOSITE1,
+       TM6000_INPUT_COMPOSITE2,
+       TM6000_INPUT_SVIDEO,
+       TM6000_INPUT_DVB,
+       TM6000_INPUT_RADIO,
+};
+
+enum tm6000_mux {
+       TM6000_VMUX_VIDEO_A = 1,
+       TM6000_VMUX_VIDEO_B,
+       TM6000_VMUX_VIDEO_AB,
+       TM6000_AMUX_ADC1,
+       TM6000_AMUX_ADC2,
+       TM6000_AMUX_SIF1,
+       TM6000_AMUX_SIF2,
+       TM6000_AMUX_I2S,
+};
+
+enum tm6000_devtype {
+       TM6000 = 0,
+       TM5600,
+       TM6010,
+};
+
+struct tm6000_input {
+       enum tm6000_itype       type;
+       enum tm6000_mux         vmux;
+       enum tm6000_mux         amux;
+       unsigned int            v_gpio;
+       unsigned int            a_gpio;
+};
+
+/* ------------------------------------------------------------------
+ *     Basic structures
+ * ------------------------------------------------------------------
+ */
+
+struct tm6000_fmt {
+       char  *name;
+       u32   fourcc;          /* v4l2 format id */
+       int   depth;
+};
+
+/* buffer for one video frame */
+struct tm6000_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+
+       struct tm6000_fmt      *fmt;
+};
+
+struct tm6000_dmaqueue {
+       struct list_head       active;
+       struct list_head       queued;
+
+       /* thread for generating video stream*/
+       struct task_struct         *kthread;
+       wait_queue_head_t          wq;
+       /* Counters to control fps rate */
+       int                        frame;
+       int                        ini_jiffies;
+};
+
+/* device states */
+enum tm6000_core_state {
+       DEV_INITIALIZED   = 0x01,
+       DEV_DISCONNECTED  = 0x02,
+       DEV_MISCONFIGURED = 0x04,
+};
+
+/* io methods */
+enum tm6000_io_method {
+       IO_NONE,
+       IO_READ,
+       IO_MMAP,
+};
+
+enum tm6000_mode {
+       TM6000_MODE_UNKNOWN = 0,
+       TM6000_MODE_ANALOG,
+       TM6000_MODE_DIGITAL,
+};
+
+struct tm6000_gpio {
+       int             tuner_reset;
+       int             tuner_on;
+       int             demod_reset;
+       int             demod_on;
+       int             power_led;
+       int             dvb_led;
+       int             ir;
+};
+
+struct tm6000_capabilities {
+       unsigned int    has_tuner:1;
+       unsigned int    has_tda9874:1;
+       unsigned int    has_dvb:1;
+       unsigned int    has_zl10353:1;
+       unsigned int    has_eeprom:1;
+       unsigned int    has_remote:1;
+       unsigned int    has_radio:1;
+};
+
+struct tm6000_dvb {
+       struct dvb_adapter      adapter;
+       struct dvb_demux        demux;
+       struct dvb_frontend     *frontend;
+       struct dmxdev           dmxdev;
+       unsigned int            streams;
+       struct urb              *bulk_urb;
+       struct mutex            mutex;
+};
+
+struct snd_tm6000_card {
+       struct snd_card                 *card;
+       spinlock_t                      reg_lock;
+       struct tm6000_core              *core;
+       struct snd_pcm_substream        *substream;
+
+       /* temporary data for buffer fill processing */
+       unsigned                        buf_pos;
+       unsigned                        period_pos;
+};
+
+struct tm6000_endpoint {
+       struct usb_host_endpoint        *endp;
+       __u8                            bInterfaceNumber;
+       __u8                            bAlternateSetting;
+       unsigned                        maxsize;
+};
+
+#define TM6000_QUIRK_NO_USB_DELAY (1 << 0)
+
+struct tm6000_core {
+       /* generic device properties */
+       char                            name[30];       /* name (including minor) of the device */
+       int                             model;          /* index in the device_data struct */
+       int                             devno;          /* marks the number of this device */
+       enum tm6000_devtype             dev_type;       /* type of device */
+       unsigned char                   eedata[256];    /* Eeprom data */
+       unsigned                        eedata_size;    /* Size of the eeprom info */
+
+       v4l2_std_id                     norm;           /* Current norm */
+       int                             width, height;  /* Selected resolution */
+
+       enum tm6000_core_state          state;
+
+       /* Device Capabilities*/
+       struct tm6000_capabilities      caps;
+
+       /* Tuner configuration */
+       int                             tuner_type;             /* type of the tuner */
+       int                             tuner_addr;             /* tuner address */
+
+       struct tm6000_gpio              gpio;
+
+       char                            *ir_codes;
+
+       __u8                            radio;
+
+       /* Demodulator configuration */
+       int                             demod_addr;     /* demodulator address */
+
+       int                             audio_bitrate;
+       /* i2c i/o */
+       struct i2c_adapter              i2c_adap;
+       struct i2c_client               i2c_client;
+
+
+       /* extension */
+       struct list_head                devlist;
+
+       /* video for linux */
+       int                             users;
+
+       /* various device info */
+       struct tm6000_fh                *resources;     /* Points to fh that is streaming */
+       bool                            is_res_read;
+
+       struct video_device             *vfd;
+       struct video_device             *radio_dev;
+       struct tm6000_dmaqueue          vidq;
+       struct v4l2_device              v4l2_dev;
+
+       int                             input;
+       struct tm6000_input             vinput[3];      /* video input */
+       struct tm6000_input             rinput;         /* radio input */
+
+       int                             freq;
+       unsigned int                    fourcc;
+
+       enum tm6000_mode                mode;
+
+       int                             ctl_mute;             /* audio */
+       int                             ctl_volume;
+       int                             amode;
+
+       /* DVB-T support */
+       struct tm6000_dvb               *dvb;
+
+       /* audio support */
+       struct snd_tm6000_card          *adev;
+       struct work_struct              wq_trigger;   /* Trigger to start/stop audio for alsa module */
+       atomic_t                        stream_started;  /* stream should be running if true */
+
+       struct tm6000_IR                *ir;
+
+       /* locks */
+       struct mutex                    lock;
+       struct mutex                    usb_lock;
+
+       /* usb transfer */
+       struct usb_device               *udev;          /* the usb device */
+
+       struct tm6000_endpoint          bulk_in, bulk_out, isoc_in, isoc_out;
+       struct tm6000_endpoint          int_in, int_out;
+
+       /* scaler!=0 if scaler is active*/
+       int                             scaler;
+
+               /* Isoc control struct */
+       struct usb_isoc_ctl          isoc_ctl;
+
+       spinlock_t                   slock;
+
+       unsigned long quirks;
+};
+
+enum tm6000_ops_type {
+       TM6000_AUDIO = 0x10,
+       TM6000_DVB = 0x20,
+};
+
+struct tm6000_ops {
+       struct list_head        next;
+       char                    *name;
+       enum tm6000_ops_type    type;
+       int (*init)(struct tm6000_core *);
+       int (*fini)(struct tm6000_core *);
+       int (*fillbuf)(struct tm6000_core *, char *buf, int size);
+};
+
+struct tm6000_fh {
+       struct tm6000_core           *dev;
+       unsigned int                 radio;
+
+       /* video capture */
+       struct tm6000_fmt            *fmt;
+       unsigned int                 width, height;
+       struct videobuf_queue        vb_vidq;
+
+       enum v4l2_buf_type           type;
+};
+
+#define TM6000_STD     (V4L2_STD_PAL|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|    \
+                       V4L2_STD_PAL_M|V4L2_STD_PAL_60|V4L2_STD_NTSC_M| \
+                       V4L2_STD_NTSC_M_JP|V4L2_STD_SECAM)
+
+/* In tm6000-cards.c */
+
+int tm6000_tuner_callback(void *ptr, int component, int command, int arg);
+int tm6000_xc5000_callback(void *ptr, int component, int command, int arg);
+int tm6000_cards_setup(struct tm6000_core *dev);
+void tm6000_flash_led(struct tm6000_core *dev, u8 state);
+
+/* In tm6000-core.c */
+
+int tm6000_read_write_usb(struct tm6000_core *dev, u8 reqtype, u8 req,
+                          u16 value, u16 index, u8 *buf, u16 len);
+int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index);
+int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index);
+int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index);
+int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index);
+int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
+                                               u16 index, u16 mask);
+int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep);
+int tm6000_init(struct tm6000_core *dev);
+int tm6000_reset(struct tm6000_core *dev);
+
+int tm6000_init_analog_mode(struct tm6000_core *dev);
+int tm6000_init_digital_mode(struct tm6000_core *dev);
+int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate);
+int tm6000_set_audio_rinput(struct tm6000_core *dev);
+int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute);
+void tm6000_set_volume(struct tm6000_core *dev, int vol);
+
+int tm6000_v4l2_register(struct tm6000_core *dev);
+int tm6000_v4l2_unregister(struct tm6000_core *dev);
+int tm6000_v4l2_exit(void);
+void tm6000_set_fourcc_format(struct tm6000_core *dev);
+
+void tm6000_remove_from_devlist(struct tm6000_core *dev);
+void tm6000_add_into_devlist(struct tm6000_core *dev);
+int tm6000_register_extension(struct tm6000_ops *ops);
+void tm6000_unregister_extension(struct tm6000_ops *ops);
+void tm6000_init_extension(struct tm6000_core *dev);
+void tm6000_close_extension(struct tm6000_core *dev);
+int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type,
+                       char *buf, int size);
+
+
+/* In tm6000-stds.c */
+void tm6000_get_std_res(struct tm6000_core *dev);
+int tm6000_set_standard(struct tm6000_core *dev);
+
+/* In tm6000-i2c.c */
+int tm6000_i2c_register(struct tm6000_core *dev);
+int tm6000_i2c_unregister(struct tm6000_core *dev);
+
+/* In tm6000-queue.c */
+
+int tm6000_v4l2_mmap(struct file *filp, struct vm_area_struct *vma);
+
+int tm6000_vidioc_streamon(struct file *file, void *priv,
+                          enum v4l2_buf_type i);
+int tm6000_vidioc_streamoff(struct file *file, void *priv,
+                           enum v4l2_buf_type i);
+int tm6000_vidioc_reqbufs(struct file *file, void *priv,
+                         struct v4l2_requestbuffers *rb);
+int tm6000_vidioc_querybuf(struct file *file, void *priv,
+                          struct v4l2_buffer *b);
+int tm6000_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b);
+int tm6000_vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b);
+ssize_t tm6000_v4l2_read(struct file *filp, char __user * buf, size_t count,
+                        loff_t *f_pos);
+unsigned int tm6000_v4l2_poll(struct file *file,
+                             struct poll_table_struct *wait);
+int tm6000_queue_init(struct tm6000_core *dev);
+
+/* In tm6000-alsa.c */
+/*int tm6000_audio_init(struct tm6000_core *dev, int idx);*/
+
+/* In tm6000-input.c */
+int tm6000_ir_init(struct tm6000_core *dev);
+int tm6000_ir_fini(struct tm6000_core *dev);
+void tm6000_ir_wait(struct tm6000_core *dev, u8 state);
+int tm6000_ir_int_start(struct tm6000_core *dev);
+void tm6000_ir_int_stop(struct tm6000_core *dev);
+
+/* Debug stuff */
+
+extern int tm6000_debug;
+
+#define dprintk(dev, level, fmt, arg...) do {\
+       if (tm6000_debug & level) \
+               printk(KERN_INFO "(%lu) %s %s :"fmt, jiffies, \
+                        dev->name, __func__ , ##arg); } while (0)
+
+#define V4L2_DEBUG_REG         0x0004
+#define V4L2_DEBUG_I2C         0x0008
+#define V4L2_DEBUG_QUEUE       0x0010
+#define V4L2_DEBUG_ISOC                0x0020
+#define V4L2_DEBUG_RES_LOCK    0x0040  /* Resource locking */
+#define V4L2_DEBUG_OPEN                0x0080  /* video open/close debug */
+
+#define tm6000_err(fmt, arg...) do {\
+       printk(KERN_ERR "tm6000 %s :"fmt, \
+               __func__ , ##arg); } while (0)
index 06c9081d596d543339115539c4bb0c9f08bb773e..720927742eb7d1e297480419ca687a0eb1a4ef70 100644 (file)
@@ -32,8 +32,6 @@ source "drivers/staging/go7007/Kconfig"
 
 source "drivers/staging/cx25821/Kconfig"
 
-source "drivers/staging/tm6000/Kconfig"
-
 source "drivers/staging/cxd2099/Kconfig"
 
 source "drivers/staging/usbip/Kconfig"
index f3c5e33bb263b138ffcdb59b064db7b8a93e34e4..d44d25ed6cf1033c8464ae9655e9cc8a04fdada1 100644 (file)
@@ -7,7 +7,6 @@ obj-$(CONFIG_ET131X)            += et131x/
 obj-$(CONFIG_SLICOSS)          += slicoss/
 obj-$(CONFIG_VIDEO_GO7007)     += go7007/
 obj-$(CONFIG_VIDEO_CX25821)    += cx25821/
-obj-$(CONFIG_VIDEO_TM6000)     += tm6000/
 obj-$(CONFIG_DVB_CXD2099)      += cxd2099/
 obj-$(CONFIG_LIRC_STAGING)     += lirc/
 obj-$(CONFIG_USBIP_CORE)       += usbip/
diff --git a/drivers/staging/tm6000/CARDLIST b/drivers/staging/tm6000/CARDLIST
deleted file mode 100644 (file)
index b5edce4..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-  1 -> Generic tm5600 board                   (tm5600)          [6000:0001]
-  2 -> Generic tm6000 board                   (tm6000)          [6000:0001]
-  3 -> Generic tm6010 board                   (tm6010)          [6000:0002]
-  4 -> 10Moons UT821                          (tm5600)          [6000:0001]
-  5 -> 10Moons UT330                          (tm5600)
-  6 -> ADSTech Dual TV                        (tm6000)          [06e1:f332]
-  7 -> FreeCom and similar                    (tm6000)          [14aa:0620]
-  8 -> ADSTech Mini Dual TV                   (tm6000)          [06e1:b339]
-  9 -> Hauppauge WinTV HVR-900H/USB2 Stick    (tm6010)          [2040:6600,2040:6601,2040:6610,2040:6611]
- 10 -> Beholder Wander                        (tm6010)          [6000:dec0]
- 11 -> Beholder Voyager                       (tm6010)          [6000:dec1]
- 12 -> TerraTec Cinergy Hybrid XE/Cinergy Hybrid Stick (tm6010) [0ccd:0086,0ccd:00a5]
- 13 -> TwinHan TU501                          (tm6010)          [13d3:3240,13d3:3241,13d3:3243,13d3:3264]
- 14 -> Beholder Wander Lite                   (tm6010)          [6000:dec2]
- 15 -> Beholder Voyager Lite                  (tm6010)          [6000:dec3]
-
diff --git a/drivers/staging/tm6000/Kconfig b/drivers/staging/tm6000/Kconfig
deleted file mode 100644 (file)
index 114eec8..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-config VIDEO_TM6000
-       tristate "TV Master TM5600/6000/6010 driver"
-       depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB && EXPERIMENTAL
-       select VIDEO_TUNER
-       select MEDIA_TUNER_XC2028
-       select MEDIA_TUNER_XC5000
-       select VIDEOBUF_VMALLOC
-       help
-         Support for TM5600/TM6000/TM6010 USB Device
-
-         Since these cards have no MPEG decoder onboard, they transmit
-         only compressed MPEG data over the usb bus, so you need
-         an external software decoder to watch TV on your computer.
-
-         Say Y if you own such a device and want to use it.
-
-config VIDEO_TM6000_ALSA
-       tristate "TV Master TM5600/6000/6010 audio support"
-       depends on VIDEO_TM6000 && SND && EXPERIMENTAL
-       select SND_PCM
-       ---help---
-         This is a video4linux driver for direct (DMA) audio for
-         TM5600/TM6000/TM6010 USB Devices.
-
-         To compile this driver as a module, choose M here: the
-         module will be called tm6000-alsa.
-
-config VIDEO_TM6000_DVB
-       tristate "DVB Support for tm6000 based TV cards"
-       depends on VIDEO_TM6000 && DVB_CORE && USB && EXPERIMENTAL
-       select DVB_ZL10353
-       ---help---
-         This adds support for DVB cards based on the tm5600/tm6000 chip.
diff --git a/drivers/staging/tm6000/Makefile b/drivers/staging/tm6000/Makefile
deleted file mode 100644 (file)
index 395515b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-tm6000-y := tm6000-cards.o \
-                  tm6000-core.o  \
-                  tm6000-i2c.o   \
-                  tm6000-video.o \
-                  tm6000-stds.o \
-                  tm6000-input.o
-
-obj-$(CONFIG_VIDEO_TM6000) += tm6000.o
-obj-$(CONFIG_VIDEO_TM6000_ALSA) += tm6000-alsa.o
-obj-$(CONFIG_VIDEO_TM6000_DVB) += tm6000-dvb.o
-
-ccflags-y := -Idrivers/media/video
-ccflags-y += -Idrivers/media/common/tuners
-ccflags-y += -Idrivers/media/dvb/dvb-core
-ccflags-y += -Idrivers/media/dvb/frontends
diff --git a/drivers/staging/tm6000/README b/drivers/staging/tm6000/README
deleted file mode 100644 (file)
index c340ebc..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-Todo:
-       - Fix the loss of some blocks when receiving the video URB's
-       - Add a lock at tm6000_read_write_usb() to prevent two simultaneous access to the
-         URB control transfers
-       - Properly add the locks at tm6000-video
-       - Add audio support
-       - Add vbi support
-       - Add IR support
-       - Do several cleanups
-       - I think that frame1/frame0 are inverted. This causes a funny effect at the image.
-         the fix is trivial, but require some tests
-       - My tm6010 devices sometimes insist on stop working. I need to turn them off, removing
-         from my machine and wait for a while for it to work again. I'm starting to think that
-         it is an overheat issue - is there a workaround that we could do?
-       - Sometimes, tm6010 doesn't read eeprom at the proper time (hardware bug). So, the device
-         got miss-detected as a "generic" tm6000. This can be really bad if the tuner is the
-         Low Power one, as it may result on loading the high power firmware, that could damage
-         the device. Maybe we may read eeprom to double check, when the device is marked as "generic"
-       - Coding Style fixes
-       - sparse cleanups
-
-Please send patches to linux-media@vger.kernel.org
diff --git a/drivers/staging/tm6000/TODO b/drivers/staging/tm6000/TODO
deleted file mode 100644 (file)
index 135d0ea..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-There a few things to do before putting this driver in production:
-       - IR NEC with tm5600/6000 TV cards
-       - IR RC5 with tm5600/6000/6010 TV cards
-       - CodingStyle;
-       - Fix audio;
-       - Fix some panic/OOPS conditions.
-
-Please send patches to linux-media@vger.kernel.org
diff --git a/drivers/staging/tm6000/tm6000-alsa.c b/drivers/staging/tm6000/tm6000-alsa.c
deleted file mode 100644 (file)
index 7d675c7..0000000
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- *
- *  Support for audio capture for tm5600/6000/6010
- *    (c) 2007-2008 Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- *  Based on cx88-alsa.c
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/usb.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-#include <linux/delay.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/control.h>
-#include <sound/initval.h>
-
-
-#include "tm6000.h"
-#include "tm6000-regs.h"
-
-#undef dprintk
-
-#define dprintk(level, fmt, arg...) do {                                  \
-       if (debug >= level)                                                \
-               printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg); \
-       } while (0)
-
-/****************************************************************************
-                       Module global static vars
- ****************************************************************************/
-
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
-
-static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
-
-module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable tm6000x soundcard. default enabled.");
-
-module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for tm6000x capture interface(s).");
-
-
-/****************************************************************************
-                               Module macros
- ****************************************************************************/
-
-MODULE_DESCRIPTION("ALSA driver module for tm5600/tm6000/tm6010 based TV cards");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("{{Trident,tm5600},"
-                       "{{Trident,tm6000},"
-                       "{{Trident,tm6010}");
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug messages");
-
-/****************************************************************************
-                       Module specific funtions
- ****************************************************************************/
-
-/*
- * BOARD Specific: Sets audio DMA
- */
-
-static int _tm6000_start_audio_dma(struct snd_tm6000_card *chip)
-{
-       struct tm6000_core *core = chip->core;
-
-       dprintk(1, "Starting audio DMA\n");
-
-       /* Enables audio */
-       tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x40, 0x40);
-
-       tm6000_set_audio_bitrate(core, 48000);
-
-       return 0;
-}
-
-/*
- * BOARD Specific: Resets audio DMA
- */
-static int _tm6000_stop_audio_dma(struct snd_tm6000_card *chip)
-{
-       struct tm6000_core *core = chip->core;
-
-       dprintk(1, "Stopping audio DMA\n");
-
-       /* Disables audio */
-       tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x00, 0x40);
-
-       return 0;
-}
-
-static void dsp_buffer_free(struct snd_pcm_substream *substream)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-
-       dprintk(2, "Freeing buffer\n");
-
-       vfree(substream->runtime->dma_area);
-       substream->runtime->dma_area = NULL;
-       substream->runtime->dma_bytes = 0;
-}
-
-static int dsp_buffer_alloc(struct snd_pcm_substream *substream, int size)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-
-       dprintk(2, "Allocating buffer\n");
-
-       if (substream->runtime->dma_area) {
-               if (substream->runtime->dma_bytes > size)
-                       return 0;
-
-               dsp_buffer_free(substream);
-       }
-
-       substream->runtime->dma_area = vmalloc(size);
-       if (!substream->runtime->dma_area)
-               return -ENOMEM;
-
-       substream->runtime->dma_bytes = size;
-
-       return 0;
-}
-
-
-/****************************************************************************
-                               ALSA PCM Interface
- ****************************************************************************/
-
-/*
- * Digital hardware definition
- */
-#define DEFAULT_FIFO_SIZE      4096
-
-static struct snd_pcm_hardware snd_tm6000_digital_hw = {
-       .info = SNDRV_PCM_INFO_MMAP |
-               SNDRV_PCM_INFO_INTERLEAVED |
-               SNDRV_PCM_INFO_BLOCK_TRANSFER |
-               SNDRV_PCM_INFO_MMAP_VALID,
-       .formats = SNDRV_PCM_FMTBIT_S16_LE,
-
-       .rates = SNDRV_PCM_RATE_CONTINUOUS,
-       .rate_min = 48000,
-       .rate_max = 48000,
-       .channels_min = 2,
-       .channels_max = 2,
-       .period_bytes_min = 64,
-       .period_bytes_max = 12544,
-       .periods_min = 1,
-       .periods_max = 98,
-       .buffer_bytes_max = 62720 * 8,
-};
-
-/*
- * audio pcm capture open callback
- */
-static int snd_tm6000_pcm_open(struct snd_pcm_substream *substream)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       int err;
-
-       err = snd_pcm_hw_constraint_pow2(runtime, 0,
-                                        SNDRV_PCM_HW_PARAM_PERIODS);
-       if (err < 0)
-               goto _error;
-
-       chip->substream = substream;
-
-       runtime->hw = snd_tm6000_digital_hw;
-
-       return 0;
-_error:
-       dprintk(1, "Error opening PCM!\n");
-       return err;
-}
-
-/*
- * audio close callback
- */
-static int snd_tm6000_close(struct snd_pcm_substream *substream)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-       struct tm6000_core *core = chip->core;
-
-       if (atomic_read(&core->stream_started) > 0) {
-               atomic_set(&core->stream_started, 0);
-               schedule_work(&core->wq_trigger);
-       }
-
-       return 0;
-}
-
-static int tm6000_fillbuf(struct tm6000_core *core, char *buf, int size)
-{
-       struct snd_tm6000_card *chip = core->adev;
-       struct snd_pcm_substream *substream = chip->substream;
-       struct snd_pcm_runtime *runtime;
-       int period_elapsed = 0;
-       unsigned int stride, buf_pos;
-       int length;
-
-       if (atomic_read(&core->stream_started) == 0)
-               return 0;
-
-       if (!size || !substream) {
-               dprintk(1, "substream was NULL\n");
-               return -EINVAL;
-       }
-
-       runtime = substream->runtime;
-       if (!runtime || !runtime->dma_area) {
-               dprintk(1, "runtime was NULL\n");
-               return -EINVAL;
-       }
-
-       buf_pos = chip->buf_pos;
-       stride = runtime->frame_bits >> 3;
-
-       if (stride == 0) {
-               dprintk(1, "stride is zero\n");
-               return -EINVAL;
-       }
-
-       length = size / stride;
-       if (length == 0) {
-               dprintk(1, "%s: length was zero\n", __func__);
-               return -EINVAL;
-       }
-
-       dprintk(1, "Copying %d bytes at %p[%d] - buf size=%d x %d\n", size,
-               runtime->dma_area, buf_pos,
-               (unsigned int)runtime->buffer_size, stride);
-
-       if (buf_pos + length >= runtime->buffer_size) {
-               unsigned int cnt = runtime->buffer_size - buf_pos;
-               memcpy(runtime->dma_area + buf_pos * stride, buf, cnt * stride);
-               memcpy(runtime->dma_area, buf + cnt * stride,
-                       length * stride - cnt * stride);
-       } else
-               memcpy(runtime->dma_area + buf_pos * stride, buf,
-                       length * stride);
-
-       snd_pcm_stream_lock(substream);
-
-       chip->buf_pos += length;
-       if (chip->buf_pos >= runtime->buffer_size)
-               chip->buf_pos -= runtime->buffer_size;
-
-       chip->period_pos += length;
-       if (chip->period_pos >= runtime->period_size) {
-               chip->period_pos -= runtime->period_size;
-               period_elapsed = 1;
-       }
-
-       snd_pcm_stream_unlock(substream);
-
-       if (period_elapsed)
-               snd_pcm_period_elapsed(substream);
-
-       return 0;
-}
-
-/*
- * hw_params callback
- */
-static int snd_tm6000_hw_params(struct snd_pcm_substream *substream,
-                             struct snd_pcm_hw_params *hw_params)
-{
-       int size, rc;
-
-       size = params_period_bytes(hw_params) * params_periods(hw_params);
-
-       rc = dsp_buffer_alloc(substream, size);
-       if (rc < 0)
-               return rc;
-
-       return 0;
-}
-
-/*
- * hw free callback
- */
-static int snd_tm6000_hw_free(struct snd_pcm_substream *substream)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-       struct tm6000_core *core = chip->core;
-
-       if (atomic_read(&core->stream_started) > 0) {
-               atomic_set(&core->stream_started, 0);
-               schedule_work(&core->wq_trigger);
-       }
-
-       dsp_buffer_free(substream);
-       return 0;
-}
-
-/*
- * prepare callback
- */
-static int snd_tm6000_prepare(struct snd_pcm_substream *substream)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-
-       chip->buf_pos = 0;
-       chip->period_pos = 0;
-
-       return 0;
-}
-
-
-/*
- * trigger callback
- */
-static void audio_trigger(struct work_struct *work)
-{
-       struct tm6000_core *core = container_of(work, struct tm6000_core,
-                                               wq_trigger);
-       struct snd_tm6000_card *chip = core->adev;
-
-       if (atomic_read(&core->stream_started)) {
-               dprintk(1, "starting capture");
-               _tm6000_start_audio_dma(chip);
-       } else {
-               dprintk(1, "stopping capture");
-               _tm6000_stop_audio_dma(chip);
-       }
-}
-
-static int snd_tm6000_card_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-       struct tm6000_core *core = chip->core;
-       int err = 0;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-               atomic_set(&core->stream_started, 1);
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
-               atomic_set(&core->stream_started, 0);
-               break;
-       default:
-               err = -EINVAL;
-               break;
-       }
-       schedule_work(&core->wq_trigger);
-
-       return err;
-}
-/*
- * pointer callback
- */
-static snd_pcm_uframes_t snd_tm6000_pointer(struct snd_pcm_substream *substream)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-
-       return chip->buf_pos;
-}
-
-/*
- * operators
- */
-static struct snd_pcm_ops snd_tm6000_pcm_ops = {
-       .open = snd_tm6000_pcm_open,
-       .close = snd_tm6000_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_tm6000_hw_params,
-       .hw_free = snd_tm6000_hw_free,
-       .prepare = snd_tm6000_prepare,
-       .trigger = snd_tm6000_card_trigger,
-       .pointer = snd_tm6000_pointer,
-};
-
-/*
- * create a PCM device
- */
-
-/* FIXME: Control interface - How to control volume/mute? */
-
-/****************************************************************************
-                       Basic Flow for Sound Devices
- ****************************************************************************/
-
-/*
- * Alsa Constructor - Component probe
- */
-static int tm6000_audio_init(struct tm6000_core *dev)
-{
-       struct snd_card         *card;
-       struct snd_tm6000_card  *chip;
-       int                     rc;
-       static int              devnr;
-       char                    component[14];
-       struct snd_pcm          *pcm;
-
-       if (!dev)
-               return 0;
-
-       if (devnr >= SNDRV_CARDS)
-               return -ENODEV;
-
-       if (!enable[devnr])
-               return -ENOENT;
-
-       rc = snd_card_create(index[devnr], "tm6000", THIS_MODULE, 0, &card);
-       if (rc < 0) {
-               snd_printk(KERN_ERR "cannot create card instance %d\n", devnr);
-               return rc;
-       }
-       strcpy(card->driver, "tm6000-alsa");
-       strcpy(card->shortname, "TM5600/60x0");
-       sprintf(card->longname, "TM5600/60x0 Audio at bus %d device %d",
-               dev->udev->bus->busnum, dev->udev->devnum);
-
-       sprintf(component, "USB%04x:%04x",
-               le16_to_cpu(dev->udev->descriptor.idVendor),
-               le16_to_cpu(dev->udev->descriptor.idProduct));
-       snd_component_add(card, component);
-       snd_card_set_dev(card, &dev->udev->dev);
-
-       chip = kzalloc(sizeof(struct snd_tm6000_card), GFP_KERNEL);
-       if (!chip) {
-               rc = -ENOMEM;
-               goto error;
-       }
-
-       chip->core = dev;
-       chip->card = card;
-       dev->adev = chip;
-       spin_lock_init(&chip->reg_lock);
-
-       rc = snd_pcm_new(card, "TM6000 Audio", 0, 0, 1, &pcm);
-       if (rc < 0)
-               goto error_chip;
-
-       pcm->info_flags = 0;
-       pcm->private_data = chip;
-       strcpy(pcm->name, "Trident TM5600/60x0");
-
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops);
-
-       INIT_WORK(&dev->wq_trigger, audio_trigger);
-       rc = snd_card_register(card);
-       if (rc < 0)
-               goto error_chip;
-
-       dprintk(1, "Registered audio driver for %s\n", card->longname);
-
-       return 0;
-
-error_chip:
-       kfree(chip);
-       dev->adev = NULL;
-error:
-       snd_card_free(card);
-       return rc;
-}
-
-static int tm6000_audio_fini(struct tm6000_core *dev)
-{
-       struct snd_tm6000_card  *chip = dev->adev;
-
-       if (!dev)
-               return 0;
-
-       if (!chip)
-               return 0;
-
-       if (!chip->card)
-               return 0;
-
-       snd_card_free(chip->card);
-       chip->card = NULL;
-       kfree(chip);
-       dev->adev = NULL;
-
-       return 0;
-}
-
-static struct tm6000_ops audio_ops = {
-       .type   = TM6000_AUDIO,
-       .name   = "TM6000 Audio Extension",
-       .init   = tm6000_audio_init,
-       .fini   = tm6000_audio_fini,
-       .fillbuf = tm6000_fillbuf,
-};
-
-static int __init tm6000_alsa_register(void)
-{
-       return tm6000_register_extension(&audio_ops);
-}
-
-static void __exit tm6000_alsa_unregister(void)
-{
-       tm6000_unregister_extension(&audio_ops);
-}
-
-module_init(tm6000_alsa_register);
-module_exit(tm6000_alsa_unregister);
diff --git a/drivers/staging/tm6000/tm6000-cards.c b/drivers/staging/tm6000/tm6000-cards.c
deleted file mode 100644 (file)
index ec2578a..0000000
+++ /dev/null
@@ -1,1402 +0,0 @@
-/*
- *  tm6000-cards.c - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/usb.h>
-#include <linux/slab.h>
-#include <media/v4l2-common.h>
-#include <media/tuner.h>
-#include <media/tvaudio.h>
-#include <media/i2c-addr.h>
-#include <media/rc-map.h>
-
-#include "tm6000.h"
-#include "tm6000-regs.h"
-#include "tuner-xc2028.h"
-#include "xc5000.h"
-
-#define TM6000_BOARD_UNKNOWN                   0
-#define TM5600_BOARD_GENERIC                   1
-#define TM6000_BOARD_GENERIC                   2
-#define TM6010_BOARD_GENERIC                   3
-#define TM5600_BOARD_10MOONS_UT821             4
-#define TM5600_BOARD_10MOONS_UT330             5
-#define TM6000_BOARD_ADSTECH_DUAL_TV           6
-#define TM6000_BOARD_FREECOM_AND_SIMILAR       7
-#define TM6000_BOARD_ADSTECH_MINI_DUAL_TV      8
-#define TM6010_BOARD_HAUPPAUGE_900H            9
-#define TM6010_BOARD_BEHOLD_WANDER             10
-#define TM6010_BOARD_BEHOLD_VOYAGER            11
-#define TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE        12
-#define TM6010_BOARD_TWINHAN_TU501             13
-#define TM6010_BOARD_BEHOLD_WANDER_LITE                14
-#define TM6010_BOARD_BEHOLD_VOYAGER_LITE       15
-#define TM5600_BOARD_TERRATEC_GRABSTER         16
-
-#define is_generic(model) ((model == TM6000_BOARD_UNKNOWN) || \
-                          (model == TM5600_BOARD_GENERIC) || \
-                          (model == TM6000_BOARD_GENERIC) || \
-                          (model == TM6010_BOARD_GENERIC))
-
-#define TM6000_MAXBOARDS        16
-static unsigned int card[]     = {[0 ... (TM6000_MAXBOARDS - 1)] = UNSET };
-
-module_param_array(card,  int, NULL, 0444);
-
-static unsigned long tm6000_devused;
-
-
-struct tm6000_board {
-       char            *name;
-       char            eename[16];             /* EEPROM name */
-       unsigned        eename_size;            /* size of EEPROM name */
-       unsigned        eename_pos;             /* Position where it appears at ROM */
-
-       struct tm6000_capabilities caps;
-
-       enum            tm6000_devtype type;    /* variant of the chipset */
-       int             tuner_type;     /* type of the tuner */
-       int             tuner_addr;     /* tuner address */
-       int             demod_addr;     /* demodulator address */
-
-       struct tm6000_gpio gpio;
-
-       struct tm6000_input     vinput[3];
-       struct tm6000_input     rinput;
-
-       char            *ir_codes;
-};
-
-static struct tm6000_board tm6000_boards[] = {
-       [TM6000_BOARD_UNKNOWN] = {
-               .name         = "Unknown tm6000 video grabber",
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_eeprom     = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6000_GPIO_1,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM5600_BOARD_GENERIC] = {
-               .name         = "Generic tm5600 board",
-               .type         = TM5600,
-               .tuner_type   = TUNER_XC2028,
-               .tuner_addr   = 0xc2 >> 1,
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_eeprom     = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6000_GPIO_1,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6000_BOARD_GENERIC] = {
-               .name         = "Generic tm6000 board",
-               .tuner_type   = TUNER_XC2028,
-               .tuner_addr   = 0xc2 >> 1,
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_eeprom     = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6000_GPIO_1,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6010_BOARD_GENERIC] = {
-               .name         = "Generic tm6010 board",
-               .type         = TM6010,
-               .tuner_type   = TUNER_XC2028,
-               .tuner_addr   = 0xc2 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_dvb        = 1,
-                       .has_zl10353    = 1,
-                       .has_eeprom     = 1,
-                       .has_remote     = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_2,
-                       .tuner_on       = TM6010_GPIO_3,
-                       .demod_reset    = TM6010_GPIO_1,
-                       .demod_on       = TM6010_GPIO_4,
-                       .power_led      = TM6010_GPIO_7,
-                       .dvb_led        = TM6010_GPIO_5,
-                       .ir             = TM6010_GPIO_0,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM5600_BOARD_10MOONS_UT821] = {
-               .name         = "10Moons UT 821",
-               .tuner_type   = TUNER_XC2028,
-               .eename       = { '1', '0', 'M', 'O', 'O', 'N', 'S', '5', '6', '0', '0', 0xff, 0x45, 0x5b},
-               .eename_size  = 14,
-               .eename_pos   = 0x14,
-               .type         = TM5600,
-               .tuner_addr   = 0xc2 >> 1,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_eeprom   = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6000_GPIO_1,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM5600_BOARD_10MOONS_UT330] = {
-               .name         = "10Moons UT 330",
-               .tuner_type   = TUNER_PHILIPS_FQ1216AME_MK4,
-               .tuner_addr   = 0xc8 >> 1,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_dvb      = 0,
-                       .has_zl10353  = 0,
-                       .has_eeprom   = 1,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6000_BOARD_ADSTECH_DUAL_TV] = {
-               .name         = "ADSTECH Dual TV USB",
-               .tuner_type   = TUNER_XC2028,
-               .tuner_addr   = 0xc8 >> 1,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_tda9874  = 1,
-                       .has_dvb      = 1,
-                       .has_zl10353  = 1,
-                       .has_eeprom   = 1,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6000_BOARD_FREECOM_AND_SIMILAR] = {
-               .name         = "Freecom Hybrid Stick / Moka DVB-T Receiver Dual",
-               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
-               .tuner_addr   = 0xc2 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_dvb      = 1,
-                       .has_zl10353  = 1,
-                       .has_eeprom   = 0,
-                       .has_remote   = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6000_GPIO_4,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6000_BOARD_ADSTECH_MINI_DUAL_TV] = {
-               .name         = "ADSTECH Mini Dual TV USB",
-               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
-               .tuner_addr   = 0xc8 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_dvb      = 1,
-                       .has_zl10353  = 1,
-                       .has_eeprom   = 0,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6000_GPIO_4,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6010_BOARD_HAUPPAUGE_900H] = {
-               .name         = "Hauppauge WinTV HVR-900H / WinTV USB2-Stick",
-               .eename       = { 'H', 0, 'V', 0, 'R', 0, '9', 0, '0', 0, '0', 0, 'H', 0 },
-               .eename_size  = 14,
-               .eename_pos   = 0x42,
-               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
-               .tuner_addr   = 0xc2 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .type         = TM6010,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_dvb      = 1,
-                       .has_zl10353  = 1,
-                       .has_eeprom   = 1,
-                       .has_remote   = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_2,
-                       .tuner_on       = TM6010_GPIO_3,
-                       .demod_reset    = TM6010_GPIO_1,
-                       .demod_on       = TM6010_GPIO_4,
-                       .power_led      = TM6010_GPIO_7,
-                       .dvb_led        = TM6010_GPIO_5,
-                       .ir             = TM6010_GPIO_0,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6010_BOARD_BEHOLD_WANDER] = {
-               .name         = "Beholder Wander DVB-T/TV/FM USB2.0",
-               .tuner_type   = TUNER_XC5000,
-               .tuner_addr   = 0xc2 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .type         = TM6010,
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_dvb        = 1,
-                       .has_zl10353    = 1,
-                       .has_eeprom     = 1,
-                       .has_remote     = 1,
-                       .has_radio      = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_0,
-                       .demod_reset    = TM6010_GPIO_1,
-                       .power_led      = TM6010_GPIO_6,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-               .rinput = {
-                       .type   = TM6000_INPUT_RADIO,
-                       .amux   = TM6000_AMUX_ADC1,
-               },
-       },
-       [TM6010_BOARD_BEHOLD_VOYAGER] = {
-               .name         = "Beholder Voyager TV/FM USB2.0",
-               .tuner_type   = TUNER_XC5000,
-               .tuner_addr   = 0xc2 >> 1,
-               .type         = TM6010,
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_dvb        = 0,
-                       .has_zl10353    = 0,
-                       .has_eeprom     = 1,
-                       .has_remote     = 1,
-                       .has_radio      = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_0,
-                       .power_led      = TM6010_GPIO_6,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-               .rinput = {
-                       .type   = TM6000_INPUT_RADIO,
-                       .amux   = TM6000_AMUX_ADC1,
-               },
-       },
-       [TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE] = {
-               .name         = "Terratec Cinergy Hybrid XE / Cinergy Hybrid-Stick",
-               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
-               .tuner_addr   = 0xc2 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .type         = TM6010,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_dvb      = 1,
-                       .has_zl10353  = 1,
-                       .has_eeprom   = 1,
-                       .has_remote   = 1,
-                       .has_radio    = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_2,
-                       .tuner_on       = TM6010_GPIO_3,
-                       .demod_reset    = TM6010_GPIO_1,
-                       .demod_on       = TM6010_GPIO_4,
-                       .power_led      = TM6010_GPIO_7,
-                       .dvb_led        = TM6010_GPIO_5,
-                       .ir             = TM6010_GPIO_0,
-               },
-               .ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS,
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-               .rinput = {
-                       .type = TM6000_INPUT_RADIO,
-                       .amux = TM6000_AMUX_SIF1,
-               },
-       },
-       [TM5600_BOARD_TERRATEC_GRABSTER] = {
-               .name         = "Terratec Grabster AV 150/250 MX",
-               .type         = TM5600,
-               .tuner_type   = TUNER_ABSENT,
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6010_BOARD_TWINHAN_TU501] = {
-               .name         = "Twinhan TU501(704D1)",
-               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
-               .tuner_addr   = 0xc2 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .type         = TM6010,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_dvb      = 1,
-                       .has_zl10353  = 1,
-                       .has_eeprom   = 1,
-                       .has_remote   = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_2,
-                       .tuner_on       = TM6010_GPIO_3,
-                       .demod_reset    = TM6010_GPIO_1,
-                       .demod_on       = TM6010_GPIO_4,
-                       .power_led      = TM6010_GPIO_7,
-                       .dvb_led        = TM6010_GPIO_5,
-                       .ir             = TM6010_GPIO_0,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6010_BOARD_BEHOLD_WANDER_LITE] = {
-               .name         = "Beholder Wander Lite DVB-T/TV/FM USB2.0",
-               .tuner_type   = TUNER_XC5000,
-               .tuner_addr   = 0xc2 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .type         = TM6010,
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_dvb        = 1,
-                       .has_zl10353    = 1,
-                       .has_eeprom     = 1,
-                       .has_remote     = 0,
-                       .has_radio      = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_0,
-                       .demod_reset    = TM6010_GPIO_1,
-                       .power_led      = TM6010_GPIO_6,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       },
-               },
-               .rinput = {
-                       .type   = TM6000_INPUT_RADIO,
-                       .amux   = TM6000_AMUX_ADC1,
-               },
-       },
-       [TM6010_BOARD_BEHOLD_VOYAGER_LITE] = {
-               .name         = "Beholder Voyager Lite TV/FM USB2.0",
-               .tuner_type   = TUNER_XC5000,
-               .tuner_addr   = 0xc2 >> 1,
-               .type         = TM6010,
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_dvb        = 0,
-                       .has_zl10353    = 0,
-                       .has_eeprom     = 1,
-                       .has_remote     = 0,
-                       .has_radio      = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_0,
-                       .power_led      = TM6010_GPIO_6,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       },
-               },
-               .rinput = {
-                       .type   = TM6000_INPUT_RADIO,
-                       .amux   = TM6000_AMUX_ADC1,
-               },
-       },
-};
-
-/* table of devices that work with this driver */
-static struct usb_device_id tm6000_id_table[] = {
-       { USB_DEVICE(0x6000, 0x0001), .driver_info = TM5600_BOARD_GENERIC },
-       { USB_DEVICE(0x6000, 0x0002), .driver_info = TM6010_BOARD_GENERIC },
-       { USB_DEVICE(0x06e1, 0xf332), .driver_info = TM6000_BOARD_ADSTECH_DUAL_TV },
-       { USB_DEVICE(0x14aa, 0x0620), .driver_info = TM6000_BOARD_FREECOM_AND_SIMILAR },
-       { USB_DEVICE(0x06e1, 0xb339), .driver_info = TM6000_BOARD_ADSTECH_MINI_DUAL_TV },
-       { USB_DEVICE(0x2040, 0x6600), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
-       { USB_DEVICE(0x2040, 0x6601), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
-       { USB_DEVICE(0x2040, 0x6610), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
-       { USB_DEVICE(0x2040, 0x6611), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
-       { USB_DEVICE(0x6000, 0xdec0), .driver_info = TM6010_BOARD_BEHOLD_WANDER },
-       { USB_DEVICE(0x6000, 0xdec1), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER },
-       { USB_DEVICE(0x0ccd, 0x0086), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE },
-       { USB_DEVICE(0x0ccd, 0x00A5), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE },
-       { USB_DEVICE(0x0ccd, 0x0079), .driver_info = TM5600_BOARD_TERRATEC_GRABSTER },
-       { USB_DEVICE(0x13d3, 0x3240), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
-       { USB_DEVICE(0x13d3, 0x3241), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
-       { USB_DEVICE(0x13d3, 0x3243), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
-       { USB_DEVICE(0x13d3, 0x3264), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
-       { USB_DEVICE(0x6000, 0xdec2), .driver_info = TM6010_BOARD_BEHOLD_WANDER_LITE },
-       { USB_DEVICE(0x6000, 0xdec3), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER_LITE },
-       { }
-};
-
-/* Control power led for show some activity */
-void tm6000_flash_led(struct tm6000_core *dev, u8 state)
-{
-       /* Power LED unconfigured */
-       if (!dev->gpio.power_led)
-               return;
-
-       /* ON Power LED */
-       if (state) {
-               switch (dev->model) {
-               case TM6010_BOARD_HAUPPAUGE_900H:
-               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
-               case TM6010_BOARD_TWINHAN_TU501:
-                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                               dev->gpio.power_led, 0x00);
-                       break;
-               case TM6010_BOARD_BEHOLD_WANDER:
-               case TM6010_BOARD_BEHOLD_VOYAGER:
-               case TM6010_BOARD_BEHOLD_WANDER_LITE:
-               case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
-                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                               dev->gpio.power_led, 0x01);
-                       break;
-               }
-       }
-       /* OFF Power LED */
-       else {
-               switch (dev->model) {
-               case TM6010_BOARD_HAUPPAUGE_900H:
-               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
-               case TM6010_BOARD_TWINHAN_TU501:
-                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                               dev->gpio.power_led, 0x01);
-                       break;
-               case TM6010_BOARD_BEHOLD_WANDER:
-               case TM6010_BOARD_BEHOLD_VOYAGER:
-               case TM6010_BOARD_BEHOLD_WANDER_LITE:
-               case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
-                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                               dev->gpio.power_led, 0x00);
-                       break;
-               }
-       }
-}
-
-/* Tuner callback to provide the proper gpio changes needed for xc5000 */
-int tm6000_xc5000_callback(void *ptr, int component, int command, int arg)
-{
-       int rc = 0;
-       struct tm6000_core *dev = ptr;
-
-       if (dev->tuner_type != TUNER_XC5000)
-               return 0;
-
-       switch (command) {
-       case XC5000_TUNER_RESET:
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                              dev->gpio.tuner_reset, 0x01);
-               msleep(15);
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                              dev->gpio.tuner_reset, 0x00);
-               msleep(15);
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                              dev->gpio.tuner_reset, 0x01);
-               break;
-       }
-       return rc;
-}
-EXPORT_SYMBOL_GPL(tm6000_xc5000_callback);
-
-/* Tuner callback to provide the proper gpio changes needed for xc2028 */
-
-int tm6000_tuner_callback(void *ptr, int component, int command, int arg)
-{
-       int rc = 0;
-       struct tm6000_core *dev = ptr;
-
-       if (dev->tuner_type != TUNER_XC2028)
-               return 0;
-
-       switch (command) {
-       case XC2028_RESET_CLK:
-               tm6000_ir_wait(dev, 0);
-
-               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT,
-                                       0x02, arg);
-               msleep(10);
-               rc = tm6000_i2c_reset(dev, 10);
-               break;
-       case XC2028_TUNER_RESET:
-               /* Reset codes during load firmware */
-               switch (arg) {
-               case 0:
-                       /* newer tuner can faster reset */
-                       switch (dev->model) {
-                       case TM5600_BOARD_10MOONS_UT821:
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x01);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              0x300, 0x01);
-                               msleep(10);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x00);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              0x300, 0x00);
-                               msleep(10);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x01);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              0x300, 0x01);
-                               break;
-                       case TM6010_BOARD_HAUPPAUGE_900H:
-                       case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
-                       case TM6010_BOARD_TWINHAN_TU501:
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x01);
-                               msleep(60);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x00);
-                               msleep(75);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x01);
-                               msleep(60);
-                               break;
-                       default:
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x00);
-                               msleep(130);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x01);
-                               msleep(130);
-                               break;
-                       }
-
-                       tm6000_ir_wait(dev, 1);
-                       break;
-               case 1:
-                       tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT,
-                                               0x02, 0x01);
-                       msleep(10);
-                       break;
-               case 2:
-                       rc = tm6000_i2c_reset(dev, 100);
-                       break;
-               }
-               break;
-       case XC2028_I2C_FLUSH:
-               tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
-               tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
-               break;
-       }
-       return rc;
-}
-EXPORT_SYMBOL_GPL(tm6000_tuner_callback);
-
-int tm6000_cards_setup(struct tm6000_core *dev)
-{
-       /*
-        * Board-specific initialization sequence. Handles all GPIO
-        * initialization sequences that are board-specific.
-        * Up to now, all found devices use GPIO1 and GPIO4 at the same way.
-        * Probably, they're all based on some reference device. Due to that,
-        * there's a common routine at the end to handle those GPIO's. Devices
-        * that use different pinups or init sequences can just return at
-        * the board-specific session.
-        */
-       switch (dev->model) {
-       case TM6010_BOARD_HAUPPAUGE_900H:
-       case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
-       case TM6010_BOARD_TWINHAN_TU501:
-       case TM6010_BOARD_GENERIC:
-               /* Turn xceive 3028 on */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.tuner_on, 0x01);
-               msleep(15);
-               /* Turn zarlink zl10353 on */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00);
-               msleep(15);
-               /* Reset zarlink zl10353 */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00);
-               msleep(50);
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01);
-               msleep(15);
-               /* Turn zarlink zl10353 off */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x01);
-               msleep(15);
-               /* ir ? */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.ir, 0x01);
-               msleep(15);
-               /* Power led on (blue) */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x00);
-               msleep(15);
-               /* DVB led off (orange) */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.dvb_led, 0x01);
-               msleep(15);
-               /* Turn zarlink zl10353 on */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00);
-               msleep(15);
-               break;
-       case TM6010_BOARD_BEHOLD_WANDER:
-       case TM6010_BOARD_BEHOLD_WANDER_LITE:
-               /* Power led on (blue) */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01);
-               msleep(15);
-               /* Reset zarlink zl10353 */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00);
-               msleep(50);
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01);
-               msleep(15);
-               break;
-       case TM6010_BOARD_BEHOLD_VOYAGER:
-       case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
-               /* Power led on (blue) */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01);
-               msleep(15);
-               break;
-       default:
-               break;
-       }
-
-       /*
-        * Default initialization. Most of the devices seem to use GPIO1
-        * and GPIO4.on the same way, so, this handles the common sequence
-        * used by most devices.
-        * If a device uses a different sequence or different GPIO pins for
-        * reset, just add the code at the board-specific part
-        */
-
-       if (dev->gpio.tuner_reset) {
-               int rc;
-               int i;
-
-               for (i = 0; i < 2; i++) {
-                       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                               dev->gpio.tuner_reset, 0x00);
-                       if (rc < 0) {
-                               printk(KERN_ERR "Error %i doing tuner reset\n", rc);
-                               return rc;
-                       }
-
-                       msleep(10); /* Just to be conservative */
-                       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                               dev->gpio.tuner_reset, 0x01);
-                       if (rc < 0) {
-                               printk(KERN_ERR "Error %i doing tuner reset\n", rc);
-                               return rc;
-                       }
-               }
-       } else {
-               printk(KERN_ERR "Tuner reset is not configured\n");
-               return -1;
-       }
-
-       msleep(50);
-
-       return 0;
-};
-
-static void tm6000_config_tuner(struct tm6000_core *dev)
-{
-       struct tuner_setup tun_setup;
-
-       /* Load tuner module */
-       v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-               "tuner", dev->tuner_addr, NULL);
-
-       memset(&tun_setup, 0, sizeof(tun_setup));
-       tun_setup.type = dev->tuner_type;
-       tun_setup.addr = dev->tuner_addr;
-
-       tun_setup.mode_mask = 0;
-       if (dev->caps.has_tuner)
-               tun_setup.mode_mask |= (T_ANALOG_TV | T_RADIO);
-
-       switch (dev->tuner_type) {
-       case TUNER_XC2028:
-               tun_setup.tuner_callback = tm6000_tuner_callback;
-               break;
-       case TUNER_XC5000:
-               tun_setup.tuner_callback = tm6000_xc5000_callback;
-               break;
-       }
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
-
-       switch (dev->tuner_type) {
-       case TUNER_XC2028: {
-               struct v4l2_priv_tun_config xc2028_cfg;
-               struct xc2028_ctrl ctl;
-
-               memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
-               memset(&ctl, 0, sizeof(ctl));
-
-               ctl.demod = XC3028_FE_ZARLINK456;
-
-               xc2028_cfg.tuner = TUNER_XC2028;
-               xc2028_cfg.priv  = &ctl;
-
-               switch (dev->model) {
-               case TM6010_BOARD_HAUPPAUGE_900H:
-               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
-               case TM6010_BOARD_TWINHAN_TU501:
-                       ctl.fname = "xc3028L-v36.fw";
-                       break;
-               default:
-                       if (dev->dev_type == TM6010)
-                               ctl.fname = "xc3028-v27.fw";
-                       else
-                               ctl.fname = "xc3028-v24.fw";
-               }
-
-               printk(KERN_INFO "Setting firmware parameters for xc2028\n");
-               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config,
-                                    &xc2028_cfg);
-
-               }
-               break;
-       case TUNER_XC5000:
-               {
-               struct v4l2_priv_tun_config  xc5000_cfg;
-               struct xc5000_config ctl = {
-                       .i2c_address = dev->tuner_addr,
-                       .if_khz      = 4570,
-                       .radio_input = XC5000_RADIO_FM1_MONO,
-                       };
-
-               xc5000_cfg.tuner = TUNER_XC5000;
-               xc5000_cfg.priv  = &ctl;
-
-               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config,
-                                    &xc5000_cfg);
-               }
-               break;
-       default:
-               printk(KERN_INFO "Unknown tuner type. Tuner is not configured.\n");
-               break;
-       }
-}
-
-static int fill_board_specific_data(struct tm6000_core *dev)
-{
-       int rc;
-
-       dev->dev_type   = tm6000_boards[dev->model].type;
-       dev->tuner_type = tm6000_boards[dev->model].tuner_type;
-       dev->tuner_addr = tm6000_boards[dev->model].tuner_addr;
-
-       dev->gpio = tm6000_boards[dev->model].gpio;
-
-       dev->ir_codes = tm6000_boards[dev->model].ir_codes;
-
-       dev->demod_addr = tm6000_boards[dev->model].demod_addr;
-
-       dev->caps = tm6000_boards[dev->model].caps;
-
-       dev->vinput[0] = tm6000_boards[dev->model].vinput[0];
-       dev->vinput[1] = tm6000_boards[dev->model].vinput[1];
-       dev->vinput[2] = tm6000_boards[dev->model].vinput[2];
-       dev->rinput = tm6000_boards[dev->model].rinput;
-
-       /* setup per-model quirks */
-       switch (dev->model) {
-       case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
-               dev->quirks |= TM6000_QUIRK_NO_USB_DELAY;
-               break;
-
-       default:
-               break;
-       }
-
-       /* initialize hardware */
-       rc = tm6000_init(dev);
-       if (rc < 0)
-               return rc;
-
-       return v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev);
-}
-
-
-static void use_alternative_detection_method(struct tm6000_core *dev)
-{
-       int i, model = -1;
-
-       if (!dev->eedata_size)
-               return;
-
-       for (i = 0; i < ARRAY_SIZE(tm6000_boards); i++) {
-               if (!tm6000_boards[i].eename_size)
-                       continue;
-               if (dev->eedata_size < tm6000_boards[i].eename_pos +
-                                      tm6000_boards[i].eename_size)
-                       continue;
-
-               if (!memcmp(&dev->eedata[tm6000_boards[i].eename_pos],
-                           tm6000_boards[i].eename,
-                           tm6000_boards[i].eename_size)) {
-                       model = i;
-                       break;
-               }
-       }
-       if (model < 0) {
-               printk(KERN_INFO "Device has eeprom but is currently unknown\n");
-               return;
-       }
-
-       dev->model = model;
-
-       printk(KERN_INFO "Device identified via eeprom as %s (type = %d)\n",
-              tm6000_boards[model].name, model);
-}
-
-static int tm6000_init_dev(struct tm6000_core *dev)
-{
-       struct v4l2_frequency f;
-       int rc = 0;
-
-       mutex_init(&dev->lock);
-       mutex_lock(&dev->lock);
-
-       if (!is_generic(dev->model)) {
-               rc = fill_board_specific_data(dev);
-               if (rc < 0)
-                       goto err;
-
-               /* register i2c bus */
-               rc = tm6000_i2c_register(dev);
-               if (rc < 0)
-                       goto err;
-       } else {
-               /* register i2c bus */
-               rc = tm6000_i2c_register(dev);
-               if (rc < 0)
-                       goto err;
-
-               use_alternative_detection_method(dev);
-
-               rc = fill_board_specific_data(dev);
-               if (rc < 0)
-                       goto err;
-       }
-
-       /* Default values for STD and resolutions */
-       dev->width = 720;
-       dev->height = 480;
-       dev->norm = V4L2_STD_PAL_M;
-
-       /* Configure tuner */
-       tm6000_config_tuner(dev);
-
-       /* Set video standard */
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
-
-       /* Set tuner frequency - also loads firmware on xc2028/xc3028 */
-       f.tuner = 0;
-       f.type = V4L2_TUNER_ANALOG_TV;
-       f.frequency = 3092;     /* 193.25 MHz */
-       dev->freq = f.frequency;
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
-
-       if (dev->caps.has_tda9874)
-               v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                       "tvaudio", I2C_ADDR_TDA9874, NULL);
-
-       /* register and initialize V4L2 */
-       rc = tm6000_v4l2_register(dev);
-       if (rc < 0)
-               goto err;
-
-       tm6000_add_into_devlist(dev);
-       tm6000_init_extension(dev);
-
-       tm6000_ir_init(dev);
-
-       mutex_unlock(&dev->lock);
-       return 0;
-
-err:
-       mutex_unlock(&dev->lock);
-       return rc;
-}
-
-/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
-#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
-
-static void get_max_endpoint(struct usb_device *udev,
-                            struct usb_host_interface *alt,
-                            char *msgtype,
-                            struct usb_host_endpoint *curr_e,
-                            struct tm6000_endpoint *tm_ep)
-{
-       u16 tmp = le16_to_cpu(curr_e->desc.wMaxPacketSize);
-       unsigned int size = tmp & 0x7ff;
-
-       if (udev->speed == USB_SPEED_HIGH)
-               size = size * hb_mult(tmp);
-
-       if (size > tm_ep->maxsize) {
-               tm_ep->endp = curr_e;
-               tm_ep->maxsize = size;
-               tm_ep->bInterfaceNumber = alt->desc.bInterfaceNumber;
-               tm_ep->bAlternateSetting = alt->desc.bAlternateSetting;
-
-               printk(KERN_INFO "tm6000: %s endpoint: 0x%02x (max size=%u bytes)\n",
-                                       msgtype, curr_e->desc.bEndpointAddress,
-                                       size);
-       }
-}
-
-/*
- * tm6000_usb_probe()
- * checks for supported devices
- */
-static int tm6000_usb_probe(struct usb_interface *interface,
-                           const struct usb_device_id *id)
-{
-       struct usb_device *usbdev;
-       struct tm6000_core *dev = NULL;
-       int i, rc = 0;
-       int nr = 0;
-       char *speed;
-
-       usbdev = usb_get_dev(interface_to_usbdev(interface));
-
-       /* Selects the proper interface */
-       rc = usb_set_interface(usbdev, 0, 1);
-       if (rc < 0)
-               goto err;
-
-       /* Check to see next free device and mark as used */
-       nr = find_first_zero_bit(&tm6000_devused, TM6000_MAXBOARDS);
-       if (nr >= TM6000_MAXBOARDS) {
-               printk(KERN_ERR "tm6000: Supports only %i tm60xx boards.\n", TM6000_MAXBOARDS);
-               usb_put_dev(usbdev);
-               return -ENOMEM;
-       }
-
-       /* Create and initialize dev struct */
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (dev == NULL) {
-               printk(KERN_ERR "tm6000" ": out of memory!\n");
-               usb_put_dev(usbdev);
-               return -ENOMEM;
-       }
-       spin_lock_init(&dev->slock);
-       mutex_init(&dev->usb_lock);
-
-       /* Increment usage count */
-       set_bit(nr, &tm6000_devused);
-       snprintf(dev->name, 29, "tm6000 #%d", nr);
-
-       dev->model = id->driver_info;
-       if (card[nr] < ARRAY_SIZE(tm6000_boards))
-               dev->model = card[nr];
-
-       dev->udev = usbdev;
-       dev->devno = nr;
-
-       switch (usbdev->speed) {
-       case USB_SPEED_LOW:
-               speed = "1.5";
-               break;
-       case USB_SPEED_UNKNOWN:
-       case USB_SPEED_FULL:
-               speed = "12";
-               break;
-       case USB_SPEED_HIGH:
-               speed = "480";
-               break;
-       default:
-               speed = "unknown";
-       }
-
-       /* Get endpoints */
-       for (i = 0; i < interface->num_altsetting; i++) {
-               int ep;
-
-               for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) {
-                       struct usb_host_endpoint        *e;
-                       int dir_out;
-
-                       e = &interface->altsetting[i].endpoint[ep];
-
-                       dir_out = ((e->desc.bEndpointAddress &
-                                       USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
-
-                       printk(KERN_INFO "tm6000: alt %d, interface %i, class %i\n",
-                              i,
-                              interface->altsetting[i].desc.bInterfaceNumber,
-                              interface->altsetting[i].desc.bInterfaceClass);
-
-                       switch (e->desc.bmAttributes) {
-                       case USB_ENDPOINT_XFER_BULK:
-                               if (!dir_out) {
-                                       get_max_endpoint(usbdev,
-                                                        &interface->altsetting[i],
-                                                        "Bulk IN", e,
-                                                        &dev->bulk_in);
-                               } else {
-                                       get_max_endpoint(usbdev,
-                                                        &interface->altsetting[i],
-                                                        "Bulk OUT", e,
-                                                        &dev->bulk_out);
-                               }
-                               break;
-                       case USB_ENDPOINT_XFER_ISOC:
-                               if (!dir_out) {
-                                       get_max_endpoint(usbdev,
-                                                        &interface->altsetting[i],
-                                                        "ISOC IN", e,
-                                                        &dev->isoc_in);
-                               } else {
-                                       get_max_endpoint(usbdev,
-                                                        &interface->altsetting[i],
-                                                        "ISOC OUT", e,
-                                                        &dev->isoc_out);
-                               }
-                               break;
-                       case USB_ENDPOINT_XFER_INT:
-                               if (!dir_out) {
-                                       get_max_endpoint(usbdev,
-                                                       &interface->altsetting[i],
-                                                       "INT IN", e,
-                                                       &dev->int_in);
-                               } else {
-                                       get_max_endpoint(usbdev,
-                                                       &interface->altsetting[i],
-                                                       "INT OUT", e,
-                                                       &dev->int_out);
-                               }
-                               break;
-                       }
-               }
-       }
-
-
-       printk(KERN_INFO "tm6000: New video device @ %s Mbps (%04x:%04x, ifnum %d)\n",
-               speed,
-               le16_to_cpu(dev->udev->descriptor.idVendor),
-               le16_to_cpu(dev->udev->descriptor.idProduct),
-               interface->altsetting->desc.bInterfaceNumber);
-
-/* check if the the device has the iso in endpoint at the correct place */
-       if (!dev->isoc_in.endp) {
-               printk(KERN_ERR "tm6000: probing error: no IN ISOC endpoint!\n");
-               rc = -ENODEV;
-
-               goto err;
-       }
-
-       /* save our data pointer in this interface device */
-       usb_set_intfdata(interface, dev);
-
-       printk(KERN_INFO "tm6000: Found %s\n", tm6000_boards[dev->model].name);
-
-       rc = tm6000_init_dev(dev);
-       if (rc < 0)
-               goto err;
-
-       return 0;
-
-err:
-       printk(KERN_ERR "tm6000: Error %d while registering\n", rc);
-
-       clear_bit(nr, &tm6000_devused);
-       usb_put_dev(usbdev);
-
-       kfree(dev);
-       return rc;
-}
-
-/*
- * tm6000_usb_disconnect()
- * called when the device gets diconencted
- * video device will be unregistered on v4l2_close in case it is still open
- */
-static void tm6000_usb_disconnect(struct usb_interface *interface)
-{
-       struct tm6000_core *dev = usb_get_intfdata(interface);
-       usb_set_intfdata(interface, NULL);
-
-       if (!dev)
-               return;
-
-       printk(KERN_INFO "tm6000: disconnecting %s\n", dev->name);
-
-       tm6000_ir_fini(dev);
-
-       if (dev->gpio.power_led) {
-               switch (dev->model) {
-               case TM6010_BOARD_HAUPPAUGE_900H:
-               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
-               case TM6010_BOARD_TWINHAN_TU501:
-                       /* Power led off */
-                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                               dev->gpio.power_led, 0x01);
-                       msleep(15);
-                       break;
-               case TM6010_BOARD_BEHOLD_WANDER:
-               case TM6010_BOARD_BEHOLD_VOYAGER:
-               case TM6010_BOARD_BEHOLD_WANDER_LITE:
-               case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
-                       /* Power led off */
-                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                               dev->gpio.power_led, 0x00);
-                       msleep(15);
-                       break;
-               }
-       }
-       tm6000_v4l2_unregister(dev);
-
-       tm6000_i2c_unregister(dev);
-
-       v4l2_device_unregister(&dev->v4l2_dev);
-
-       dev->state |= DEV_DISCONNECTED;
-
-       usb_put_dev(dev->udev);
-
-       tm6000_close_extension(dev);
-       tm6000_remove_from_devlist(dev);
-
-       clear_bit(dev->devno, &tm6000_devused);
-       kfree(dev);
-}
-
-static struct usb_driver tm6000_usb_driver = {
-               .name = "tm6000",
-               .probe = tm6000_usb_probe,
-               .disconnect = tm6000_usb_disconnect,
-               .id_table = tm6000_id_table,
-};
-
-static int __init tm6000_module_init(void)
-{
-       int result;
-
-       printk(KERN_INFO "tm6000" " v4l2 driver version %d.%d.%d loaded\n",
-              (TM6000_VERSION  >> 16) & 0xff,
-              (TM6000_VERSION  >> 8) & 0xff, TM6000_VERSION  & 0xff);
-
-       /* register this driver with the USB subsystem */
-       result = usb_register(&tm6000_usb_driver);
-       if (result)
-               printk(KERN_ERR "tm6000"
-                          " usb_register failed. Error number %d.\n", result);
-
-       return result;
-}
-
-static void __exit tm6000_module_exit(void)
-{
-       /* deregister at USB subsystem */
-       usb_deregister(&tm6000_usb_driver);
-}
-
-module_init(tm6000_module_init);
-module_exit(tm6000_module_exit);
-
-MODULE_DESCRIPTION("Trident TVMaster TM5600/TM6000/TM6010 USB2 adapter");
-MODULE_AUTHOR("Mauro Carvalho Chehab");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/tm6000/tm6000-core.c b/drivers/staging/tm6000/tm6000-core.c
deleted file mode 100644 (file)
index 9783616..0000000
+++ /dev/null
@@ -1,965 +0,0 @@
-/*
- *  tm6000-core.c - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
- *      - DVB-T support
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/i2c.h>
-#include "tm6000.h"
-#include "tm6000-regs.h"
-#include <media/v4l2-common.h>
-#include <media/tuner.h>
-
-#define USB_TIMEOUT    (5 * HZ) /* ms */
-
-int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req,
-                         u16 value, u16 index, u8 *buf, u16 len)
-{
-       int          ret, i;
-       unsigned int pipe;
-       u8           *data = NULL;
-
-       mutex_lock(&dev->usb_lock);
-
-       if (len)
-               data = kzalloc(len, GFP_KERNEL);
-
-       if (req_type & USB_DIR_IN)
-               pipe = usb_rcvctrlpipe(dev->udev, 0);
-       else {
-               pipe = usb_sndctrlpipe(dev->udev, 0);
-               memcpy(data, buf, len);
-       }
-
-       if (tm6000_debug & V4L2_DEBUG_I2C) {
-               printk(KERN_DEBUG "(dev %p, pipe %08x): ", dev->udev, pipe);
-
-               printk(KERN_CONT "%s: %02x %02x %02x %02x %02x %02x %02x %02x ",
-                       (req_type & USB_DIR_IN) ? " IN" : "OUT",
-                       req_type, req, value&0xff, value>>8, index&0xff,
-                       index>>8, len&0xff, len>>8);
-
-               if (!(req_type & USB_DIR_IN)) {
-                       printk(KERN_CONT ">>> ");
-                       for (i = 0; i < len; i++)
-                               printk(KERN_CONT " %02x", buf[i]);
-                       printk(KERN_CONT "\n");
-               }
-       }
-
-       ret = usb_control_msg(dev->udev, pipe, req, req_type, value, index,
-                             data, len, USB_TIMEOUT);
-
-       if (req_type &  USB_DIR_IN)
-               memcpy(buf, data, len);
-
-       if (tm6000_debug & V4L2_DEBUG_I2C) {
-               if (ret < 0) {
-                       if (req_type &  USB_DIR_IN)
-                               printk(KERN_DEBUG "<<< (len=%d)\n", len);
-
-                       printk(KERN_CONT "%s: Error #%d\n", __func__, ret);
-               } else if (req_type &  USB_DIR_IN) {
-                       printk(KERN_CONT "<<< ");
-                       for (i = 0; i < len; i++)
-                               printk(KERN_CONT " %02x", buf[i]);
-                       printk(KERN_CONT "\n");
-               }
-       }
-
-       kfree(data);
-       msleep(5);
-
-       mutex_unlock(&dev->usb_lock);
-       return ret;
-}
-
-int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index)
-{
-       return
-               tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
-                                     req, value, index, NULL, 0);
-}
-EXPORT_SYMBOL_GPL(tm6000_set_reg);
-
-int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index)
-{
-       int rc;
-       u8 buf[1];
-
-       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
-                                       value, index, buf, 1);
-
-       if (rc < 0)
-               return rc;
-
-       return *buf;
-}
-EXPORT_SYMBOL_GPL(tm6000_get_reg);
-
-int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
-                                               u16 index, u16 mask)
-{
-       int rc;
-       u8 buf[1];
-       u8 new_index;
-
-       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
-                                       value, index, buf, 1);
-
-       if (rc < 0)
-               return rc;
-
-       new_index = (buf[0] & ~mask) | (index & mask);
-
-       if (new_index == index)
-               return 0;
-
-       return tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
-                                     req, value, new_index, NULL, 0);
-}
-EXPORT_SYMBOL_GPL(tm6000_set_reg_mask);
-
-int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index)
-{
-       int rc;
-       u8 buf[2];
-
-       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
-                                       value, index, buf, 2);
-
-       if (rc < 0)
-               return rc;
-
-       return buf[1]|buf[0]<<8;
-}
-
-int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index)
-{
-       int rc;
-       u8 buf[4];
-
-       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
-                                       value, index, buf, 4);
-
-       if (rc < 0)
-               return rc;
-
-       return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24;
-}
-
-int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep)
-{
-       int rc;
-
-       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
-       if (rc < 0)
-               return rc;
-
-       msleep(tsleep);
-
-       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
-       msleep(tsleep);
-
-       return rc;
-}
-
-void tm6000_set_fourcc_format(struct tm6000_core *dev)
-{
-       if (dev->dev_type == TM6010) {
-               int val;
-
-               val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, 0) & 0xfc;
-               if (dev->fourcc == V4L2_PIX_FMT_UYVY)
-                       tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val);
-               else
-                       tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val | 1);
-       } else {
-               if (dev->fourcc == V4L2_PIX_FMT_UYVY)
-                       tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0);
-               else
-                       tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0x90);
-       }
-}
-
-static void tm6000_set_vbi(struct tm6000_core *dev)
-{
-       /*
-        * FIXME:
-        * VBI lines and start/end are different between 60Hz and 50Hz
-        * So, it is very likely that we need to change the config to
-        * something that takes it into account, doing something different
-        * if (dev->norm & V4L2_STD_525_60)
-        */
-
-       if (dev->dev_type == TM6010) {
-               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
-               tm6000_set_reg(dev, TM6010_REQ07_R41_TELETEXT_VBI_CODE1, 0x27);
-               tm6000_set_reg(dev, TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55);
-               tm6000_set_reg(dev, TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7, 0x66);
-               tm6000_set_reg(dev, TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8, 0x66);
-               tm6000_set_reg(dev, TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23, 0x00);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES, 0x00);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN, 0x00);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02);
-               tm6000_set_reg(dev, TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35);
-               tm6000_set_reg(dev, TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0);
-               tm6000_set_reg(dev, TM6010_REQ07_R5A_VBI_TELETEXT_DTO1, 0x11);
-               tm6000_set_reg(dev, TM6010_REQ07_R5B_VBI_TELETEXT_DTO0, 0x4c);
-               tm6000_set_reg(dev, TM6010_REQ07_R40_TELETEXT_VBI_CODE0, 0x01);
-               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00);
-       }
-}
-
-int tm6000_init_analog_mode(struct tm6000_core *dev)
-{
-       struct v4l2_frequency f;
-
-       if (dev->dev_type == TM6010) {
-               u8 active = TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE;
-
-               if (!dev->radio)
-                       active |= TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE;
-
-               /* Enable video and audio */
-               tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
-                                                       active, 0x60);
-               /* Disable TS input */
-               tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
-                                                       0x00, 0x40);
-       } else {
-               /* Enables soft reset */
-               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
-
-               if (dev->scaler)
-                       /* Disable Hfilter and Enable TS Drop err */
-                       tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x20);
-               else    /* Enable Hfilter and disable TS Drop err */
-                       tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x80);
-
-               tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x88);
-               tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x23);
-               tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xc0);
-               tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xd8);
-               tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x06);
-               tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f);
-
-               /* AP Software reset */
-               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08);
-               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00);
-
-               tm6000_set_fourcc_format(dev);
-
-               /* Disables soft reset */
-               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00);
-       }
-       msleep(20);
-
-       /* Tuner firmware can now be loaded */
-
-       /*
-        * FIXME: This is a hack! xc3028 "sleeps" when no channel is detected
-        * for more than a few seconds. Not sure why, as this behavior does
-        * not happen on other devices with xc3028. So, I suspect that it
-        * is yet another bug at tm6000. After start sleeping, decoding
-        * doesn't start automatically. Instead, it requires some
-        * I2C commands to wake it up. As we want to have image at the
-        * beginning, we needed to add this hack. The better would be to
-        * discover some way to make tm6000 to wake up without this hack.
-        */
-       f.frequency = dev->freq;
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
-
-       msleep(100);
-       tm6000_set_standard(dev);
-       tm6000_set_vbi(dev);
-       tm6000_set_audio_bitrate(dev, 48000);
-
-       /* switch dvb led off */
-       if (dev->gpio.dvb_led) {
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                       dev->gpio.dvb_led, 0x01);
-       }
-
-       return 0;
-}
-
-int tm6000_init_digital_mode(struct tm6000_core *dev)
-{
-       if (dev->dev_type == TM6010) {
-               /* Disable video and audio */
-               tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
-                               0x00, 0x60);
-               /* Enable TS input */
-               tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
-                               0x40, 0x40);
-               /* all power down, but not the digital data port */
-               tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0x28);
-               tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xfc);
-               tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0xff);
-       } else  {
-               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08);
-               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00);
-               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
-               tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x08);
-               tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c);
-               tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff);
-               tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0xd8);
-               tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x40);
-               tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0);
-               tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x09);
-               tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x37);
-               tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xd8);
-               tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xc0);
-               tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x60);
-
-               tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c);
-               tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff);
-               tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0x08);
-               msleep(50);
-
-               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
-               msleep(50);
-               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x01);
-               msleep(50);
-               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
-               msleep(100);
-       }
-
-       /* switch dvb led on */
-       if (dev->gpio.dvb_led) {
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                       dev->gpio.dvb_led, 0x00);
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(tm6000_init_digital_mode);
-
-struct reg_init {
-       u8 req;
-       u8 reg;
-       u8 val;
-};
-
-/* The meaning of those initializations are unknown */
-static struct reg_init tm6000_init_tab[] = {
-       /* REG  VALUE */
-       { TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f },
-       { TM6010_REQ07_RFF_SOFT_RESET, 0x08 },
-       { TM6010_REQ07_RFF_SOFT_RESET, 0x00 },
-       { TM6010_REQ07_RD5_POWERSAVE, 0x4f },
-       { TM6000_REQ07_RDA_CLK_SEL, 0x23 },
-       { TM6000_REQ07_RDB_OUT_SEL, 0x08 },
-       { TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x00 },
-       { TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10 },
-       { TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00 },
-       { TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00 },
-       { TM6000_REQ07_REB_VADC_AADC_MODE, 0x64 },      /* 48000 bits/sample, external input */
-       { TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL, 0xc2 },
-
-       { TM6010_REQ07_R3F_RESET, 0x01 },               /* Start of soft reset */
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
-       { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 },
-       { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 },
-       { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 },
-       { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 },
-       { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a },
-       { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 },
-       { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 },
-       { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b },
-       { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 },
-       { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f },
-       { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c },
-       { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c },
-       { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
-       { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
-       { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a },
-       { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 },
-       { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 },
-       { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a },
-       { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 },
-       { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 },
-       { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 },
-       { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 },
-       { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 },
-       { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 },
-       { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
-       { TM6010_REQ07_RC1_TRESHOLD, 0xd0 },
-       { TM6010_REQ07_RC3_HSTART1, 0x88 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },               /* End of the soft reset */
-       { TM6010_REQ05_R18_IMASK7, 0x00 },
-};
-
-static struct reg_init tm6010_init_tab[] = {
-       { TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x00 },
-       { TM6010_REQ07_RC4_HSTART0, 0xa0 },
-       { TM6010_REQ07_RC6_HEND0, 0x40 },
-       { TM6010_REQ07_RCA_VEND0, 0x31 },
-       { TM6010_REQ07_RCC_ACTIVE_IF, 0xe1 },
-       { TM6010_REQ07_RE0_DVIDEO_SOURCE, 0x03 },
-       { TM6010_REQ07_RFE_POWER_DOWN, 0x7f },
-
-       { TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0 },
-       { TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4 },
-       { TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8 },
-       { TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x00 },
-       { TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2 },
-       { TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0 },
-       { TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2 },
-       { TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60 },
-       { TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc },
-
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
-       { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 },
-       { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 },
-       { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 },
-       { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 },
-       { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a },
-       { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 },
-       { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 },
-       { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b },
-       { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 },
-       { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f },
-       { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c },
-       { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c },
-       { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
-       { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
-       { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a },
-       { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 },
-       { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 },
-       { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a },
-       { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 },
-       { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 },
-       { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 },
-       { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 },
-       { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 },
-       { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 },
-       { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
-       { TM6010_REQ07_RC1_TRESHOLD, 0xd0 },
-       { TM6010_REQ07_RC3_HSTART1, 0x88 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-
-       { TM6010_REQ05_R18_IMASK7, 0x00 },
-
-       { TM6010_REQ07_RD8_IR_LEADER1, 0xaa },
-       { TM6010_REQ07_RD8_IR_LEADER0, 0x30 },
-       { TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20 },
-       { TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0 },
-       { REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 },
-       { TM6010_REQ07_RD8_IR, 0x2f },
-
-       /* set remote wakeup key:any key wakeup */
-       { TM6010_REQ07_RE5_REMOTE_WAKEUP,  0xfe },
-       { TM6010_REQ07_RD8_IR_WAKEUP_SEL,  0xff },
-};
-
-int tm6000_init(struct tm6000_core *dev)
-{
-       int board, rc = 0, i, size;
-       struct reg_init *tab;
-
-       /* Check board revision */
-       board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0);
-       if (board >= 0) {
-               switch (board & 0xff) {
-               case 0xf3:
-                       printk(KERN_INFO "Found tm6000\n");
-                       if (dev->dev_type != TM6000)
-                               dev->dev_type = TM6000;
-                       break;
-               case 0xf4:
-                       printk(KERN_INFO "Found tm6010\n");
-                       if (dev->dev_type != TM6010)
-                               dev->dev_type = TM6010;
-                       break;
-               default:
-                       printk(KERN_INFO "Unknown board version = 0x%08x\n", board);
-               }
-       } else
-               printk(KERN_ERR "Error %i while retrieving board version\n", board);
-
-       if (dev->dev_type == TM6010) {
-               tab = tm6010_init_tab;
-               size = ARRAY_SIZE(tm6010_init_tab);
-       } else {
-               tab = tm6000_init_tab;
-               size = ARRAY_SIZE(tm6000_init_tab);
-       }
-
-       /* Load board's initialization table */
-       for (i = 0; i < size; i++) {
-               rc = tm6000_set_reg(dev, tab[i].req, tab[i].reg, tab[i].val);
-               if (rc < 0) {
-                       printk(KERN_ERR "Error %i while setting req %d, "
-                                       "reg %d to value %d\n", rc,
-                                       tab[i].req, tab[i].reg, tab[i].val);
-                       return rc;
-               }
-       }
-
-       msleep(5); /* Just to be conservative */
-
-       rc = tm6000_cards_setup(dev);
-
-       return rc;
-}
-
-int tm6000_reset(struct tm6000_core *dev)
-{
-       int pipe;
-       int err;
-
-       msleep(500);
-
-       err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 0);
-       if (err < 0) {
-               tm6000_err("failed to select interface %d, alt. setting 0\n",
-                               dev->isoc_in.bInterfaceNumber);
-               return err;
-       }
-
-       err = usb_reset_configuration(dev->udev);
-       if (err < 0) {
-               tm6000_err("failed to reset configuration\n");
-               return err;
-       }
-
-       if ((dev->quirks & TM6000_QUIRK_NO_USB_DELAY) == 0)
-               msleep(5);
-
-       /*
-        * Not all devices have int_in defined
-        */
-       if (!dev->int_in.endp)
-               return 0;
-
-       err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 2);
-       if (err < 0) {
-               tm6000_err("failed to select interface %d, alt. setting 2\n",
-                               dev->isoc_in.bInterfaceNumber);
-               return err;
-       }
-
-       msleep(5);
-
-       pipe = usb_rcvintpipe(dev->udev,
-                       dev->int_in.endp->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
-
-       err = usb_clear_halt(dev->udev, pipe);
-       if (err < 0) {
-               tm6000_err("usb_clear_halt failed: %d\n", err);
-               return err;
-       }
-
-       return 0;
-}
-
-int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate)
-{
-       int val = 0;
-       u8 areg_f0 = 0x60; /* ADC MCLK = 250 Fs */
-       u8 areg_0a = 0x91; /* SIF 48KHz */
-
-       switch (bitrate) {
-       case 48000:
-               areg_f0 = 0x60; /* ADC MCLK = 250 Fs */
-               areg_0a = 0x91; /* SIF 48KHz */
-               dev->audio_bitrate = bitrate;
-               break;
-       case 32000:
-               areg_f0 = 0x00; /* ADC MCLK = 375 Fs */
-               areg_0a = 0x90; /* SIF 32KHz */
-               dev->audio_bitrate = bitrate;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-
-       /* enable I2S, if we use sif or external I2S device */
-       if (dev->dev_type == TM6010) {
-               val = tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, areg_0a);
-               if (val < 0)
-                       return val;
-
-               val = tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
-                                                       areg_f0, 0xf0);
-               if (val < 0)
-                       return val;
-       } else {
-               val = tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
-                                                       areg_f0, 0xf0);
-               if (val < 0)
-                       return val;
-       }
-       return 0;
-}
-EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate);
-
-int tm6000_set_audio_rinput(struct tm6000_core *dev)
-{
-       if (dev->dev_type == TM6010) {
-               /* Audio crossbar setting, default SIF1 */
-               u8 areg_f0;
-
-               switch (dev->rinput.amux) {
-               case TM6000_AMUX_SIF1:
-               case TM6000_AMUX_SIF2:
-                       areg_f0 = 0x03;
-                       break;
-               case TM6000_AMUX_ADC1:
-                       areg_f0 = 0x00;
-                       break;
-               case TM6000_AMUX_ADC2:
-                       areg_f0 = 0x08;
-                       break;
-               case TM6000_AMUX_I2S:
-                       areg_f0 = 0x04;
-                       break;
-               default:
-                       printk(KERN_INFO "%s: audio input dosn't support\n",
-                               dev->name);
-                       return 0;
-                       break;
-               }
-               /* Set audio input crossbar */
-               tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
-                                                       areg_f0, 0x0f);
-       } else {
-               u8 areg_eb;
-               /* Audio setting, default LINE1 */
-               switch (dev->rinput.amux) {
-               case TM6000_AMUX_ADC1:
-                       areg_eb = 0x00;
-                       break;
-               case TM6000_AMUX_ADC2:
-                       areg_eb = 0x04;
-                       break;
-               default:
-                       printk(KERN_INFO "%s: audio input dosn't support\n",
-                               dev->name);
-                       return 0;
-                       break;
-               }
-               /* Set audio input */
-               tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
-                                                       areg_eb, 0x0f);
-       }
-       return 0;
-}
-
-static void tm6010_set_mute_sif(struct tm6000_core *dev, u8 mute)
-{
-       u8 mute_reg = 0;
-
-       if (mute)
-               mute_reg = 0x08;
-
-       tm6000_set_reg_mask(dev, TM6010_REQ08_R0A_A_I2S_MOD, mute_reg, 0x08);
-}
-
-static void tm6010_set_mute_adc(struct tm6000_core *dev, u8 mute)
-{
-       u8 mute_reg = 0;
-
-       if (mute)
-               mute_reg = 0x20;
-
-       if (dev->dev_type == TM6010) {
-               tm6000_set_reg_mask(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL,
-                                                       mute_reg, 0x20);
-               tm6000_set_reg_mask(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL,
-                                                       mute_reg, 0x20);
-       } else {
-               tm6000_set_reg_mask(dev, TM6000_REQ07_REC_VADC_AADC_LVOL,
-                                                       mute_reg, 0x20);
-               tm6000_set_reg_mask(dev, TM6000_REQ07_RED_VADC_AADC_RVOL,
-                                                       mute_reg, 0x20);
-       }
-}
-
-int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute)
-{
-       enum tm6000_mux mux;
-
-       if (dev->radio)
-               mux = dev->rinput.amux;
-       else
-               mux = dev->vinput[dev->input].amux;
-
-       switch (mux) {
-       case TM6000_AMUX_SIF1:
-       case TM6000_AMUX_SIF2:
-               if (dev->dev_type == TM6010)
-                       tm6010_set_mute_sif(dev, mute);
-               else {
-                       printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has"
-                                       " SIF audio inputs. Please check the %s"
-                                       " configuration.\n", dev->name);
-                       return -EINVAL;
-               }
-               break;
-       case TM6000_AMUX_ADC1:
-       case TM6000_AMUX_ADC2:
-               tm6010_set_mute_adc(dev, mute);
-               break;
-       default:
-               return -EINVAL;
-               break;
-       }
-       return 0;
-}
-
-static void tm6010_set_volume_sif(struct tm6000_core *dev, int vol)
-{
-       u8 vol_reg;
-
-       vol_reg = vol & 0x0F;
-
-       if (vol < 0)
-               vol_reg |= 0x40;
-
-       tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, vol_reg);
-       tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, vol_reg);
-}
-
-static void tm6010_set_volume_adc(struct tm6000_core *dev, int vol)
-{
-       u8 vol_reg;
-
-       vol_reg = (vol + 0x10) & 0x1f;
-
-       if (dev->dev_type == TM6010) {
-               tm6000_set_reg(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL, vol_reg);
-               tm6000_set_reg(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL, vol_reg);
-       } else {
-               tm6000_set_reg(dev, TM6000_REQ07_REC_VADC_AADC_LVOL, vol_reg);
-               tm6000_set_reg(dev, TM6000_REQ07_RED_VADC_AADC_RVOL, vol_reg);
-       }
-}
-
-void tm6000_set_volume(struct tm6000_core *dev, int vol)
-{
-       enum tm6000_mux mux;
-
-       if (dev->radio) {
-               mux = dev->rinput.amux;
-               vol += 8; /* Offset to 0 dB */
-       } else
-               mux = dev->vinput[dev->input].amux;
-
-       switch (mux) {
-       case TM6000_AMUX_SIF1:
-       case TM6000_AMUX_SIF2:
-               if (dev->dev_type == TM6010)
-                       tm6010_set_volume_sif(dev, vol);
-               else
-                       printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has"
-                                       " SIF audio inputs. Please check the %s"
-                                       " configuration.\n", dev->name);
-               break;
-       case TM6000_AMUX_ADC1:
-       case TM6000_AMUX_ADC2:
-               tm6010_set_volume_adc(dev, vol);
-               break;
-       default:
-               break;
-       }
-}
-
-static LIST_HEAD(tm6000_devlist);
-static DEFINE_MUTEX(tm6000_devlist_mutex);
-
-/*
- * tm6000_realease_resource()
- */
-
-void tm6000_remove_from_devlist(struct tm6000_core *dev)
-{
-       mutex_lock(&tm6000_devlist_mutex);
-       list_del(&dev->devlist);
-       mutex_unlock(&tm6000_devlist_mutex);
-};
-
-void tm6000_add_into_devlist(struct tm6000_core *dev)
-{
-       mutex_lock(&tm6000_devlist_mutex);
-       list_add_tail(&dev->devlist, &tm6000_devlist);
-       mutex_unlock(&tm6000_devlist_mutex);
-};
-
-/*
- * Extension interface
- */
-
-static LIST_HEAD(tm6000_extension_devlist);
-
-int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type,
-                       char *buf, int size)
-{
-       struct tm6000_ops *ops = NULL;
-
-       /* FIXME: tm6000_extension_devlist_lock should be a spinlock */
-
-       if (!list_empty(&tm6000_extension_devlist)) {
-               list_for_each_entry(ops, &tm6000_extension_devlist, next) {
-                       if (ops->fillbuf && ops->type == type)
-                               ops->fillbuf(dev, buf, size);
-               }
-       }
-
-       return 0;
-}
-
-int tm6000_register_extension(struct tm6000_ops *ops)
-{
-       struct tm6000_core *dev = NULL;
-
-       mutex_lock(&tm6000_devlist_mutex);
-       list_add_tail(&ops->next, &tm6000_extension_devlist);
-       list_for_each_entry(dev, &tm6000_devlist, devlist) {
-               ops->init(dev);
-               printk(KERN_INFO "%s: Initialized (%s) extension\n",
-                      dev->name, ops->name);
-       }
-       mutex_unlock(&tm6000_devlist_mutex);
-       return 0;
-}
-EXPORT_SYMBOL(tm6000_register_extension);
-
-void tm6000_unregister_extension(struct tm6000_ops *ops)
-{
-       struct tm6000_core *dev = NULL;
-
-       mutex_lock(&tm6000_devlist_mutex);
-       list_for_each_entry(dev, &tm6000_devlist, devlist)
-               ops->fini(dev);
-
-       printk(KERN_INFO "tm6000: Remove (%s) extension\n", ops->name);
-       list_del(&ops->next);
-       mutex_unlock(&tm6000_devlist_mutex);
-}
-EXPORT_SYMBOL(tm6000_unregister_extension);
-
-void tm6000_init_extension(struct tm6000_core *dev)
-{
-       struct tm6000_ops *ops = NULL;
-
-       mutex_lock(&tm6000_devlist_mutex);
-       if (!list_empty(&tm6000_extension_devlist)) {
-               list_for_each_entry(ops, &tm6000_extension_devlist, next) {
-                       if (ops->init)
-                               ops->init(dev);
-               }
-       }
-       mutex_unlock(&tm6000_devlist_mutex);
-}
-
-void tm6000_close_extension(struct tm6000_core *dev)
-{
-       struct tm6000_ops *ops = NULL;
-
-       mutex_lock(&tm6000_devlist_mutex);
-       if (!list_empty(&tm6000_extension_devlist)) {
-               list_for_each_entry(ops, &tm6000_extension_devlist, next) {
-                       if (ops->fini)
-                               ops->fini(dev);
-               }
-       }
-       mutex_unlock(&tm6000_devlist_mutex);
-}
diff --git a/drivers/staging/tm6000/tm6000-dvb.c b/drivers/staging/tm6000/tm6000-dvb.c
deleted file mode 100644 (file)
index 5e6c129..0000000
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- *  tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-
-#include "tm6000.h"
-#include "tm6000-regs.h"
-
-#include "zl10353.h"
-
-#include <media/tuner.h>
-
-#include "tuner-xc2028.h"
-#include "xc5000.h"
-
-MODULE_DESCRIPTION("DVB driver extension module for tm5600/6000/6010 based TV cards");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_LICENSE("GPL");
-
-MODULE_SUPPORTED_DEVICE("{{Trident, tm5600},"
-                       "{{Trident, tm6000},"
-                       "{{Trident, tm6010}");
-
-static int debug;
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug message");
-
-static inline void print_err_status(struct tm6000_core *dev,
-                                   int packet, int status)
-{
-       char *errmsg = "Unknown";
-
-       switch (status) {
-       case -ENOENT:
-               errmsg = "unlinked synchronuously";
-               break;
-       case -ECONNRESET:
-               errmsg = "unlinked asynchronuously";
-               break;
-       case -ENOSR:
-               errmsg = "Buffer error (overrun)";
-               break;
-       case -EPIPE:
-               errmsg = "Stalled (device not responding)";
-               break;
-       case -EOVERFLOW:
-               errmsg = "Babble (bad cable?)";
-               break;
-       case -EPROTO:
-               errmsg = "Bit-stuff error (bad cable?)";
-               break;
-       case -EILSEQ:
-               errmsg = "CRC/Timeout (could be anything)";
-               break;
-       case -ETIME:
-               errmsg = "Device does not respond";
-               break;
-       }
-       if (packet < 0) {
-               dprintk(dev, 1, "URB status %d [%s].\n",
-                       status, errmsg);
-       } else {
-               dprintk(dev, 1, "URB packet %d, status %d [%s].\n",
-                       packet, status, errmsg);
-       }
-}
-
-static void tm6000_urb_received(struct urb *urb)
-{
-       int ret;
-       struct tm6000_core *dev = urb->context;
-
-       if (urb->status != 0)
-               print_err_status(dev, 0, urb->status);
-       else if (urb->actual_length > 0)
-               dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
-                                                  urb->actual_length);
-
-       if (dev->dvb->streams > 0) {
-               ret = usb_submit_urb(urb, GFP_ATOMIC);
-               if (ret < 0) {
-                       printk(KERN_ERR "tm6000:  error %s\n", __func__);
-                       kfree(urb->transfer_buffer);
-                       usb_free_urb(urb);
-               }
-       }
-}
-
-static int tm6000_start_stream(struct tm6000_core *dev)
-{
-       int ret;
-       unsigned int pipe, size;
-       struct tm6000_dvb *dvb = dev->dvb;
-
-       printk(KERN_INFO "tm6000: got start stream request %s\n", __func__);
-
-       if (dev->mode != TM6000_MODE_DIGITAL) {
-               tm6000_init_digital_mode(dev);
-               dev->mode = TM6000_MODE_DIGITAL;
-       }
-
-       dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (dvb->bulk_urb == NULL) {
-               printk(KERN_ERR "tm6000: couldn't allocate urb\n");
-               return -ENOMEM;
-       }
-
-       pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress
-                                                         & USB_ENDPOINT_NUMBER_MASK);
-
-       size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
-       size = size * 15; /* 512 x 8 or 12 or 15 */
-
-       dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
-       if (dvb->bulk_urb->transfer_buffer == NULL) {
-               usb_free_urb(dvb->bulk_urb);
-               printk(KERN_ERR "tm6000: couldn't allocate transfer buffer!\n");
-               return -ENOMEM;
-       }
-
-       usb_fill_bulk_urb(dvb->bulk_urb, dev->udev, pipe,
-                                                dvb->bulk_urb->transfer_buffer,
-                                                size,
-                                                tm6000_urb_received, dev);
-
-       ret = usb_clear_halt(dev->udev, pipe);
-       if (ret < 0) {
-               printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",
-                                                       ret, __func__);
-               return ret;
-       } else
-               printk(KERN_ERR "tm6000: pipe resetted\n");
-
-/*     mutex_lock(&tm6000_driver.open_close_mutex); */
-       ret = usb_submit_urb(dvb->bulk_urb, GFP_KERNEL);
-
-/*     mutex_unlock(&tm6000_driver.open_close_mutex); */
-       if (ret) {
-               printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n",
-                                                                       ret);
-
-               kfree(dvb->bulk_urb->transfer_buffer);
-               usb_free_urb(dvb->bulk_urb);
-               return ret;
-       }
-
-       return 0;
-}
-
-static void tm6000_stop_stream(struct tm6000_core *dev)
-{
-       struct tm6000_dvb *dvb = dev->dvb;
-
-       if (dvb->bulk_urb) {
-               printk(KERN_INFO "urb killing\n");
-               usb_kill_urb(dvb->bulk_urb);
-               printk(KERN_INFO "urb buffer free\n");
-               kfree(dvb->bulk_urb->transfer_buffer);
-               usb_free_urb(dvb->bulk_urb);
-               dvb->bulk_urb = NULL;
-       }
-}
-
-static int tm6000_start_feed(struct dvb_demux_feed *feed)
-{
-       struct dvb_demux *demux = feed->demux;
-       struct tm6000_core *dev = demux->priv;
-       struct tm6000_dvb *dvb = dev->dvb;
-       printk(KERN_INFO "tm6000: got start feed request %s\n", __func__);
-
-       mutex_lock(&dvb->mutex);
-       if (dvb->streams == 0) {
-               dvb->streams = 1;
-/*             mutex_init(&tm6000_dev->streming_mutex); */
-               tm6000_start_stream(dev);
-       } else
-               ++(dvb->streams);
-       mutex_unlock(&dvb->mutex);
-
-       return 0;
-}
-
-static int tm6000_stop_feed(struct dvb_demux_feed *feed)
-{
-       struct dvb_demux *demux = feed->demux;
-       struct tm6000_core *dev = demux->priv;
-       struct tm6000_dvb *dvb = dev->dvb;
-
-       printk(KERN_INFO "tm6000: got stop feed request %s\n", __func__);
-
-       mutex_lock(&dvb->mutex);
-
-       printk(KERN_INFO "stream %#x\n", dvb->streams);
-       --(dvb->streams);
-       if (dvb->streams == 0) {
-               printk(KERN_INFO "stop stream\n");
-               tm6000_stop_stream(dev);
-/*             mutex_destroy(&tm6000_dev->streaming_mutex); */
-       }
-       mutex_unlock(&dvb->mutex);
-/*     mutex_destroy(&tm6000_dev->streaming_mutex); */
-
-       return 0;
-}
-
-static int tm6000_dvb_attach_frontend(struct tm6000_core *dev)
-{
-       struct tm6000_dvb *dvb = dev->dvb;
-
-       if (dev->caps.has_zl10353) {
-               struct zl10353_config config = {
-                                    .demod_address = dev->demod_addr,
-                                    .no_tuner = 1,
-                                    .parallel_ts = 1,
-                                    .if2 = 45700,
-                                    .disable_i2c_gate_ctrl = 1,
-                                   };
-
-               dvb->frontend = dvb_attach(zl10353_attach, &config,
-                                                          &dev->i2c_adap);
-       } else {
-               printk(KERN_ERR "tm6000: no frontend defined for the device!\n");
-               return -1;
-       }
-
-       return (!dvb->frontend) ? -1 : 0;
-}
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int register_dvb(struct tm6000_core *dev)
-{
-       int ret = -1;
-       struct tm6000_dvb *dvb = dev->dvb;
-
-       mutex_init(&dvb->mutex);
-
-       dvb->streams = 0;
-
-       /* attach the frontend */
-       ret = tm6000_dvb_attach_frontend(dev);
-       if (ret < 0) {
-               printk(KERN_ERR "tm6000: couldn't attach the frontend!\n");
-               goto err;
-       }
-
-       ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T",
-                                       THIS_MODULE, &dev->udev->dev, adapter_nr);
-       dvb->adapter.priv = dev;
-
-       if (dvb->frontend) {
-               switch (dev->tuner_type) {
-               case TUNER_XC2028: {
-                       struct xc2028_config cfg = {
-                               .i2c_adap = &dev->i2c_adap,
-                               .i2c_addr = dev->tuner_addr,
-                       };
-
-                       dvb->frontend->callback = tm6000_tuner_callback;
-                       ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
-                       if (ret < 0) {
-                               printk(KERN_ERR
-                                       "tm6000: couldn't register frontend\n");
-                               goto adapter_err;
-                       }
-
-                       if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
-                               printk(KERN_ERR "tm6000: couldn't register "
-                                               "frontend (xc3028)\n");
-                               ret = -EINVAL;
-                               goto frontend_err;
-                       }
-                       printk(KERN_INFO "tm6000: XC2028/3028 asked to be "
-                                        "attached to frontend!\n");
-                       break;
-                       }
-               case TUNER_XC5000: {
-                       struct xc5000_config cfg = {
-                               .i2c_address = dev->tuner_addr,
-                       };
-
-                       dvb->frontend->callback = tm6000_xc5000_callback;
-                       ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
-                       if (ret < 0) {
-                               printk(KERN_ERR
-                                       "tm6000: couldn't register frontend\n");
-                               goto adapter_err;
-                       }
-
-                       if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) {
-                               printk(KERN_ERR "tm6000: couldn't register "
-                                               "frontend (xc5000)\n");
-                               ret = -EINVAL;
-                               goto frontend_err;
-                       }
-                       printk(KERN_INFO "tm6000: XC5000 asked to be "
-                                        "attached to frontend!\n");
-                       break;
-                       }
-               }
-       } else
-               printk(KERN_ERR "tm6000: no frontend found\n");
-
-       dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING
-                                                           | DMX_MEMORY_BASED_FILTERING;
-       dvb->demux.priv = dev;
-       dvb->demux.filternum = 8;
-       dvb->demux.feednum = 8;
-       dvb->demux.start_feed = tm6000_start_feed;
-       dvb->demux.stop_feed = tm6000_stop_feed;
-       dvb->demux.write_to_decoder = NULL;
-       ret = dvb_dmx_init(&dvb->demux);
-       if (ret < 0) {
-               printk(KERN_ERR "tm6000: dvb_dmx_init failed (errno = %d)\n", ret);
-               goto frontend_err;
-       }
-
-       dvb->dmxdev.filternum = dev->dvb->demux.filternum;
-       dvb->dmxdev.demux = &dev->dvb->demux.dmx;
-       dvb->dmxdev.capabilities = 0;
-
-       ret =  dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
-       if (ret < 0) {
-               printk(KERN_ERR "tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret);
-               goto dvb_dmx_err;
-       }
-
-       return 0;
-
-dvb_dmx_err:
-       dvb_dmx_release(&dvb->demux);
-frontend_err:
-       if (dvb->frontend) {
-               dvb_frontend_detach(dvb->frontend);
-               dvb_unregister_frontend(dvb->frontend);
-       }
-adapter_err:
-       dvb_unregister_adapter(&dvb->adapter);
-err:
-       return ret;
-}
-
-static void unregister_dvb(struct tm6000_core *dev)
-{
-       struct tm6000_dvb *dvb = dev->dvb;
-
-       if (dvb->bulk_urb != NULL) {
-               struct urb *bulk_urb = dvb->bulk_urb;
-
-               kfree(bulk_urb->transfer_buffer);
-               bulk_urb->transfer_buffer = NULL;
-               usb_unlink_urb(bulk_urb);
-               usb_free_urb(bulk_urb);
-       }
-
-/*     mutex_lock(&tm6000_driver.open_close_mutex); */
-       if (dvb->frontend) {
-               dvb_frontend_detach(dvb->frontend);
-               dvb_unregister_frontend(dvb->frontend);
-       }
-
-       dvb_dmxdev_release(&dvb->dmxdev);
-       dvb_dmx_release(&dvb->demux);
-       dvb_unregister_adapter(&dvb->adapter);
-       mutex_destroy(&dvb->mutex);
-/*     mutex_unlock(&tm6000_driver.open_close_mutex); */
-}
-
-static int dvb_init(struct tm6000_core *dev)
-{
-       struct tm6000_dvb *dvb;
-       int rc;
-
-       if (!dev)
-               return 0;
-
-       if (!dev->caps.has_dvb)
-               return 0;
-
-       dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL);
-       if (!dvb) {
-               printk(KERN_INFO "Cannot allocate memory\n");
-               return -ENOMEM;
-       }
-
-       dev->dvb = dvb;
-
-       rc = register_dvb(dev);
-       if (rc < 0) {
-               kfree(dvb);
-               dev->dvb = NULL;
-               return 0;
-       }
-
-       return 0;
-}
-
-static int dvb_fini(struct tm6000_core *dev)
-{
-       if (!dev)
-               return 0;
-
-       if (!dev->caps.has_dvb)
-               return 0;
-
-       if (dev->dvb) {
-               unregister_dvb(dev);
-               kfree(dev->dvb);
-               dev->dvb = NULL;
-       }
-
-       return 0;
-}
-
-static struct tm6000_ops dvb_ops = {
-       .type   = TM6000_DVB,
-       .name   = "TM6000 dvb Extension",
-       .init   = dvb_init,
-       .fini   = dvb_fini,
-};
-
-static int __init tm6000_dvb_register(void)
-{
-       return tm6000_register_extension(&dvb_ops);
-}
-
-static void __exit tm6000_dvb_unregister(void)
-{
-       tm6000_unregister_extension(&dvb_ops);
-}
-
-module_init(tm6000_dvb_register);
-module_exit(tm6000_dvb_unregister);
diff --git a/drivers/staging/tm6000/tm6000-i2c.c b/drivers/staging/tm6000/tm6000-i2c.c
deleted file mode 100644 (file)
index 0290bbf..0000000
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- *  tm6000-i2c.c - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
- *     - Fix SMBus Read Byte command
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/usb.h>
-#include <linux/i2c.h>
-
-#include "tm6000.h"
-#include "tm6000-regs.h"
-#include <media/v4l2-common.h>
-#include <media/tuner.h>
-#include "tuner-xc2028.h"
-
-
-/* ----------------------------------------------------------- */
-
-static unsigned int i2c_debug;
-module_param(i2c_debug, int, 0644);
-MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
-
-#define i2c_dprintk(lvl, fmt, args...) if (i2c_debug >= lvl) do { \
-                       printk(KERN_DEBUG "%s at %s: " fmt, \
-                       dev->name, __func__, ##args); } while (0)
-
-static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr,
-                               __u8 reg, char *buf, int len)
-{
-       int rc;
-       unsigned int tsleep;
-       unsigned int i2c_packet_limit = 16;
-
-       if (dev->dev_type == TM6010)
-               i2c_packet_limit = 64;
-
-       if (!buf)
-               return -1;
-
-       if (len < 1 || len > i2c_packet_limit) {
-               printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
-                       len, i2c_packet_limit);
-               return -1;
-       }
-
-       /* capture mutex */
-       rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
-               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
-               addr | reg << 8, 0, buf, len);
-
-       if (rc < 0) {
-               /* release mutex */
-               return rc;
-       }
-
-       /* Calculate delay time, 14000us for 64 bytes */
-       tsleep = ((len * 200) + 200 + 1000) / 1000;
-       msleep(tsleep);
-
-       /* release mutex */
-       return rc;
-}
-
-/* Generic read - doesn't work fine with 16bit registers */
-static int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr,
-                               __u8 reg, char *buf, int len)
-{
-       int rc;
-       u8 b[2];
-       unsigned int i2c_packet_limit = 16;
-
-       if (dev->dev_type == TM6010)
-               i2c_packet_limit = 64;
-
-       if (!buf)
-               return -1;
-
-       if (len < 1 || len > i2c_packet_limit) {
-               printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
-                       len, i2c_packet_limit);
-               return -1;
-       }
-
-       /* capture mutex */
-       if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
-               /*
-                * Workaround an I2C bug when reading from zl10353
-                */
-               reg -= 1;
-               len += 1;
-
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len);
-
-               *buf = b[1];
-       } else {
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
-       }
-
-       /* release mutex */
-       return rc;
-}
-
-/*
- * read from a 16bit register
- * for example xc2028, xc3028 or xc3028L
- */
-static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr,
-                                 __u16 reg, char *buf, int len)
-{
-       int rc;
-       unsigned char ureg;
-
-       if (!buf || len != 2)
-               return -1;
-
-       /* capture mutex */
-       if (dev->dev_type == TM6010) {
-               ureg = reg & 0xFF;
-               rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
-                       USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
-                       addr | (reg & 0xFF00), 0, &ureg, 1);
-
-               if (rc < 0) {
-                       /* release mutex */
-                       return rc;
-               }
-
-               msleep(1400 / 1000);
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
-                       USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
-                       reg, 0, buf, len);
-       } else {
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
-                       USB_RECIP_DEVICE, REQ_14_SET_GET_I2C_WR2_RDN,
-                       addr, reg, buf, len);
-       }
-
-       /* release mutex */
-       return rc;
-}
-
-static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
-                          struct i2c_msg msgs[], int num)
-{
-       struct tm6000_core *dev = i2c_adap->algo_data;
-       int addr, rc, i, byte;
-
-       if (num <= 0)
-               return 0;
-       for (i = 0; i < num; i++) {
-               addr = (msgs[i].addr << 1) & 0xff;
-               i2c_dprintk(2, "%s %s addr=0x%x len=%d:",
-                        (msgs[i].flags & I2C_M_RD) ? "read" : "write",
-                        i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
-               if (msgs[i].flags & I2C_M_RD) {
-                       /* read request without preceding register selection */
-                       /*
-                        * The TM6000 only supports a read transaction
-                        * immediately after a 1 or 2 byte write to select
-                        * a register.  We cannot fulfil this request.
-                        */
-                       i2c_dprintk(2, " read without preceding write not"
-                                      " supported");
-                       rc = -EOPNOTSUPP;
-                       goto err;
-               } else if (i + 1 < num && msgs[i].len <= 2 &&
-                          (msgs[i + 1].flags & I2C_M_RD) &&
-                          msgs[i].addr == msgs[i + 1].addr) {
-                       /* 1 or 2 byte write followed by a read */
-                       if (i2c_debug >= 2)
-                               for (byte = 0; byte < msgs[i].len; byte++)
-                                       printk(KERN_CONT " %02x", msgs[i].buf[byte]);
-                       i2c_dprintk(2, "; joined to read %s len=%d:",
-                                   i == num - 2 ? "stop" : "nonstop",
-                                   msgs[i + 1].len);
-
-                       if (msgs[i].len == 2) {
-                               rc = tm6000_i2c_recv_regs16(dev, addr,
-                                       msgs[i].buf[0] << 8 | msgs[i].buf[1],
-                                       msgs[i + 1].buf, msgs[i + 1].len);
-                       } else {
-                               rc = tm6000_i2c_recv_regs(dev, addr, msgs[i].buf[0],
-                                       msgs[i + 1].buf, msgs[i + 1].len);
-                       }
-
-                       i++;
-
-                       if (addr == dev->tuner_addr << 1) {
-                               tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
-                               tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
-                       }
-                       if (i2c_debug >= 2)
-                               for (byte = 0; byte < msgs[i].len; byte++)
-                                       printk(KERN_CONT " %02x", msgs[i].buf[byte]);
-               } else {
-                       /* write bytes */
-                       if (i2c_debug >= 2)
-                               for (byte = 0; byte < msgs[i].len; byte++)
-                                       printk(KERN_CONT " %02x", msgs[i].buf[byte]);
-                       rc = tm6000_i2c_send_regs(dev, addr, msgs[i].buf[0],
-                               msgs[i].buf + 1, msgs[i].len - 1);
-               }
-               if (i2c_debug >= 2)
-                       printk(KERN_CONT "\n");
-               if (rc < 0)
-                       goto err;
-       }
-
-       return num;
-err:
-       i2c_dprintk(2, " ERROR: %i\n", rc);
-       return rc;
-}
-
-static int tm6000_i2c_eeprom(struct tm6000_core *dev)
-{
-       int i, rc;
-       unsigned char *p = dev->eedata;
-       unsigned char bytes[17];
-
-       dev->i2c_client.addr = 0xa0 >> 1;
-       dev->eedata_size = 0;
-
-       bytes[16] = '\0';
-       for (i = 0; i < sizeof(dev->eedata); ) {
-               *p = i;
-               rc = tm6000_i2c_recv_regs(dev, 0xa0, i, p, 1);
-               if (rc < 1) {
-                       if (p == dev->eedata)
-                               goto noeeprom;
-                       else {
-                               printk(KERN_WARNING
-                               "%s: i2c eeprom read error (err=%d)\n",
-                               dev->name, rc);
-                       }
-                       return -EINVAL;
-               }
-               dev->eedata_size++;
-               p++;
-               if (0 == (i % 16))
-                       printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
-               printk(KERN_CONT " %02x", dev->eedata[i]);
-               if ((dev->eedata[i] >= ' ') && (dev->eedata[i] <= 'z'))
-                       bytes[i%16] = dev->eedata[i];
-               else
-                       bytes[i%16] = '.';
-
-               i++;
-
-               if (0 == (i % 16)) {
-                       bytes[16] = '\0';
-                       printk(KERN_CONT "  %s\n", bytes);
-               }
-       }
-       if (0 != (i%16)) {
-               bytes[i%16] = '\0';
-               for (i %= 16; i < 16; i++)
-                       printk(KERN_CONT "   ");
-               printk(KERN_CONT "  %s\n", bytes);
-       }
-
-       return 0;
-
-noeeprom:
-       printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
-              dev->name, rc);
-       return -EINVAL;
-}
-
-/* ----------------------------------------------------------- */
-
-/*
- * functionality()
- */
-static u32 functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_SMBUS_EMUL;
-}
-
-static const struct i2c_algorithm tm6000_algo = {
-       .master_xfer   = tm6000_i2c_xfer,
-       .functionality = functionality,
-};
-
-/* ----------------------------------------------------------- */
-
-/*
- * tm6000_i2c_register()
- * register i2c bus
- */
-int tm6000_i2c_register(struct tm6000_core *dev)
-{
-       int rc;
-
-       dev->i2c_adap.owner = THIS_MODULE;
-       dev->i2c_adap.algo = &tm6000_algo;
-       dev->i2c_adap.dev.parent = &dev->udev->dev;
-       strlcpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name));
-       dev->i2c_adap.algo_data = dev;
-       i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
-       rc = i2c_add_adapter(&dev->i2c_adap);
-       if (rc)
-               return rc;
-
-       dev->i2c_client.adapter = &dev->i2c_adap;
-       strlcpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE);
-       tm6000_i2c_eeprom(dev);
-
-       return 0;
-}
-
-/*
- * tm6000_i2c_unregister()
- * unregister i2c_bus
- */
-int tm6000_i2c_unregister(struct tm6000_core *dev)
-{
-       i2c_del_adapter(&dev->i2c_adap);
-       return 0;
-}
diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c
deleted file mode 100644 (file)
index 405d127..0000000
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- *  tm6000-input.c - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2010 Stefan Ringel <stefan.ringel@arcor.de>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-
-#include <linux/input.h>
-#include <linux/usb.h>
-
-#include <media/rc-core.h>
-
-#include "tm6000.h"
-#include "tm6000-regs.h"
-
-static unsigned int ir_debug;
-module_param(ir_debug, int, 0644);
-MODULE_PARM_DESC(ir_debug, "enable debug message [IR]");
-
-static unsigned int enable_ir = 1;
-module_param(enable_ir, int, 0644);
-MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)");
-
-/* number of 50ms for ON-OFF-ON power led */
-/* show IR activity */
-#define PWLED_OFF 2
-
-#undef dprintk
-
-#define dprintk(fmt, arg...) \
-       if (ir_debug) { \
-               printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
-       }
-
-struct tm6000_ir_poll_result {
-       u16 rc_data;
-};
-
-struct tm6000_IR {
-       struct tm6000_core      *dev;
-       struct rc_dev           *rc;
-       char                    name[32];
-       char                    phys[32];
-
-       /* poll expernal decoder */
-       int                     polling;
-       struct delayed_work     work;
-       u8                      wait:1;
-       u8                      key:1;
-       u8                      pwled:1;
-       u8                      pwledcnt;
-       u16                     key_addr;
-       struct urb              *int_urb;
-       u8                      *urb_data;
-
-       int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *);
-
-       /* IR device properties */
-       u64                     rc_type;
-};
-
-
-void tm6000_ir_wait(struct tm6000_core *dev, u8 state)
-{
-       struct tm6000_IR *ir = dev->ir;
-
-       if (!dev->ir)
-               return;
-
-       if (state)
-               ir->wait = 1;
-       else
-               ir->wait = 0;
-}
-
-
-static int tm6000_ir_config(struct tm6000_IR *ir)
-{
-       struct tm6000_core *dev = ir->dev;
-       u8 buf[10];
-       int rc;
-
-       switch (ir->rc_type) {
-       case RC_TYPE_NEC:
-               /* Setup IR decoder for NEC standard 12MHz system clock */
-               /* IR_LEADER_CNT = 0.9ms             */
-               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER1, 0xaa);
-               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER0, 0x30);
-               /* IR_PULSE_CNT = 0.7ms              */
-               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20);
-               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0);
-               /* Remote WAKEUP = enable */
-               tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe);
-               /* IR_WKUP_SEL = Low byte in decoded IR data */
-               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff);
-               /* IR_WKU_ADD code */
-               tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_ADD, 0xff);
-               tm6000_flash_led(dev, 0);
-               msleep(100);
-               tm6000_flash_led(dev, 1);
-               break;
-       default:
-               /* hack */
-               buf[0] = 0xff;
-               buf[1] = 0xff;
-               buf[2] = 0xf2;
-               buf[3] = 0x2b;
-               buf[4] = 0x20;
-               buf[5] = 0x35;
-               buf[6] = 0x60;
-               buf[7] = 0x04;
-               buf[8] = 0xc0;
-               buf[9] = 0x08;
-
-               rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
-                       USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a);
-               msleep(100);
-
-               if (rc < 0) {
-                       printk(KERN_INFO "IR configuration failed");
-                       return rc;
-               }
-               break;
-       }
-
-       return 0;
-}
-
-static void tm6000_ir_urb_received(struct urb *urb)
-{
-       struct tm6000_core *dev = urb->context;
-       struct tm6000_IR *ir = dev->ir;
-       int rc;
-
-       if (urb->status != 0)
-               printk(KERN_INFO "not ready\n");
-       else if (urb->actual_length > 0) {
-               memcpy(ir->urb_data, urb->transfer_buffer, urb->actual_length);
-
-               dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0],
-                       ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]);
-
-               ir->key = 1;
-       }
-
-       rc = usb_submit_urb(urb, GFP_ATOMIC);
-}
-
-static int default_polling_getkey(struct tm6000_IR *ir,
-                               struct tm6000_ir_poll_result *poll_result)
-{
-       struct tm6000_core *dev = ir->dev;
-       int rc;
-       u8 buf[2];
-
-       if (ir->wait && !&dev->int_in)
-               return 0;
-
-       if (&dev->int_in) {
-               switch (ir->rc_type) {
-               case RC_TYPE_RC5:
-                       poll_result->rc_data = ir->urb_data[0];
-                       break;
-               case RC_TYPE_NEC:
-                       if (ir->urb_data[1] == ((ir->key_addr >> 8) & 0xff)) {
-                               poll_result->rc_data = ir->urb_data[0]
-                                                       | ir->urb_data[1] << 8;
-                       }
-                       break;
-               default:
-                       poll_result->rc_data = ir->urb_data[0]
-                                       | ir->urb_data[1] << 8;
-                       break;
-               }
-       } else {
-               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
-               msleep(10);
-               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1);
-               msleep(10);
-
-               if (ir->rc_type == RC_TYPE_RC5) {
-                       rc = tm6000_read_write_usb(dev, USB_DIR_IN |
-                               USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                               REQ_02_GET_IR_CODE, 0, 0, buf, 1);
-
-                       msleep(10);
-
-                       dprintk("read data=%02x\n", buf[0]);
-                       if (rc < 0)
-                               return rc;
-
-                       poll_result->rc_data = buf[0];
-               } else {
-                       rc = tm6000_read_write_usb(dev, USB_DIR_IN |
-                               USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                               REQ_02_GET_IR_CODE, 0, 0, buf, 2);
-
-                       msleep(10);
-
-                       dprintk("read data=%04x\n", buf[0] | buf[1] << 8);
-                       if (rc < 0)
-                               return rc;
-
-                       poll_result->rc_data = buf[0] | buf[1] << 8;
-               }
-               if ((poll_result->rc_data & 0x00ff) != 0xff)
-                       ir->key = 1;
-       }
-       return 0;
-}
-
-static void tm6000_ir_handle_key(struct tm6000_IR *ir)
-{
-       struct tm6000_core *dev = ir->dev;
-       int result;
-       struct tm6000_ir_poll_result poll_result;
-
-       /* read the registers containing the IR status */
-       result = ir->get_key(ir, &poll_result);
-       if (result < 0) {
-               printk(KERN_INFO "ir->get_key() failed %d\n", result);
-               return;
-       }
-
-       dprintk("ir->get_key result data=%04x\n", poll_result.rc_data);
-
-       if (ir->pwled) {
-               if (ir->pwledcnt >= PWLED_OFF) {
-                       ir->pwled = 0;
-                       ir->pwledcnt = 0;
-                       tm6000_flash_led(dev, 1);
-               } else
-                       ir->pwledcnt += 1;
-       }
-
-       if (ir->key) {
-               rc_keydown(ir->rc, poll_result.rc_data, 0);
-               ir->key = 0;
-               ir->pwled = 1;
-               ir->pwledcnt = 0;
-               tm6000_flash_led(dev, 0);
-       }
-       return;
-}
-
-static void tm6000_ir_work(struct work_struct *work)
-{
-       struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
-
-       tm6000_ir_handle_key(ir);
-       schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
-}
-
-static int tm6000_ir_start(struct rc_dev *rc)
-{
-       struct tm6000_IR *ir = rc->priv;
-
-       INIT_DELAYED_WORK(&ir->work, tm6000_ir_work);
-       schedule_delayed_work(&ir->work, 0);
-
-       return 0;
-}
-
-static void tm6000_ir_stop(struct rc_dev *rc)
-{
-       struct tm6000_IR *ir = rc->priv;
-
-       cancel_delayed_work_sync(&ir->work);
-}
-
-static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
-{
-       struct tm6000_IR *ir = rc->priv;
-
-       if (!ir)
-               return 0;
-
-       if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC))
-               ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff);
-
-       ir->get_key = default_polling_getkey;
-       ir->rc_type = rc_type;
-
-       tm6000_ir_config(ir);
-       /* TODO */
-       return 0;
-}
-
-int tm6000_ir_int_start(struct tm6000_core *dev)
-{
-       struct tm6000_IR *ir = dev->ir;
-       int pipe, size;
-       int err = -ENOMEM;
-
-
-       if (!ir)
-               return -ENODEV;
-
-       ir->int_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!ir->int_urb)
-               return -ENOMEM;
-
-       pipe = usb_rcvintpipe(dev->udev,
-               dev->int_in.endp->desc.bEndpointAddress
-               & USB_ENDPOINT_NUMBER_MASK);
-
-       size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
-       dprintk("IR max size: %d\n", size);
-
-       ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
-       if (ir->int_urb->transfer_buffer == NULL) {
-               usb_free_urb(ir->int_urb);
-               return err;
-       }
-       dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval);
-       usb_fill_int_urb(ir->int_urb, dev->udev, pipe,
-               ir->int_urb->transfer_buffer, size,
-               tm6000_ir_urb_received, dev,
-               dev->int_in.endp->desc.bInterval);
-       err = usb_submit_urb(ir->int_urb, GFP_KERNEL);
-       if (err) {
-               kfree(ir->int_urb->transfer_buffer);
-               usb_free_urb(ir->int_urb);
-               return err;
-       }
-       ir->urb_data = kzalloc(size, GFP_KERNEL);
-
-       return 0;
-}
-
-void tm6000_ir_int_stop(struct tm6000_core *dev)
-{
-       struct tm6000_IR *ir = dev->ir;
-
-       if (!ir)
-               return;
-
-       usb_kill_urb(ir->int_urb);
-       kfree(ir->int_urb->transfer_buffer);
-       usb_free_urb(ir->int_urb);
-       ir->int_urb = NULL;
-       kfree(ir->urb_data);
-       ir->urb_data = NULL;
-}
-
-int tm6000_ir_init(struct tm6000_core *dev)
-{
-       struct tm6000_IR *ir;
-       struct rc_dev *rc;
-       int err = -ENOMEM;
-
-       if (!enable_ir)
-               return -ENODEV;
-
-       if (!dev->caps.has_remote)
-               return 0;
-
-       if (!dev->ir_codes)
-               return 0;
-
-       ir = kzalloc(sizeof(*ir), GFP_KERNEL);
-       rc = rc_allocate_device();
-       if (!ir || !rc)
-               goto out;
-
-       /* record handles to ourself */
-       ir->dev = dev;
-       dev->ir = ir;
-       ir->rc = rc;
-
-       /* input einrichten */
-       rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
-       rc->priv = ir;
-       rc->change_protocol = tm6000_ir_change_protocol;
-       rc->open = tm6000_ir_start;
-       rc->close = tm6000_ir_stop;
-       rc->driver_type = RC_DRIVER_SCANCODE;
-
-       ir->polling = 50;
-       ir->pwled = 0;
-       ir->pwledcnt = 0;
-
-
-       snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)",
-                                               dev->name);
-
-       usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
-       strlcat(ir->phys, "/input0", sizeof(ir->phys));
-
-       tm6000_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
-
-       rc->input_name = ir->name;
-       rc->input_phys = ir->phys;
-       rc->input_id.bustype = BUS_USB;
-       rc->input_id.version = 1;
-       rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
-       rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
-       rc->map_name = dev->ir_codes;
-       rc->driver_name = "tm6000";
-       rc->dev.parent = &dev->udev->dev;
-
-       if (&dev->int_in) {
-               dprintk("IR over int\n");
-
-               err = tm6000_ir_int_start(dev);
-
-               if (err)
-                       goto out;
-       }
-
-       /* ir register */
-       err = rc_register_device(rc);
-       if (err)
-               goto out;
-
-       return 0;
-
-out:
-       dev->ir = NULL;
-       rc_free_device(rc);
-       kfree(ir);
-       return err;
-}
-
-int tm6000_ir_fini(struct tm6000_core *dev)
-{
-       struct tm6000_IR *ir = dev->ir;
-
-       /* skip detach on non attached board */
-
-       if (!ir)
-               return 0;
-
-       rc_unregister_device(ir->rc);
-
-       if (ir->int_urb)
-               tm6000_ir_int_stop(dev);
-
-       kfree(ir);
-       dev->ir = NULL;
-
-       return 0;
-}
diff --git a/drivers/staging/tm6000/tm6000-regs.h b/drivers/staging/tm6000/tm6000-regs.h
deleted file mode 100644 (file)
index 7f491b6..0000000
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- *  tm6000-regs.h - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * Define TV Master TM5600/TM6000/TM6010 Request codes
- */
-#define REQ_00_SET_IR_VALUE            0
-#define REQ_01_SET_WAKEUP_IRCODE       1
-#define REQ_02_GET_IR_CODE             2
-#define REQ_03_SET_GET_MCU_PIN         3
-#define REQ_04_EN_DISABLE_MCU_INT      4
-#define REQ_05_SET_GET_USBREG          5
-       /* Write: RegNum, Value, 0 */
-       /* Read : RegNum, Value, 1, RegStatus */
-#define REQ_06_SET_GET_USBREG_BIT      6
-#define REQ_07_SET_GET_AVREG           7
-       /* Write: RegNum, Value, 0 */
-       /* Read : RegNum, Value, 1, RegStatus */
-#define REQ_08_SET_GET_AVREG_BIT       8
-#define REQ_09_SET_GET_TUNER_FQ                9
-#define REQ_10_SET_TUNER_SYSTEM                10
-#define REQ_11_SET_EEPROM_ADDR         11
-#define REQ_12_SET_GET_EEPROMBYTE      12
-#define REQ_13_GET_EEPROM_SEQREAD      13
-#define REQ_14_SET_GET_I2C_WR2_RDN     14
-#define REQ_15_SET_GET_I2CBYTE         15
-       /* Write: Subaddr, Slave Addr, value, 0 */
-       /* Read : Subaddr, Slave Addr, value, 1 */
-#define REQ_16_SET_GET_I2C_WR1_RDN     16
-       /* Subaddr, Slave Addr, 0, length */
-#define REQ_17_SET_GET_I2CFP           17
-       /* Write: Slave Addr, register, value */
-       /* Read : Slave Addr, register, 2, data */
-#define REQ_20_DATA_TRANSFER           20
-#define REQ_30_I2C_WRITE               30
-#define REQ_31_I2C_READ                        31
-#define REQ_35_AFTEK_TUNER_READ                35
-#define REQ_40_GET_VERSION             40
-#define REQ_50_SET_START               50
-#define REQ_51_SET_STOP                        51
-#define REQ_52_TRANSMIT_DATA           52
-#define REQ_53_SPI_INITIAL             53
-#define REQ_54_SPI_SETSTART            54
-#define REQ_55_SPI_INOUTDATA           55
-#define REQ_56_SPI_SETSTOP             56
-
-/*
- * Define TV Master TM5600/TM6000/TM6010 GPIO lines
- */
-
-#define TM6000_GPIO_CLK                0x101
-#define TM6000_GPIO_DATA       0x100
-
-#define TM6000_GPIO_1          0x102
-#define TM6000_GPIO_2          0x103
-#define TM6000_GPIO_3          0x104
-#define TM6000_GPIO_4          0x300
-#define TM6000_GPIO_5          0x301
-#define TM6000_GPIO_6          0x304
-#define TM6000_GPIO_7          0x305
-
-/* tm6010 defines GPIO with different values */
-#define TM6010_GPIO_0      0x0102
-#define TM6010_GPIO_1      0x0103
-#define TM6010_GPIO_2      0x0104
-#define TM6010_GPIO_3      0x0105
-#define TM6010_GPIO_4      0x0106
-#define TM6010_GPIO_5      0x0107
-#define TM6010_GPIO_6      0x0300
-#define TM6010_GPIO_7      0x0301
-#define TM6010_GPIO_9      0x0305
-/*
- * Define TV Master TM5600/TM6000/TM6010 URB message codes and length
- */
-
-enum {
-       TM6000_URB_MSG_VIDEO = 1,
-       TM6000_URB_MSG_AUDIO,
-       TM6000_URB_MSG_VBI,
-       TM6000_URB_MSG_PTS,
-       TM6000_URB_MSG_ERR,
-};
-
-/* Define specific TM6000 Video decoder registers */
-#define TM6000_REQ07_RD8_TEST_SEL                      0x07, 0xd8
-#define TM6000_REQ07_RD9_A_SIM_SEL                     0x07, 0xd9
-#define TM6000_REQ07_RDA_CLK_SEL                       0x07, 0xda
-#define TM6000_REQ07_RDB_OUT_SEL                       0x07, 0xdb
-#define TM6000_REQ07_RDC_NSEL_I2S                      0x07, 0xdc
-#define TM6000_REQ07_RDD_GPIO2_MDRV                    0x07, 0xdd
-#define TM6000_REQ07_RDE_GPIO1_MDRV                    0x07, 0xde
-#define TM6000_REQ07_RDF_PWDOWN_ACLK                   0x07, 0xdf
-#define TM6000_REQ07_RE0_VADC_REF_CTL                  0x07, 0xe0
-#define TM6000_REQ07_RE1_VADC_DACLIMP                  0x07, 0xe1
-#define TM6000_REQ07_RE2_VADC_STATUS_CTL               0x07, 0xe2
-#define TM6000_REQ07_RE3_VADC_INP_LPF_SEL1             0x07, 0xe3
-#define TM6000_REQ07_RE4_VADC_TARGET1                  0x07, 0xe4
-#define TM6000_REQ07_RE5_VADC_INP_LPF_SEL2             0x07, 0xe5
-#define TM6000_REQ07_RE6_VADC_TARGET2                  0x07, 0xe6
-#define TM6000_REQ07_RE7_VADC_AGAIN_CTL                        0x07, 0xe7
-#define TM6000_REQ07_RE8_VADC_PWDOWN_CTL               0x07, 0xe8
-#define TM6000_REQ07_RE9_VADC_INPUT_CTL1               0x07, 0xe9
-#define TM6000_REQ07_REA_VADC_INPUT_CTL2               0x07, 0xea
-#define TM6000_REQ07_REB_VADC_AADC_MODE                        0x07, 0xeb
-#define TM6000_REQ07_REC_VADC_AADC_LVOL                        0x07, 0xec
-#define TM6000_REQ07_RED_VADC_AADC_RVOL                        0x07, 0xed
-#define TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL         0x07, 0xee
-#define TM6000_REQ07_REF_VADC_GAIN_MAP_CTL             0x07, 0xef
-#define TM6000_REQ07_RFD_BIST_ERR_VST_LOW              0x07, 0xfd
-#define TM6000_REQ07_RFE_BIST_ERR_VST_HIGH             0x07, 0xfe
-
-/* Define TM6000/TM6010 Video decoder registers */
-#define TM6010_REQ07_R00_VIDEO_CONTROL0                        0x07, 0x00
-#define TM6010_REQ07_R01_VIDEO_CONTROL1                        0x07, 0x01
-#define TM6010_REQ07_R02_VIDEO_CONTROL2                        0x07, 0x02
-#define TM6010_REQ07_R03_YC_SEP_CONTROL                        0x07, 0x03
-#define TM6010_REQ07_R04_LUMA_HAGC_CONTROL             0x07, 0x04
-#define TM6010_REQ07_R05_NOISE_THRESHOLD               0x07, 0x05
-#define TM6010_REQ07_R06_AGC_GATE_THRESHOLD            0x07, 0x06
-#define TM6010_REQ07_R07_OUTPUT_CONTROL                        0x07, 0x07
-#define TM6010_REQ07_R08_LUMA_CONTRAST_ADJ             0x07, 0x08
-#define TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ           0x07, 0x09
-#define TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ         0x07, 0x0a
-#define TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ          0x07, 0x0b
-#define TM6010_REQ07_R0C_CHROMA_AGC_CONTROL            0x07, 0x0c
-#define TM6010_REQ07_R0D_CHROMA_KILL_LEVEL             0x07, 0x0d
-#define TM6010_REQ07_R0F_CHROMA_AUTO_POSITION          0x07, 0x0f
-#define TM6010_REQ07_R10_AGC_PEAK_NOMINAL              0x07, 0x10
-#define TM6010_REQ07_R11_AGC_PEAK_CONTROL              0x07, 0x11
-#define TM6010_REQ07_R12_AGC_GATE_STARTH               0x07, 0x12
-#define TM6010_REQ07_R13_AGC_GATE_STARTL               0x07, 0x13
-#define TM6010_REQ07_R14_AGC_GATE_WIDTH                        0x07, 0x14
-#define TM6010_REQ07_R15_AGC_BP_DELAY                  0x07, 0x15
-#define TM6010_REQ07_R16_LOCK_COUNT                    0x07, 0x16
-#define TM6010_REQ07_R17_HLOOP_MAXSTATE                        0x07, 0x17
-#define TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3         0x07, 0x18
-#define TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2         0x07, 0x19
-#define TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1         0x07, 0x1a
-#define TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0         0x07, 0x1b
-#define TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3          0x07, 0x1c
-#define TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2          0x07, 0x1d
-#define TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1          0x07, 0x1e
-#define TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0          0x07, 0x1f
-#define TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME                0x07, 0x20
-#define TM6010_REQ07_R21_HSYNC_PHASE_OFFSET            0x07, 0x21
-#define TM6010_REQ07_R22_HSYNC_PLL_START_TIME          0x07, 0x22
-#define TM6010_REQ07_R23_HSYNC_PLL_END_TIME            0x07, 0x23
-#define TM6010_REQ07_R24_HSYNC_TIP_START_TIME          0x07, 0x24
-#define TM6010_REQ07_R25_HSYNC_TIP_END_TIME            0x07, 0x25
-#define TM6010_REQ07_R26_HSYNC_RISING_EDGE_START       0x07, 0x26
-#define TM6010_REQ07_R27_HSYNC_RISING_EDGE_END         0x07, 0x27
-#define TM6010_REQ07_R28_BACKPORCH_START               0x07, 0x28
-#define TM6010_REQ07_R29_BACKPORCH_END                 0x07, 0x29
-#define TM6010_REQ07_R2A_HSYNC_FILTER_START            0x07, 0x2a
-#define TM6010_REQ07_R2B_HSYNC_FILTER_END              0x07, 0x2b
-#define TM6010_REQ07_R2C_CHROMA_BURST_START            0x07, 0x2c
-#define TM6010_REQ07_R2D_CHROMA_BURST_END              0x07, 0x2d
-#define TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART           0x07, 0x2e
-#define TM6010_REQ07_R2F_ACTIVE_VIDEO_HWIDTH           0x07, 0x2f
-#define TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART           0x07, 0x30
-#define TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT           0x07, 0x31
-#define TM6010_REQ07_R32_VSYNC_HLOCK_MIN               0x07, 0x32
-#define TM6010_REQ07_R33_VSYNC_HLOCK_MAX               0x07, 0x33
-#define TM6010_REQ07_R34_VSYNC_AGC_MIN                 0x07, 0x34
-#define TM6010_REQ07_R35_VSYNC_AGC_MAX                 0x07, 0x35
-#define TM6010_REQ07_R36_VSYNC_VBI_MIN                 0x07, 0x36
-#define TM6010_REQ07_R37_VSYNC_VBI_MAX                 0x07, 0x37
-#define TM6010_REQ07_R38_VSYNC_THRESHOLD               0x07, 0x38
-#define TM6010_REQ07_R39_VSYNC_TIME_CONSTANT           0x07, 0x39
-#define TM6010_REQ07_R3A_STATUS1                       0x07, 0x3a
-#define TM6010_REQ07_R3B_STATUS2                       0x07, 0x3b
-#define TM6010_REQ07_R3C_STATUS3                       0x07, 0x3c
-#define TM6010_REQ07_R3F_RESET                         0x07, 0x3f
-#define TM6010_REQ07_R40_TELETEXT_VBI_CODE0            0x07, 0x40
-#define TM6010_REQ07_R41_TELETEXT_VBI_CODE1            0x07, 0x41
-#define TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL           0x07, 0x42
-#define TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7           0x07, 0x43
-#define TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8           0x07, 0x44
-#define TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9           0x07, 0x45
-#define TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10          0x07, 0x46
-#define TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11          0x07, 0x47
-#define TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12          0x07, 0x48
-#define TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13          0x07, 0x49
-#define TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14          0x07, 0x4a
-#define TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15          0x07, 0x4b
-#define TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16          0x07, 0x4c
-#define TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17          0x07, 0x4d
-#define TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18          0x07, 0x4e
-#define TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19          0x07, 0x4f
-#define TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20          0x07, 0x50
-#define TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21          0x07, 0x51
-#define TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22          0x07, 0x52
-#define TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23          0x07, 0x53
-#define TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES          0x07, 0x54
-#define TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN          0x07, 0x55
-#define TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN                0x07, 0x56
-#define TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN                0x07, 0x57
-#define TM6010_REQ07_R58_VBI_CAPTION_DTO1              0x07, 0x58
-#define TM6010_REQ07_R59_VBI_CAPTION_DTO0              0x07, 0x59
-#define TM6010_REQ07_R5A_VBI_TELETEXT_DTO1             0x07, 0x5a
-#define TM6010_REQ07_R5B_VBI_TELETEXT_DTO0             0x07, 0x5b
-#define TM6010_REQ07_R5C_VBI_WSS625_DTO1               0x07, 0x5c
-#define TM6010_REQ07_R5D_VBI_WSS625_DTO0               0x07, 0x5d
-#define TM6010_REQ07_R5E_VBI_CAPTION_FRAME_START       0x07, 0x5e
-#define TM6010_REQ07_R5F_VBI_WSS625_FRAME_START                0x07, 0x5f
-#define TM6010_REQ07_R60_TELETEXT_FRAME_START          0x07, 0x60
-#define TM6010_REQ07_R61_VBI_CCDATA1                   0x07, 0x61
-#define TM6010_REQ07_R62_VBI_CCDATA2                   0x07, 0x62
-#define TM6010_REQ07_R63_VBI_WSS625_DATA1              0x07, 0x63
-#define TM6010_REQ07_R64_VBI_WSS625_DATA2              0x07, 0x64
-#define TM6010_REQ07_R65_VBI_DATA_STATUS               0x07, 0x65
-#define TM6010_REQ07_R66_VBI_CAPTION_START             0x07, 0x66
-#define TM6010_REQ07_R67_VBI_WSS625_START              0x07, 0x67
-#define TM6010_REQ07_R68_VBI_TELETEXT_START            0x07, 0x68
-#define TM6010_REQ07_R70_HSYNC_DTO_INC_STATUS3         0x07, 0x70
-#define TM6010_REQ07_R71_HSYNC_DTO_INC_STATUS2         0x07, 0x71
-#define TM6010_REQ07_R72_HSYNC_DTO_INC_STATUS1         0x07, 0x72
-#define TM6010_REQ07_R73_HSYNC_DTO_INC_STATUS0         0x07, 0x73
-#define TM6010_REQ07_R74_CHROMA_DTO_INC_STATUS3                0x07, 0x74
-#define TM6010_REQ07_R75_CHROMA_DTO_INC_STATUS2                0x07, 0x75
-#define TM6010_REQ07_R76_CHROMA_DTO_INC_STATUS1                0x07, 0x76
-#define TM6010_REQ07_R77_CHROMA_DTO_INC_STATUS0                0x07, 0x77
-#define TM6010_REQ07_R78_AGC_AGAIN_STATUS              0x07, 0x78
-#define TM6010_REQ07_R79_AGC_DGAIN_STATUS              0x07, 0x79
-#define TM6010_REQ07_R7A_CHROMA_MAG_STATUS             0x07, 0x7a
-#define TM6010_REQ07_R7B_CHROMA_GAIN_STATUS1           0x07, 0x7b
-#define TM6010_REQ07_R7C_CHROMA_GAIN_STATUS0           0x07, 0x7c
-#define TM6010_REQ07_R7D_CORDIC_FREQ_STATUS            0x07, 0x7d
-#define TM6010_REQ07_R7F_STATUS_NOISE                  0x07, 0x7f
-#define TM6010_REQ07_R80_COMB_FILTER_TRESHOLD          0x07, 0x80
-#define TM6010_REQ07_R82_COMB_FILTER_CONFIG            0x07, 0x82
-#define TM6010_REQ07_R83_CHROMA_LOCK_CONFIG            0x07, 0x83
-#define TM6010_REQ07_R84_NOISE_NTSC_C                  0x07, 0x84
-#define TM6010_REQ07_R85_NOISE_PAL_C                   0x07, 0x85
-#define TM6010_REQ07_R86_NOISE_PHASE_C                 0x07, 0x86
-#define TM6010_REQ07_R87_NOISE_PHASE_Y                 0x07, 0x87
-#define TM6010_REQ07_R8A_CHROMA_LOOPFILTER_STATE       0x07, 0x8a
-#define TM6010_REQ07_R8B_CHROMA_HRESAMPLER             0x07, 0x8b
-#define TM6010_REQ07_R8D_CPUMP_DELAY_ADJ               0x07, 0x8d
-#define TM6010_REQ07_R8E_CPUMP_ADJ                     0x07, 0x8e
-#define TM6010_REQ07_R8F_CPUMP_DELAY                   0x07, 0x8f
-
-/* Define TM6000/TM6010 Miscellaneous registers */
-#define TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE           0x07, 0xc0
-#define TM6010_REQ07_RC1_TRESHOLD                      0x07, 0xc1
-#define TM6010_REQ07_RC2_HSYNC_WIDTH                   0x07, 0xc2
-#define TM6010_REQ07_RC3_HSTART1                       0x07, 0xc3
-#define TM6010_REQ07_RC4_HSTART0                       0x07, 0xc4
-#define TM6010_REQ07_RC5_HEND1                         0x07, 0xc5
-#define TM6010_REQ07_RC6_HEND0                         0x07, 0xc6
-#define TM6010_REQ07_RC7_VSTART1                       0x07, 0xc7
-#define TM6010_REQ07_RC8_VSTART0                       0x07, 0xc8
-#define TM6010_REQ07_RC9_VEND1                         0x07, 0xc9
-#define TM6010_REQ07_RCA_VEND0                         0x07, 0xca
-#define TM6010_REQ07_RCB_DELAY                         0x07, 0xcb
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RCC_ACTIVE_IF                     0x07, 0xcc
-#define TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE (1 << 5)
-#define TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE (1 << 6)
-#define TM6010_REQ07_RD0_USB_PERIPHERY_CONTROL         0x07, 0xd0
-#define TM6010_REQ07_RD1_ADDR_FOR_REQ1                 0x07, 0xd1
-#define TM6010_REQ07_RD2_ADDR_FOR_REQ2                 0x07, 0xd2
-#define TM6010_REQ07_RD3_ADDR_FOR_REQ3                 0x07, 0xd3
-#define TM6010_REQ07_RD4_ADDR_FOR_REQ4                 0x07, 0xd4
-#define TM6010_REQ07_RD5_POWERSAVE                     0x07, 0xd5
-#define TM6010_REQ07_RD6_ENDP_REQ1_REQ2                        0x07, 0xd6
-#define TM6010_REQ07_RD7_ENDP_REQ3_REQ4                        0x07, 0xd7
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR                            0x07, 0xd8
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_BSIZE                      0x07, 0xd9
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_WAKEUP_SEL                 0x07, 0xda
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_WAKEUP_ADD                 0x07, 0xdb
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_LEADER1                    0x07, 0xdc
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_LEADER0                    0x07, 0xdd
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_PULSE_CNT1                 0x07, 0xde
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR_PULSE_CNT0                 0x07, 0xdf
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE0_DVIDEO_SOURCE                 0x07, 0xe0
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE0_DVIDEO_SOURCE_IF              0x07, 0xe1
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE2_OUT_SEL2                      0x07, 0xe2
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE3_OUT_SEL1                      0x07, 0xe3
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE4_OUT_SEL0                      0x07, 0xe4
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE5_REMOTE_WAKEUP                 0x07, 0xe5
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE7_PUB_GPIO                      0x07, 0xe7
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE8_TYPESEL_MOS_I2S               0x07, 0xe8
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE9_TYPESEL_MOS_TS                        0x07, 0xe9
-/* ONLY for TM6010 */
-#define TM6010_REQ07_REA_TYPESEL_MOS_CCIR              0x07, 0xea
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF0_BIST_CRC_RESULT0              0x07, 0xf0
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF1_BIST_CRC_RESULT1              0x07, 0xf1
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF2_BIST_CRC_RESULT2              0x07, 0xf2
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF3_BIST_CRC_RESULT3              0x07, 0xf3
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF4_BIST_ERR_VST2                 0x07, 0xf4
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF5_BIST_ERR_VST1                 0x07, 0xf5
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF6_BIST_ERR_VST0                 0x07, 0xf6
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF7_BIST                          0x07, 0xf7
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RFE_POWER_DOWN                    0x07, 0xfe
-#define TM6010_REQ07_RFF_SOFT_RESET                    0x07, 0xff
-
-/* Define TM6000/TM6010 USB registers */
-#define TM6010_REQ05_R00_MAIN_CTRL             0x05, 0x00
-#define TM6010_REQ05_R01_DEVADDR               0x05, 0x01
-#define TM6010_REQ05_R02_TEST                  0x05, 0x02
-#define TM6010_REQ05_R04_SOFN0                 0x05, 0x04
-#define TM6010_REQ05_R05_SOFN1                 0x05, 0x05
-#define TM6010_REQ05_R06_SOFTM0                        0x05, 0x06
-#define TM6010_REQ05_R07_SOFTM1                        0x05, 0x07
-#define TM6010_REQ05_R08_PHY_TEST              0x05, 0x08
-#define TM6010_REQ05_R09_VCTL                  0x05, 0x09
-#define TM6010_REQ05_R0A_VSTA                  0x05, 0x0a
-#define TM6010_REQ05_R0B_CX_CFG                        0x05, 0x0b
-#define TM6010_REQ05_R0C_ENDP0_REG0            0x05, 0x0c
-#define TM6010_REQ05_R10_GMASK                 0x05, 0x10
-#define TM6010_REQ05_R11_IMASK0                        0x05, 0x11
-#define TM6010_REQ05_R12_IMASK1                        0x05, 0x12
-#define TM6010_REQ05_R13_IMASK2                        0x05, 0x13
-#define TM6010_REQ05_R14_IMASK3                        0x05, 0x14
-#define TM6010_REQ05_R15_IMASK4                        0x05, 0x15
-#define TM6010_REQ05_R16_IMASK5                        0x05, 0x16
-#define TM6010_REQ05_R17_IMASK6                        0x05, 0x17
-#define TM6010_REQ05_R18_IMASK7                        0x05, 0x18
-#define TM6010_REQ05_R19_ZEROP0                        0x05, 0x19
-#define TM6010_REQ05_R1A_ZEROP1                        0x05, 0x1a
-#define TM6010_REQ05_R1C_FIFO_EMP0             0x05, 0x1c
-#define TM6010_REQ05_R1D_FIFO_EMP1             0x05, 0x1d
-#define TM6010_REQ05_R20_IRQ_GROUP             0x05, 0x20
-#define TM6010_REQ05_R21_IRQ_SOURCE0           0x05, 0x21
-#define TM6010_REQ05_R22_IRQ_SOURCE1           0x05, 0x22
-#define TM6010_REQ05_R23_IRQ_SOURCE2           0x05, 0x23
-#define TM6010_REQ05_R24_IRQ_SOURCE3           0x05, 0x24
-#define TM6010_REQ05_R25_IRQ_SOURCE4           0x05, 0x25
-#define TM6010_REQ05_R26_IRQ_SOURCE5           0x05, 0x26
-#define TM6010_REQ05_R27_IRQ_SOURCE6           0x05, 0x27
-#define TM6010_REQ05_R28_IRQ_SOURCE7           0x05, 0x28
-#define TM6010_REQ05_R29_SEQ_ERR0              0x05, 0x29
-#define TM6010_REQ05_R2A_SEQ_ERR1              0x05, 0x2a
-#define TM6010_REQ05_R2B_SEQ_ABORT0            0x05, 0x2b
-#define TM6010_REQ05_R2C_SEQ_ABORT1            0x05, 0x2c
-#define TM6010_REQ05_R2D_TX_ZERO0              0x05, 0x2d
-#define TM6010_REQ05_R2E_TX_ZERO1              0x05, 0x2e
-#define TM6010_REQ05_R2F_IDLE_CNT              0x05, 0x2f
-#define TM6010_REQ05_R30_FNO_P1                        0x05, 0x30
-#define TM6010_REQ05_R31_FNO_P2                        0x05, 0x31
-#define TM6010_REQ05_R32_FNO_P3                        0x05, 0x32
-#define TM6010_REQ05_R33_FNO_P4                        0x05, 0x33
-#define TM6010_REQ05_R34_FNO_P5                        0x05, 0x34
-#define TM6010_REQ05_R35_FNO_P6                        0x05, 0x35
-#define TM6010_REQ05_R36_FNO_P7                        0x05, 0x36
-#define TM6010_REQ05_R37_FNO_P8                        0x05, 0x37
-#define TM6010_REQ05_R38_FNO_P9                        0x05, 0x38
-#define TM6010_REQ05_R30_FNO_P10               0x05, 0x39
-#define TM6010_REQ05_R30_FNO_P11               0x05, 0x3a
-#define TM6010_REQ05_R30_FNO_P12               0x05, 0x3b
-#define TM6010_REQ05_R30_FNO_P13               0x05, 0x3c
-#define TM6010_REQ05_R30_FNO_P14               0x05, 0x3d
-#define TM6010_REQ05_R30_FNO_P15               0x05, 0x3e
-#define TM6010_REQ05_R40_IN_MAXPS_LOW1         0x05, 0x40
-#define TM6010_REQ05_R41_IN_MAXPS_HIGH1                0x05, 0x41
-#define TM6010_REQ05_R42_IN_MAXPS_LOW2         0x05, 0x42
-#define TM6010_REQ05_R43_IN_MAXPS_HIGH2                0x05, 0x43
-#define TM6010_REQ05_R44_IN_MAXPS_LOW3         0x05, 0x44
-#define TM6010_REQ05_R45_IN_MAXPS_HIGH3                0x05, 0x45
-#define TM6010_REQ05_R46_IN_MAXPS_LOW4         0x05, 0x46
-#define TM6010_REQ05_R47_IN_MAXPS_HIGH4                0x05, 0x47
-#define TM6010_REQ05_R48_IN_MAXPS_LOW5         0x05, 0x48
-#define TM6010_REQ05_R49_IN_MAXPS_HIGH5                0x05, 0x49
-#define TM6010_REQ05_R4A_IN_MAXPS_LOW6         0x05, 0x4a
-#define TM6010_REQ05_R4B_IN_MAXPS_HIGH6                0x05, 0x4b
-#define TM6010_REQ05_R4C_IN_MAXPS_LOW7         0x05, 0x4c
-#define TM6010_REQ05_R4D_IN_MAXPS_HIGH7                0x05, 0x4d
-#define TM6010_REQ05_R4E_IN_MAXPS_LOW8         0x05, 0x4e
-#define TM6010_REQ05_R4F_IN_MAXPS_HIGH8                0x05, 0x4f
-#define TM6010_REQ05_R50_IN_MAXPS_LOW9         0x05, 0x50
-#define TM6010_REQ05_R51_IN_MAXPS_HIGH9                0x05, 0x51
-#define TM6010_REQ05_R40_IN_MAXPS_LOW10                0x05, 0x52
-#define TM6010_REQ05_R41_IN_MAXPS_HIGH10       0x05, 0x53
-#define TM6010_REQ05_R40_IN_MAXPS_LOW11                0x05, 0x54
-#define TM6010_REQ05_R41_IN_MAXPS_HIGH11       0x05, 0x55
-#define TM6010_REQ05_R40_IN_MAXPS_LOW12                0x05, 0x56
-#define TM6010_REQ05_R41_IN_MAXPS_HIGH12       0x05, 0x57
-#define TM6010_REQ05_R40_IN_MAXPS_LOW13                0x05, 0x58
-#define TM6010_REQ05_R41_IN_MAXPS_HIGH13       0x05, 0x59
-#define TM6010_REQ05_R40_IN_MAXPS_LOW14                0x05, 0x5a
-#define TM6010_REQ05_R41_IN_MAXPS_HIGH14       0x05, 0x5b
-#define TM6010_REQ05_R40_IN_MAXPS_LOW15                0x05, 0x5c
-#define TM6010_REQ05_R41_IN_MAXPS_HIGH15       0x05, 0x5d
-#define TM6010_REQ05_R60_OUT_MAXPS_LOW1                0x05, 0x60
-#define TM6010_REQ05_R61_OUT_MAXPS_HIGH1       0x05, 0x61
-#define TM6010_REQ05_R62_OUT_MAXPS_LOW2                0x05, 0x62
-#define TM6010_REQ05_R63_OUT_MAXPS_HIGH2       0x05, 0x63
-#define TM6010_REQ05_R64_OUT_MAXPS_LOW3                0x05, 0x64
-#define TM6010_REQ05_R65_OUT_MAXPS_HIGH3       0x05, 0x65
-#define TM6010_REQ05_R66_OUT_MAXPS_LOW4                0x05, 0x66
-#define TM6010_REQ05_R67_OUT_MAXPS_HIGH4       0x05, 0x67
-#define TM6010_REQ05_R68_OUT_MAXPS_LOW5                0x05, 0x68
-#define TM6010_REQ05_R69_OUT_MAXPS_HIGH5       0x05, 0x69
-#define TM6010_REQ05_R6A_OUT_MAXPS_LOW6                0x05, 0x6a
-#define TM6010_REQ05_R6B_OUT_MAXPS_HIGH6       0x05, 0x6b
-#define TM6010_REQ05_R6C_OUT_MAXPS_LOW7                0x05, 0x6c
-#define TM6010_REQ05_R6D_OUT_MAXPS_HIGH7       0x05, 0x6d
-#define TM6010_REQ05_R6E_OUT_MAXPS_LOW8                0x05, 0x6e
-#define TM6010_REQ05_R6F_OUT_MAXPS_HIGH8       0x05, 0x6f
-#define TM6010_REQ05_R70_OUT_MAXPS_LOW9                0x05, 0x70
-#define TM6010_REQ05_R71_OUT_MAXPS_HIGH9       0x05, 0x71
-#define TM6010_REQ05_R60_OUT_MAXPS_LOW10       0x05, 0x72
-#define TM6010_REQ05_R61_OUT_MAXPS_HIGH10      0x05, 0x73
-#define TM6010_REQ05_R60_OUT_MAXPS_LOW11       0x05, 0x74
-#define TM6010_REQ05_R61_OUT_MAXPS_HIGH11      0x05, 0x75
-#define TM6010_REQ05_R60_OUT_MAXPS_LOW12       0x05, 0x76
-#define TM6010_REQ05_R61_OUT_MAXPS_HIGH12      0x05, 0x77
-#define TM6010_REQ05_R60_OUT_MAXPS_LOW13       0x05, 0x78
-#define TM6010_REQ05_R61_OUT_MAXPS_HIGH13      0x05, 0x79
-#define TM6010_REQ05_R60_OUT_MAXPS_LOW14       0x05, 0x7a
-#define TM6010_REQ05_R61_OUT_MAXPS_HIGH14      0x05, 0x7b
-#define TM6010_REQ05_R60_OUT_MAXPS_LOW15       0x05, 0x7c
-#define TM6010_REQ05_R61_OUT_MAXPS_HIGH15      0x05, 0x7d
-#define TM6010_REQ05_R80_FIFO0                 0x05, 0x80
-#define TM6010_REQ05_R81_FIFO1                 0x05, 0x81
-#define TM6010_REQ05_R82_FIFO2                 0x05, 0x82
-#define TM6010_REQ05_R83_FIFO3                 0x05, 0x83
-#define TM6010_REQ05_R84_FIFO4                 0x05, 0x84
-#define TM6010_REQ05_R85_FIFO5                 0x05, 0x85
-#define TM6010_REQ05_R86_FIFO6                 0x05, 0x86
-#define TM6010_REQ05_R87_FIFO7                 0x05, 0x87
-#define TM6010_REQ05_R88_FIFO8                 0x05, 0x88
-#define TM6010_REQ05_R89_FIFO9                 0x05, 0x89
-#define TM6010_REQ05_R81_FIFO10                        0x05, 0x8a
-#define TM6010_REQ05_R81_FIFO11                        0x05, 0x8b
-#define TM6010_REQ05_R81_FIFO12                        0x05, 0x8c
-#define TM6010_REQ05_R81_FIFO13                        0x05, 0x8d
-#define TM6010_REQ05_R81_FIFO14                        0x05, 0x8e
-#define TM6010_REQ05_R81_FIFO15                        0x05, 0x8f
-#define TM6010_REQ05_R90_CFG_FIFO0             0x05, 0x90
-#define TM6010_REQ05_R91_CFG_FIFO1             0x05, 0x91
-#define TM6010_REQ05_R92_CFG_FIFO2             0x05, 0x92
-#define TM6010_REQ05_R93_CFG_FIFO3             0x05, 0x93
-#define TM6010_REQ05_R94_CFG_FIFO4             0x05, 0x94
-#define TM6010_REQ05_R95_CFG_FIFO5             0x05, 0x95
-#define TM6010_REQ05_R96_CFG_FIFO6             0x05, 0x96
-#define TM6010_REQ05_R97_CFG_FIFO7             0x05, 0x97
-#define TM6010_REQ05_R98_CFG_FIFO8             0x05, 0x98
-#define TM6010_REQ05_R99_CFG_FIFO9             0x05, 0x99
-#define TM6010_REQ05_R91_CFG_FIFO10            0x05, 0x9a
-#define TM6010_REQ05_R91_CFG_FIFO11            0x05, 0x9b
-#define TM6010_REQ05_R91_CFG_FIFO12            0x05, 0x9c
-#define TM6010_REQ05_R91_CFG_FIFO13            0x05, 0x9d
-#define TM6010_REQ05_R91_CFG_FIFO14            0x05, 0x9e
-#define TM6010_REQ05_R91_CFG_FIFO15            0x05, 0x9f
-#define TM6010_REQ05_RA0_CTL_FIFO0             0x05, 0xa0
-#define TM6010_REQ05_RA1_CTL_FIFO1             0x05, 0xa1
-#define TM6010_REQ05_RA2_CTL_FIFO2             0x05, 0xa2
-#define TM6010_REQ05_RA3_CTL_FIFO3             0x05, 0xa3
-#define TM6010_REQ05_RA4_CTL_FIFO4             0x05, 0xa4
-#define TM6010_REQ05_RA5_CTL_FIFO5             0x05, 0xa5
-#define TM6010_REQ05_RA6_CTL_FIFO6             0x05, 0xa6
-#define TM6010_REQ05_RA7_CTL_FIFO7             0x05, 0xa7
-#define TM6010_REQ05_RA8_CTL_FIFO8             0x05, 0xa8
-#define TM6010_REQ05_RA9_CTL_FIFO9             0x05, 0xa9
-#define TM6010_REQ05_RA1_CTL_FIFO10            0x05, 0xaa
-#define TM6010_REQ05_RA1_CTL_FIFO11            0x05, 0xab
-#define TM6010_REQ05_RA1_CTL_FIFO12            0x05, 0xac
-#define TM6010_REQ05_RA1_CTL_FIFO13            0x05, 0xad
-#define TM6010_REQ05_RA1_CTL_FIFO14            0x05, 0xae
-#define TM6010_REQ05_RA1_CTL_FIFO15            0x05, 0xaf
-#define TM6010_REQ05_RB0_BC_LOW_FIFO0          0x05, 0xb0
-#define TM6010_REQ05_RB1_BC_LOW_FIFO1          0x05, 0xb1
-#define TM6010_REQ05_RB2_BC_LOW_FIFO2          0x05, 0xb2
-#define TM6010_REQ05_RB3_BC_LOW_FIFO3          0x05, 0xb3
-#define TM6010_REQ05_RB4_BC_LOW_FIFO4          0x05, 0xb4
-#define TM6010_REQ05_RB5_BC_LOW_FIFO5          0x05, 0xb5
-#define TM6010_REQ05_RB6_BC_LOW_FIFO6          0x05, 0xb6
-#define TM6010_REQ05_RB7_BC_LOW_FIFO7          0x05, 0xb7
-#define TM6010_REQ05_RB8_BC_LOW_FIFO8          0x05, 0xb8
-#define TM6010_REQ05_RB9_BC_LOW_FIFO9          0x05, 0xb9
-#define TM6010_REQ05_RB1_BC_LOW_FIFO10         0x05, 0xba
-#define TM6010_REQ05_RB1_BC_LOW_FIFO11         0x05, 0xbb
-#define TM6010_REQ05_RB1_BC_LOW_FIFO12         0x05, 0xbc
-#define TM6010_REQ05_RB1_BC_LOW_FIFO13         0x05, 0xbd
-#define TM6010_REQ05_RB1_BC_LOW_FIFO14         0x05, 0xbe
-#define TM6010_REQ05_RB1_BC_LOW_FIFO15         0x05, 0xbf
-#define TM6010_REQ05_RC0_DATA_FIFO0            0x05, 0xc0
-#define TM6010_REQ05_RC4_DATA_FIFO1            0x05, 0xc4
-#define TM6010_REQ05_RC8_DATA_FIFO2            0x05, 0xc8
-#define TM6010_REQ05_RCC_DATA_FIFO3            0x05, 0xcc
-#define TM6010_REQ05_RD0_DATA_FIFO4            0x05, 0xd0
-#define TM6010_REQ05_RD4_DATA_FIFO5            0x05, 0xd4
-#define TM6010_REQ05_RD8_DATA_FIFO6            0x05, 0xd8
-#define TM6010_REQ05_RDC_DATA_FIFO7            0x05, 0xdc
-#define TM6010_REQ05_RE0_DATA_FIFO8            0x05, 0xe0
-#define TM6010_REQ05_RE4_DATA_FIFO9            0x05, 0xe4
-#define TM6010_REQ05_RC4_DATA_FIFO10           0x05, 0xe8
-#define TM6010_REQ05_RC4_DATA_FIFO11           0x05, 0xec
-#define TM6010_REQ05_RC4_DATA_FIFO12           0x05, 0xf0
-#define TM6010_REQ05_RC4_DATA_FIFO13           0x05, 0xf4
-#define TM6010_REQ05_RC4_DATA_FIFO14           0x05, 0xf8
-#define TM6010_REQ05_RC4_DATA_FIFO15           0x05, 0xfc
-
-/* Define TM6010 Audio decoder registers */
-/* This core available only in TM6010 */
-#define TM6010_REQ08_R00_A_VERSION             0x08, 0x00
-#define TM6010_REQ08_R01_A_INIT                        0x08, 0x01
-#define TM6010_REQ08_R02_A_FIX_GAIN_CTRL       0x08, 0x02
-#define TM6010_REQ08_R03_A_AUTO_GAIN_CTRL      0x08, 0x03
-#define TM6010_REQ08_R04_A_SIF_AMP_CTRL                0x08, 0x04
-#define TM6010_REQ08_R05_A_STANDARD_MOD                0x08, 0x05
-#define TM6010_REQ08_R06_A_SOUND_MOD           0x08, 0x06
-#define TM6010_REQ08_R07_A_LEFT_VOL            0x08, 0x07
-#define TM6010_REQ08_R08_A_RIGHT_VOL           0x08, 0x08
-#define TM6010_REQ08_R09_A_MAIN_VOL            0x08, 0x09
-#define TM6010_REQ08_R0A_A_I2S_MOD             0x08, 0x0a
-#define TM6010_REQ08_R0B_A_ASD_THRES1          0x08, 0x0b
-#define TM6010_REQ08_R0C_A_ASD_THRES2          0x08, 0x0c
-#define TM6010_REQ08_R0D_A_AMD_THRES           0x08, 0x0d
-#define TM6010_REQ08_R0E_A_MONO_THRES1         0x08, 0x0e
-#define TM6010_REQ08_R0F_A_MONO_THRES2         0x08, 0x0f
-#define TM6010_REQ08_R10_A_MUTE_THRES1         0x08, 0x10
-#define TM6010_REQ08_R11_A_MUTE_THRES2         0x08, 0x11
-#define TM6010_REQ08_R12_A_AGC_U               0x08, 0x12
-#define TM6010_REQ08_R13_A_AGC_ERR_T           0x08, 0x13
-#define TM6010_REQ08_R14_A_AGC_GAIN_INIT       0x08, 0x14
-#define TM6010_REQ08_R15_A_AGC_STEP_THR                0x08, 0x15
-#define TM6010_REQ08_R16_A_AGC_GAIN_MAX                0x08, 0x16
-#define TM6010_REQ08_R17_A_AGC_GAIN_MIN                0x08, 0x17
-#define TM6010_REQ08_R18_A_TR_CTRL             0x08, 0x18
-#define TM6010_REQ08_R19_A_FH_2FH_GAIN         0x08, 0x19
-#define TM6010_REQ08_R1A_A_NICAM_SER_MAX       0x08, 0x1a
-#define TM6010_REQ08_R1B_A_NICAM_SER_MIN       0x08, 0x1b
-#define TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT     0x08, 0x1e
-#define TM6010_REQ08_R1F_A_TEST_INTF_SEL       0x08, 0x1f
-#define TM6010_REQ08_R20_A_TEST_PIN_SEL                0x08, 0x20
-#define TM6010_REQ08_R21_A_AGC_ERR             0x08, 0x21
-#define TM6010_REQ08_R22_A_AGC_GAIN            0x08, 0x22
-#define TM6010_REQ08_R23_A_NICAM_INFO          0x08, 0x23
-#define TM6010_REQ08_R24_A_SER                 0x08, 0x24
-#define TM6010_REQ08_R25_A_C1_AMP              0x08, 0x25
-#define TM6010_REQ08_R26_A_C2_AMP              0x08, 0x26
-#define TM6010_REQ08_R27_A_NOISE_AMP           0x08, 0x27
-#define TM6010_REQ08_R28_A_AUDIO_MODE_RES      0x08, 0x28
-
-/* Define TM6010 Video ADC registers */
-#define TM6010_REQ08_RE0_ADC_REF               0x08, 0xe0
-#define TM6010_REQ08_RE1_DAC_CLMP              0x08, 0xe1
-#define TM6010_REQ08_RE2_POWER_DOWN_CTRL1      0x08, 0xe2
-#define TM6010_REQ08_RE3_ADC_IN1_SEL           0x08, 0xe3
-#define TM6010_REQ08_RE4_ADC_IN2_SEL           0x08, 0xe4
-#define TM6010_REQ08_RE5_GAIN_PARAM            0x08, 0xe5
-#define TM6010_REQ08_RE6_POWER_DOWN_CTRL2      0x08, 0xe6
-#define TM6010_REQ08_RE7_REG_GAIN_Y            0x08, 0xe7
-#define TM6010_REQ08_RE8_REG_GAIN_C            0x08, 0xe8
-#define TM6010_REQ08_RE9_BIAS_CTRL             0x08, 0xe9
-#define TM6010_REQ08_REA_BUFF_DRV_CTRL         0x08, 0xea
-#define TM6010_REQ08_REB_SIF_GAIN_CTRL         0x08, 0xeb
-#define TM6010_REQ08_REC_REVERSE_YC_CTRL       0x08, 0xec
-#define TM6010_REQ08_RED_GAIN_SEL              0x08, 0xed
-
-/* Define TM6010 Audio ADC registers */
-#define TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG   0x08, 0xf0
-#define TM6010_REQ08_RF1_AADC_POWER_DOWN       0x08, 0xf1
-#define TM6010_REQ08_RF2_LEFT_CHANNEL_VOL      0x08, 0xf2
-#define TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL     0x08, 0xf3
diff --git a/drivers/staging/tm6000/tm6000-stds.c b/drivers/staging/tm6000/tm6000-stds.c
deleted file mode 100644 (file)
index 9a4145d..0000000
+++ /dev/null
@@ -1,659 +0,0 @@
-/*
- *  tm6000-stds.c - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2007 Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include "tm6000.h"
-#include "tm6000-regs.h"
-
-static unsigned int tm6010_a_mode;
-module_param(tm6010_a_mode, int, 0644);
-MODULE_PARM_DESC(tm6010_a_mode, "set tm6010 sif audio mode");
-
-struct tm6000_reg_settings {
-       unsigned char req;
-       unsigned char reg;
-       unsigned char value;
-};
-
-
-struct tm6000_std_settings {
-       v4l2_std_id id;
-       struct tm6000_reg_settings *common;
-};
-
-static struct tm6000_reg_settings composite_pal_m[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x04 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x20 },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings composite_pal_nc[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x36 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings composite_pal[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x32 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings composite_secam[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x38 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings composite_ntsc[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_std_settings composite_stds[] = {
-       { .id = V4L2_STD_PAL_M, .common = composite_pal_m, },
-       { .id = V4L2_STD_PAL_Nc, .common = composite_pal_nc, },
-       { .id = V4L2_STD_PAL, .common = composite_pal, },
-       { .id = V4L2_STD_SECAM, .common = composite_secam, },
-       { .id = V4L2_STD_NTSC, .common = composite_ntsc, },
-};
-
-static struct tm6000_reg_settings svideo_pal_m[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x05 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings svideo_pal_nc[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x37 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings svideo_pal[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x33 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings svideo_secam[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x39 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings svideo_ntsc[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x01 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 },
-       { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0x8b },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_std_settings svideo_stds[] = {
-       { .id = V4L2_STD_PAL_M, .common = svideo_pal_m, },
-       { .id = V4L2_STD_PAL_Nc, .common = svideo_pal_nc, },
-       { .id = V4L2_STD_PAL, .common = svideo_pal, },
-       { .id = V4L2_STD_SECAM, .common = svideo_secam, },
-       { .id = V4L2_STD_NTSC, .common = svideo_ntsc, },
-};
-
-static int tm6000_set_audio_std(struct tm6000_core *dev)
-{
-       uint8_t areg_02 = 0x04; /* GC1 Fixed gain 0dB */
-       uint8_t areg_05 = 0x01; /* Auto 4.5 = M Japan, Auto 6.5 = DK */
-       uint8_t areg_06 = 0x02; /* Auto de-emphasis, mannual channel mode */
-       uint8_t nicam_flag = 0; /* No NICAM */
-
-       if (dev->radio) {
-               tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00);
-               tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, 0x04);
-               tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00);
-               tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0x80);
-               tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, 0x0c);
-               /* set mono or stereo */
-               if (dev->amode == V4L2_TUNER_MODE_MONO)
-                       tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x00);
-               else if (dev->amode == V4L2_TUNER_MODE_STEREO)
-                       tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x02);
-               tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x18);
-               tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x0a);
-               tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x40);
-               tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe);
-               tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13);
-               tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80);
-               tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0xff);
-               return 0;
-       }
-
-       switch (tm6010_a_mode) {
-       /* auto */
-       case 0:
-               switch (dev->norm) {
-               case V4L2_STD_NTSC_M_KR:
-                       areg_05 |= 0x00;
-                       break;
-               case V4L2_STD_NTSC_M_JP:
-                       areg_05 |= 0x40;
-                       break;
-               case V4L2_STD_NTSC_M:
-               case V4L2_STD_PAL_M:
-               case V4L2_STD_PAL_N:
-                       areg_05 |= 0x20;
-                       break;
-               case V4L2_STD_PAL_Nc:
-                       areg_05 |= 0x60;
-                       break;
-               case V4L2_STD_SECAM_L:
-                       areg_05 |= 0x00;
-                       break;
-               case V4L2_STD_DK:
-                       areg_05 |= 0x10;
-                       break;
-               }
-               break;
-       /* A2 */
-       case 1:
-               switch (dev->norm) {
-               case V4L2_STD_B:
-               case V4L2_STD_GH:
-                       areg_05 = 0x05;
-                       break;
-               case V4L2_STD_DK:
-                       areg_05 = 0x09;
-                       break;
-               }
-               break;
-       /* NICAM */
-       case 2:
-               switch (dev->norm) {
-               case V4L2_STD_B:
-               case V4L2_STD_GH:
-                       areg_05 = 0x07;
-                       break;
-               case V4L2_STD_DK:
-                       areg_05 = 0x06;
-                       break;
-               case V4L2_STD_PAL_I:
-                       areg_05 = 0x08;
-                       break;
-               case V4L2_STD_SECAM_L:
-                       areg_05 = 0x0a;
-                       areg_02 = 0x02;
-                       break;
-               }
-               nicam_flag = 1;
-               break;
-       /* other */
-       case 3:
-               switch (dev->norm) {
-               /* DK3_A2 */
-               case V4L2_STD_DK:
-                       areg_05 = 0x0b;
-                       break;
-               /* Korea */
-               case V4L2_STD_NTSC_M_KR:
-                       areg_05 = 0x04;
-                       break;
-               /* EIAJ */
-               case V4L2_STD_NTSC_M_JP:
-                       areg_05 = 0x03;
-                       break;
-               default:
-                       areg_05 = 0x02;
-                       break;
-               }
-               break;
-       }
-
-       tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00);
-       tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, areg_02);
-       tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00);
-       tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0xa0);
-       tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, areg_05);
-       tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, areg_06);
-       tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, 0x00);
-       tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, 0x00);
-       tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x08);
-       tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, 0x91);
-       tm6000_set_reg(dev, TM6010_REQ08_R0B_A_ASD_THRES1, 0x20);
-       tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x12);
-       tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x20);
-       tm6000_set_reg(dev, TM6010_REQ08_R0E_A_MONO_THRES1, 0xf0);
-       tm6000_set_reg(dev, TM6010_REQ08_R0F_A_MONO_THRES2, 0x80);
-       tm6000_set_reg(dev, TM6010_REQ08_R10_A_MUTE_THRES1, 0xc0);
-       tm6000_set_reg(dev, TM6010_REQ08_R11_A_MUTE_THRES2, 0x80);
-       tm6000_set_reg(dev, TM6010_REQ08_R12_A_AGC_U, 0x12);
-       tm6000_set_reg(dev, TM6010_REQ08_R13_A_AGC_ERR_T, 0xfe);
-       tm6000_set_reg(dev, TM6010_REQ08_R14_A_AGC_GAIN_INIT, 0x20);
-       tm6000_set_reg(dev, TM6010_REQ08_R15_A_AGC_STEP_THR, 0x14);
-       tm6000_set_reg(dev, TM6010_REQ08_R16_A_AGC_GAIN_MAX, 0xfe);
-       tm6000_set_reg(dev, TM6010_REQ08_R17_A_AGC_GAIN_MIN, 0x01);
-       tm6000_set_reg(dev, TM6010_REQ08_R18_A_TR_CTRL, 0xa0);
-       tm6000_set_reg(dev, TM6010_REQ08_R19_A_FH_2FH_GAIN, 0x32);
-       tm6000_set_reg(dev, TM6010_REQ08_R1A_A_NICAM_SER_MAX, 0x64);
-       tm6000_set_reg(dev, TM6010_REQ08_R1B_A_NICAM_SER_MIN, 0x20);
-       tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1c, 0x00);
-       tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1d, 0x00);
-       tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13);
-       tm6000_set_reg(dev, TM6010_REQ08_R1F_A_TEST_INTF_SEL, 0x00);
-       tm6000_set_reg(dev, TM6010_REQ08_R20_A_TEST_PIN_SEL, 0x00);
-       tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80);
-
-       return 0;
-}
-
-void tm6000_get_std_res(struct tm6000_core *dev)
-{
-       /* Currently, those are the only supported resoltions */
-       if (dev->norm & V4L2_STD_525_60)
-               dev->height = 480;
-       else
-               dev->height = 576;
-
-       dev->width = 720;
-}
-
-static int tm6000_load_std(struct tm6000_core *dev, struct tm6000_reg_settings *set)
-{
-       int i, rc;
-
-       /* Load board's initialization table */
-       for (i = 0; set[i].req; i++) {
-               rc = tm6000_set_reg(dev, set[i].req, set[i].reg, set[i].value);
-               if (rc < 0) {
-                       printk(KERN_ERR "Error %i while setting "
-                              "req %d, reg %d to value %d\n",
-                              rc, set[i].req, set[i].reg, set[i].value);
-                       return rc;
-               }
-       }
-
-       return 0;
-}
-
-int tm6000_set_standard(struct tm6000_core *dev)
-{
-       struct tm6000_input *input;
-       int i, rc = 0;
-       u8 reg_07_fe = 0x8a;
-       u8 reg_08_f1 = 0xfc;
-       u8 reg_08_e2 = 0xf0;
-       u8 reg_08_e6 = 0x0f;
-
-       tm6000_get_std_res(dev);
-
-       if (!dev->radio)
-               input = &dev->vinput[dev->input];
-       else
-               input = &dev->rinput;
-
-       if (dev->dev_type == TM6010) {
-               switch (input->vmux) {
-               case TM6000_VMUX_VIDEO_A:
-                       tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4);
-                       tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1);
-                       tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0);
-                       tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
-                       tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8);
-                       reg_07_fe |= 0x01;
-                       break;
-               case TM6000_VMUX_VIDEO_B:
-                       tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8);
-                       tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1);
-                       tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0);
-                       tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
-                       tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8);
-                       reg_07_fe |= 0x01;
-                       break;
-               case TM6000_VMUX_VIDEO_AB:
-                       tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc);
-                       tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8);
-                       reg_08_e6 = 0x00;
-                       tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2);
-                       tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0);
-                       tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
-                       tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe0);
-                       break;
-               default:
-                       break;
-               }
-               switch (input->amux) {
-               case TM6000_AMUX_ADC1:
-                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
-                               0x00, 0x0f);
-                       break;
-               case TM6000_AMUX_ADC2:
-                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
-                               0x08, 0x0f);
-                       break;
-               case TM6000_AMUX_SIF1:
-                       reg_08_e2 |= 0x02;
-                       reg_08_e6 = 0x08;
-                       reg_07_fe |= 0x40;
-                       reg_08_f1 |= 0x02;
-                       tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3);
-                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
-                               0x02, 0x0f);
-                       break;
-               case TM6000_AMUX_SIF2:
-                       reg_08_e2 |= 0x02;
-                       reg_08_e6 = 0x08;
-                       reg_07_fe |= 0x40;
-                       reg_08_f1 |= 0x02;
-                       tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf7);
-                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
-                               0x02, 0x0f);
-                       break;
-               default:
-                       break;
-               }
-               tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, reg_08_e2);
-               tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, reg_08_e6);
-               tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, reg_08_f1);
-               tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, reg_07_fe);
-       } else {
-               switch (input->vmux) {
-               case TM6000_VMUX_VIDEO_A:
-                       tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10);
-                       tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00);
-                       tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f);
-                       tm6000_set_reg(dev,
-                           REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0);
-                       break;
-               case TM6000_VMUX_VIDEO_B:
-                       tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x00);
-                       tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00);
-                       tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f);
-                       tm6000_set_reg(dev,
-                           REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0);
-                       break;
-               case TM6000_VMUX_VIDEO_AB:
-                       tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10);
-                       tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x10);
-                       tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00);
-                       tm6000_set_reg(dev,
-                           REQ_03_SET_GET_MCU_PIN, input->v_gpio, 1);
-                       break;
-               default:
-                       break;
-               }
-               switch (input->amux) {
-               case TM6000_AMUX_ADC1:
-                       tm6000_set_reg_mask(dev,
-                               TM6000_REQ07_REB_VADC_AADC_MODE, 0x00, 0x0f);
-                       break;
-               case TM6000_AMUX_ADC2:
-                       tm6000_set_reg_mask(dev,
-                               TM6000_REQ07_REB_VADC_AADC_MODE, 0x04, 0x0f);
-                       break;
-               default:
-                       break;
-               }
-       }
-       if (input->type == TM6000_INPUT_SVIDEO) {
-               for (i = 0; i < ARRAY_SIZE(svideo_stds); i++) {
-                       if (dev->norm & svideo_stds[i].id) {
-                               rc = tm6000_load_std(dev, svideo_stds[i].common);
-                               goto ret;
-                       }
-               }
-               return -EINVAL;
-       } else {
-               for (i = 0; i < ARRAY_SIZE(composite_stds); i++) {
-                       if (dev->norm & composite_stds[i].id) {
-                               rc = tm6000_load_std(dev, composite_stds[i].common);
-                               goto ret;
-                       }
-               }
-               return -EINVAL;
-       }
-
-ret:
-       if (rc < 0)
-               return rc;
-
-       if ((dev->dev_type == TM6010) &&
-           ((input->amux == TM6000_AMUX_SIF1) ||
-           (input->amux == TM6000_AMUX_SIF2)))
-               tm6000_set_audio_std(dev);
-
-       msleep(40);
-
-       return 0;
-}
diff --git a/drivers/staging/tm6000/tm6000-usb-isoc.h b/drivers/staging/tm6000/tm6000-usb-isoc.h
deleted file mode 100644 (file)
index 99d15a5..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  tm6000-buf.c - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/videodev2.h>
-
-#define TM6000_URB_MSG_LEN 180
-
-struct usb_isoc_ctl {
-               /* max packet size of isoc transaction */
-       int                             max_pkt_size;
-
-               /* number of allocated urbs */
-       int                             num_bufs;
-
-               /* urb for isoc transfers */
-       struct urb                      **urb;
-
-               /* transfer buffers for isoc transfer */
-       char                            **transfer_buffer;
-
-               /* Last buffer command and region */
-       u8                              cmd;
-       int                             pos, size, pktsize;
-
-               /* Last field: ODD or EVEN? */
-       int                             vfield, field;
-
-               /* Stores incomplete commands */
-       u32                             tmp_buf;
-       int                             tmp_buf_len;
-
-               /* Stores already requested buffers */
-       struct tm6000_buffer            *buf;
-};
diff --git a/drivers/staging/tm6000/tm6000-video.c b/drivers/staging/tm6000/tm6000-video.c
deleted file mode 100644 (file)
index 1e5ace0..0000000
+++ /dev/null
@@ -1,1813 +0,0 @@
-/*
- *   tm6000-video.c - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
- *     - Fixed module load/unload
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/random.h>
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-ioctl.h>
-#include <media/tuner.h>
-#include <linux/interrupt.h>
-#include <linux/kthread.h>
-#include <linux/highmem.h>
-#include <linux/freezer.h>
-
-#include "tm6000-regs.h"
-#include "tm6000.h"
-
-#define BUFFER_TIMEOUT     msecs_to_jiffies(2000)  /* 2 seconds */
-
-/* Limits minimum and default number of buffers */
-#define TM6000_MIN_BUF 4
-#define TM6000_DEF_BUF 8
-
-#define TM6000_MAX_ISO_PACKETS 46      /* Max number of ISO packets */
-
-/* Declare static vars that will be used as parameters */
-static unsigned int vid_limit = 16;    /* Video memory limit, in Mb */
-static int video_nr = -1;              /* /dev/videoN, -1 for autodetect */
-static int radio_nr = -1;              /* /dev/radioN, -1 for autodetect */
-
-/* Debug level */
-int tm6000_debug;
-EXPORT_SYMBOL_GPL(tm6000_debug);
-
-static const struct v4l2_queryctrl no_ctrl = {
-       .name  = "42",
-       .flags = V4L2_CTRL_FLAG_DISABLED,
-};
-
-/* supported controls */
-static struct v4l2_queryctrl tm6000_qctrl[] = {
-       {
-               .id            = V4L2_CID_BRIGHTNESS,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Brightness",
-               .minimum       = 0,
-               .maximum       = 255,
-               .step          = 1,
-               .default_value = 54,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_CONTRAST,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Contrast",
-               .minimum       = 0,
-               .maximum       = 255,
-               .step          = 0x1,
-               .default_value = 119,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_SATURATION,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Saturation",
-               .minimum       = 0,
-               .maximum       = 255,
-               .step          = 0x1,
-               .default_value = 112,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_HUE,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Hue",
-               .minimum       = -128,
-               .maximum       = 127,
-               .step          = 0x1,
-               .default_value = 0,
-               .flags         = 0,
-       },
-               /* --- audio --- */
-       {
-               .id            = V4L2_CID_AUDIO_MUTE,
-               .name          = "Mute",
-               .minimum       = 0,
-               .maximum       = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       }, {
-               .id            = V4L2_CID_AUDIO_VOLUME,
-               .name          = "Volume",
-               .minimum       = -15,
-               .maximum       = 15,
-               .step          = 1,
-               .default_value = 0,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       }
-};
-
-static const unsigned int CTRLS = ARRAY_SIZE(tm6000_qctrl);
-static int qctl_regs[ARRAY_SIZE(tm6000_qctrl)];
-
-static struct tm6000_fmt format[] = {
-       {
-               .name     = "4:2:2, packed, YVY2",
-               .fourcc   = V4L2_PIX_FMT_YUYV,
-               .depth    = 16,
-       }, {
-               .name     = "4:2:2, packed, UYVY",
-               .fourcc   = V4L2_PIX_FMT_UYVY,
-               .depth    = 16,
-       }, {
-               .name     = "A/V + VBI mux packet",
-               .fourcc   = V4L2_PIX_FMT_TM6000,
-               .depth    = 16,
-       }
-};
-
-static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id)
-{
-       unsigned int i;
-
-       for (i = 0; i < CTRLS; i++)
-               if (tm6000_qctrl[i].id == id)
-                       return tm6000_qctrl+i;
-       return NULL;
-}
-
-/* ------------------------------------------------------------------
- *     DMA and thread functions
- * ------------------------------------------------------------------
- */
-
-#define norm_maxw(a) 720
-#define norm_maxh(a) 576
-
-#define norm_minw(a) norm_maxw(a)
-#define norm_minh(a) norm_maxh(a)
-
-/*
- * video-buf generic routine to get the next available buffer
- */
-static inline void get_next_buf(struct tm6000_dmaqueue *dma_q,
-                              struct tm6000_buffer   **buf)
-{
-       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
-       char *outp;
-
-       if (list_empty(&dma_q->active)) {
-               dprintk(dev, V4L2_DEBUG_QUEUE, "No active queue to serve\n");
-               *buf = NULL;
-               return;
-       }
-
-       *buf = list_entry(dma_q->active.next,
-                       struct tm6000_buffer, vb.queue);
-
-       /* Cleans up buffer - Useful for testing for frame/URB loss */
-       outp = videobuf_to_vmalloc(&(*buf)->vb);
-
-       return;
-}
-
-/*
- * Announces that a buffer were filled and request the next
- */
-static inline void buffer_filled(struct tm6000_core *dev,
-                                struct tm6000_dmaqueue *dma_q,
-                                struct tm6000_buffer *buf)
-{
-       /* Advice that buffer was filled */
-       dprintk(dev, V4L2_DEBUG_ISOC, "[%p/%d] wakeup\n", buf, buf->vb.i);
-       buf->vb.state = VIDEOBUF_DONE;
-       buf->vb.field_count++;
-       do_gettimeofday(&buf->vb.ts);
-
-       list_del(&buf->vb.queue);
-       wake_up(&buf->vb.done);
-}
-
-/*
- * Identify the tm5600/6000 buffer header type and properly handles
- */
-static int copy_streams(u8 *data, unsigned long len,
-                       struct urb *urb)
-{
-       struct tm6000_dmaqueue  *dma_q = urb->context;
-       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
-       u8 *ptr = data, *endp = data+len, c;
-       unsigned long header = 0;
-       int rc = 0;
-       unsigned int cmd, cpysize, pktsize, size, field, block, line, pos = 0;
-       struct tm6000_buffer *vbuf = NULL;
-       char *voutp = NULL;
-       unsigned int linewidth;
-
-       if (!dev->radio) {
-               /* get video buffer */
-               get_next_buf(dma_q, &vbuf);
-
-               if (!vbuf)
-                       return rc;
-               voutp = videobuf_to_vmalloc(&vbuf->vb);
-
-               if (!voutp)
-                       return 0;
-       }
-
-       for (ptr = data; ptr < endp;) {
-               if (!dev->isoc_ctl.cmd) {
-                       /* Header */
-                       if (dev->isoc_ctl.tmp_buf_len > 0) {
-                               /* from last urb or packet */
-                               header = dev->isoc_ctl.tmp_buf;
-                               if (4 - dev->isoc_ctl.tmp_buf_len > 0) {
-                                       memcpy((u8 *)&header +
-                                               dev->isoc_ctl.tmp_buf_len,
-                                               ptr,
-                                               4 - dev->isoc_ctl.tmp_buf_len);
-                                       ptr += 4 - dev->isoc_ctl.tmp_buf_len;
-                               }
-                               dev->isoc_ctl.tmp_buf_len = 0;
-                       } else {
-                               if (ptr + 3 >= endp) {
-                                       /* have incomplete header */
-                                       dev->isoc_ctl.tmp_buf_len = endp - ptr;
-                                       memcpy(&dev->isoc_ctl.tmp_buf, ptr,
-                                               dev->isoc_ctl.tmp_buf_len);
-                                       return rc;
-                               }
-                               /* Seek for sync */
-                               for (; ptr < endp - 3; ptr++) {
-                                       if (*(ptr + 3) == 0x47)
-                                               break;
-                               }
-                               /* Get message header */
-                               header = *(unsigned long *)ptr;
-                               ptr += 4;
-                       }
-
-                       /* split the header fields */
-                       c = (header >> 24) & 0xff;
-                       size = ((header & 0x7e) << 1);
-                       if (size > 0)
-                               size -= 4;
-                       block = (header >> 7) & 0xf;
-                       field = (header >> 11) & 0x1;
-                       line  = (header >> 12) & 0x1ff;
-                       cmd   = (header >> 21) & 0x7;
-                       /* Validates haeder fields */
-                       if (size > TM6000_URB_MSG_LEN)
-                               size = TM6000_URB_MSG_LEN;
-                       pktsize = TM6000_URB_MSG_LEN;
-                       /*
-                        * calculate position in buffer and change the buffer
-                        */
-                       switch (cmd) {
-                       case TM6000_URB_MSG_VIDEO:
-                               if (!dev->radio) {
-                                       if ((dev->isoc_ctl.vfield != field) &&
-                                               (field == 1)) {
-                                               /*
-                                                * Announces that a new buffer
-                                                * were filled
-                                                */
-                                               buffer_filled(dev, dma_q, vbuf);
-                                               dprintk(dev, V4L2_DEBUG_ISOC,
-                                                       "new buffer filled\n");
-                                               get_next_buf(dma_q, &vbuf);
-                                               if (!vbuf)
-                                                       return rc;
-                                               voutp = videobuf_to_vmalloc(&vbuf->vb);
-                                               if (!voutp)
-                                                       return rc;
-                                               memset(voutp, 0, vbuf->vb.size);
-                                       }
-                                       linewidth = vbuf->vb.width << 1;
-                                       pos = ((line << 1) - field - 1) *
-                                       linewidth + block * TM6000_URB_MSG_LEN;
-                                       /* Don't allow to write out of the buffer */
-                                       if (pos + size > vbuf->vb.size)
-                                               cmd = TM6000_URB_MSG_ERR;
-                                       dev->isoc_ctl.vfield = field;
-                               }
-                               break;
-                       case TM6000_URB_MSG_VBI:
-                               break;
-                       case TM6000_URB_MSG_AUDIO:
-                       case TM6000_URB_MSG_PTS:
-                               size = pktsize; /* Size is always 180 bytes */
-                               break;
-                       }
-               } else {
-                       /* Continue the last copy */
-                       cmd = dev->isoc_ctl.cmd;
-                       size = dev->isoc_ctl.size;
-                       pos = dev->isoc_ctl.pos;
-                       pktsize = dev->isoc_ctl.pktsize;
-                       field = dev->isoc_ctl.field;
-               }
-               cpysize = (endp - ptr > size) ? size : endp - ptr;
-               if (cpysize) {
-                       /* copy data in different buffers */
-                       switch (cmd) {
-                       case TM6000_URB_MSG_VIDEO:
-                               /* Fills video buffer */
-                               if (vbuf)
-                                       memcpy(&voutp[pos], ptr, cpysize);
-                               break;
-                       case TM6000_URB_MSG_AUDIO: {
-                               int i;
-                               for (i = 0; i < cpysize; i += 2)
-                                       swab16s((u16 *)(ptr + i));
-
-                               tm6000_call_fillbuf(dev, TM6000_AUDIO, ptr, cpysize);
-                               break;
-                       }
-                       case TM6000_URB_MSG_VBI:
-                               /* Need some code to copy vbi buffer */
-                               break;
-                       case TM6000_URB_MSG_PTS: {
-                               /* Need some code to copy pts */
-                               u32 pts;
-                               pts = *(u32 *)ptr;
-                               dprintk(dev, V4L2_DEBUG_ISOC, "field %d, PTS %x",
-                                       field, pts);
-                               break;
-                       }
-                       }
-               }
-               if (ptr + pktsize > endp) {
-                       /*
-                        * End of URB packet, but cmd processing is not
-                        * complete. Preserve the state for a next packet
-                        */
-                       dev->isoc_ctl.pos = pos + cpysize;
-                       dev->isoc_ctl.size = size - cpysize;
-                       dev->isoc_ctl.cmd = cmd;
-                       dev->isoc_ctl.field = field;
-                       dev->isoc_ctl.pktsize = pktsize - (endp - ptr);
-                       ptr += endp - ptr;
-               } else {
-                       dev->isoc_ctl.cmd = 0;
-                       ptr += pktsize;
-               }
-       }
-       return 0;
-}
-
-/*
- * Identify the tm5600/6000 buffer header type and properly handles
- */
-static int copy_multiplexed(u8 *ptr, unsigned long len,
-                       struct urb *urb)
-{
-       struct tm6000_dmaqueue  *dma_q = urb->context;
-       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
-       unsigned int pos = dev->isoc_ctl.pos, cpysize;
-       int rc = 1;
-       struct tm6000_buffer *buf;
-       char *outp = NULL;
-
-       get_next_buf(dma_q, &buf);
-       if (buf)
-               outp = videobuf_to_vmalloc(&buf->vb);
-
-       if (!outp)
-               return 0;
-
-       while (len > 0) {
-               cpysize = min(len, buf->vb.size-pos);
-               memcpy(&outp[pos], ptr, cpysize);
-               pos += cpysize;
-               ptr += cpysize;
-               len -= cpysize;
-               if (pos >= buf->vb.size) {
-                       pos = 0;
-                       /* Announces that a new buffer were filled */
-                       buffer_filled(dev, dma_q, buf);
-                       dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n");
-                       get_next_buf(dma_q, &buf);
-                       if (!buf)
-                               break;
-                       outp = videobuf_to_vmalloc(&(buf->vb));
-                       if (!outp)
-                               return rc;
-                       pos = 0;
-               }
-       }
-
-       dev->isoc_ctl.pos = pos;
-       return rc;
-}
-
-static inline void print_err_status(struct tm6000_core *dev,
-                                    int packet, int status)
-{
-       char *errmsg = "Unknown";
-
-       switch (status) {
-       case -ENOENT:
-               errmsg = "unlinked synchronuously";
-               break;
-       case -ECONNRESET:
-               errmsg = "unlinked asynchronuously";
-               break;
-       case -ENOSR:
-               errmsg = "Buffer error (overrun)";
-               break;
-       case -EPIPE:
-               errmsg = "Stalled (device not responding)";
-               break;
-       case -EOVERFLOW:
-               errmsg = "Babble (bad cable?)";
-               break;
-       case -EPROTO:
-               errmsg = "Bit-stuff error (bad cable?)";
-               break;
-       case -EILSEQ:
-               errmsg = "CRC/Timeout (could be anything)";
-               break;
-       case -ETIME:
-               errmsg = "Device does not respond";
-               break;
-       }
-       if (packet < 0) {
-               dprintk(dev, V4L2_DEBUG_QUEUE, "URB status %d [%s].\n",
-                       status, errmsg);
-       } else {
-               dprintk(dev, V4L2_DEBUG_QUEUE, "URB packet %d, status %d [%s].\n",
-                       packet, status, errmsg);
-       }
-}
-
-
-/*
- * Controls the isoc copy of each urb packet
- */
-static inline int tm6000_isoc_copy(struct urb *urb)
-{
-       struct tm6000_dmaqueue  *dma_q = urb->context;
-       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
-       int i, len = 0, rc = 1, status;
-       char *p;
-
-       if (urb->status < 0) {
-               print_err_status(dev, -1, urb->status);
-               return 0;
-       }
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               status = urb->iso_frame_desc[i].status;
-
-               if (status < 0) {
-                       print_err_status(dev, i, status);
-                       continue;
-               }
-
-               len = urb->iso_frame_desc[i].actual_length;
-
-               if (len > 0) {
-                       p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-                       if (!urb->iso_frame_desc[i].status) {
-                               if ((dev->fourcc) == V4L2_PIX_FMT_TM6000) {
-                                       rc = copy_multiplexed(p, len, urb);
-                                       if (rc <= 0)
-                                               return rc;
-                               } else {
-                                       copy_streams(p, len, urb);
-                               }
-                       }
-               }
-       }
-       return rc;
-}
-
-/* ------------------------------------------------------------------
- *     URB control
- * ------------------------------------------------------------------
- */
-
-/*
- * IRQ callback, called by URB callback
- */
-static void tm6000_irq_callback(struct urb *urb)
-{
-       struct tm6000_dmaqueue  *dma_q = urb->context;
-       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
-       int i;
-
-       switch (urb->status) {
-       case 0:
-       case -ETIMEDOUT:
-               break;
-
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               return;
-
-       default:
-               tm6000_err("urb completion error %d.\n", urb->status);
-               break;
-       }
-
-       spin_lock(&dev->slock);
-       tm6000_isoc_copy(urb);
-       spin_unlock(&dev->slock);
-
-       /* Reset urb buffers */
-       for (i = 0; i < urb->number_of_packets; i++) {
-               urb->iso_frame_desc[i].status = 0;
-               urb->iso_frame_desc[i].actual_length = 0;
-       }
-
-       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (urb->status)
-               tm6000_err("urb resubmit failed (error=%i)\n",
-                       urb->status);
-}
-
-/*
- * Stop and Deallocate URBs
- */
-static void tm6000_uninit_isoc(struct tm6000_core *dev)
-{
-       struct urb *urb;
-       int i;
-
-       dev->isoc_ctl.buf = NULL;
-       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
-               urb = dev->isoc_ctl.urb[i];
-               if (urb) {
-                       usb_kill_urb(urb);
-                       usb_unlink_urb(urb);
-                       if (dev->isoc_ctl.transfer_buffer[i]) {
-                               usb_free_coherent(dev->udev,
-                                               urb->transfer_buffer_length,
-                                               dev->isoc_ctl.transfer_buffer[i],
-                                               urb->transfer_dma);
-                       }
-                       usb_free_urb(urb);
-                       dev->isoc_ctl.urb[i] = NULL;
-               }
-               dev->isoc_ctl.transfer_buffer[i] = NULL;
-       }
-
-       kfree(dev->isoc_ctl.urb);
-       kfree(dev->isoc_ctl.transfer_buffer);
-
-       dev->isoc_ctl.urb = NULL;
-       dev->isoc_ctl.transfer_buffer = NULL;
-       dev->isoc_ctl.num_bufs = 0;
-}
-
-/*
- * Allocate URBs and start IRQ
- */
-static int tm6000_prepare_isoc(struct tm6000_core *dev)
-{
-       struct tm6000_dmaqueue *dma_q = &dev->vidq;
-       int i, j, sb_size, pipe, size, max_packets, num_bufs = 8;
-       struct urb *urb;
-
-       /* De-allocates all pending stuff */
-       tm6000_uninit_isoc(dev);
-       /* Stop interrupt USB pipe */
-       tm6000_ir_int_stop(dev);
-
-       usb_set_interface(dev->udev,
-                         dev->isoc_in.bInterfaceNumber,
-                         dev->isoc_in.bAlternateSetting);
-
-       /* Start interrupt USB pipe */
-       tm6000_ir_int_start(dev);
-
-       pipe = usb_rcvisocpipe(dev->udev,
-                              dev->isoc_in.endp->desc.bEndpointAddress &
-                              USB_ENDPOINT_NUMBER_MASK);
-
-       size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
-
-       if (size > dev->isoc_in.maxsize)
-               size = dev->isoc_in.maxsize;
-
-       dev->isoc_ctl.max_pkt_size = size;
-
-       max_packets = TM6000_MAX_ISO_PACKETS;
-       sb_size = max_packets * size;
-
-       dev->isoc_ctl.num_bufs = num_bufs;
-
-       dev->isoc_ctl.urb = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
-       if (!dev->isoc_ctl.urb) {
-               tm6000_err("cannot alloc memory for usb buffers\n");
-               return -ENOMEM;
-       }
-
-       dev->isoc_ctl.transfer_buffer = kmalloc(sizeof(void *)*num_bufs,
-                                  GFP_KERNEL);
-       if (!dev->isoc_ctl.transfer_buffer) {
-               tm6000_err("cannot allocate memory for usbtransfer\n");
-               kfree(dev->isoc_ctl.urb);
-               return -ENOMEM;
-       }
-
-       dprintk(dev, V4L2_DEBUG_QUEUE, "Allocating %d x %d packets"
-                   " (%d bytes) of %d bytes each to handle %u size\n",
-                   max_packets, num_bufs, sb_size,
-                   dev->isoc_in.maxsize, size);
-
-       /* allocate urbs and transfer buffers */
-       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
-               urb = usb_alloc_urb(max_packets, GFP_KERNEL);
-               if (!urb) {
-                       tm6000_err("cannot alloc isoc_ctl.urb %i\n", i);
-                       tm6000_uninit_isoc(dev);
-                       usb_free_urb(urb);
-                       return -ENOMEM;
-               }
-               dev->isoc_ctl.urb[i] = urb;
-
-               dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev,
-                       sb_size, GFP_KERNEL, &urb->transfer_dma);
-               if (!dev->isoc_ctl.transfer_buffer[i]) {
-                       tm6000_err("unable to allocate %i bytes for transfer"
-                                       " buffer %i%s\n",
-                                       sb_size, i,
-                                       in_interrupt() ? " while in int" : "");
-                       tm6000_uninit_isoc(dev);
-                       return -ENOMEM;
-               }
-               memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
-
-               usb_fill_bulk_urb(urb, dev->udev, pipe,
-                                 dev->isoc_ctl.transfer_buffer[i], sb_size,
-                                 tm6000_irq_callback, dma_q);
-               urb->interval = dev->isoc_in.endp->desc.bInterval;
-               urb->number_of_packets = max_packets;
-               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-
-               for (j = 0; j < max_packets; j++) {
-                       urb->iso_frame_desc[j].offset = size * j;
-                       urb->iso_frame_desc[j].length = size;
-               }
-       }
-
-       return 0;
-}
-
-static int tm6000_start_thread(struct tm6000_core *dev)
-{
-       struct tm6000_dmaqueue *dma_q = &dev->vidq;
-       int i;
-
-       dma_q->frame = 0;
-       dma_q->ini_jiffies = jiffies;
-
-       init_waitqueue_head(&dma_q->wq);
-
-       /* submit urbs and enables IRQ */
-       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
-               int rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
-               if (rc) {
-                       tm6000_err("submit of urb %i failed (error=%i)\n", i,
-                                  rc);
-                       tm6000_uninit_isoc(dev);
-                       return rc;
-               }
-       }
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------
- *     Videobuf operations
- * ------------------------------------------------------------------
- */
-
-static int
-buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
-{
-       struct tm6000_fh *fh = vq->priv_data;
-
-       *size = fh->fmt->depth * fh->width * fh->height >> 3;
-       if (0 == *count)
-               *count = TM6000_DEF_BUF;
-
-       if (*count < TM6000_MIN_BUF)
-               *count = TM6000_MIN_BUF;
-
-       while (*size * *count > vid_limit * 1024 * 1024)
-               (*count)--;
-
-       return 0;
-}
-
-static void free_buffer(struct videobuf_queue *vq, struct tm6000_buffer *buf)
-{
-       struct tm6000_fh *fh = vq->priv_data;
-       struct tm6000_core   *dev = fh->dev;
-       unsigned long flags;
-
-       if (in_interrupt())
-               BUG();
-
-       /* We used to wait for the buffer to finish here, but this didn't work
-          because, as we were keeping the state as VIDEOBUF_QUEUED,
-          videobuf_queue_cancel marked it as finished for us.
-          (Also, it could wedge forever if the hardware was misconfigured.)
-
-          This should be safe; by the time we get here, the buffer isn't
-          queued anymore. If we ever start marking the buffers as
-          VIDEOBUF_ACTIVE, it won't be, though.
-       */
-       spin_lock_irqsave(&dev->slock, flags);
-       if (dev->isoc_ctl.buf == buf)
-               dev->isoc_ctl.buf = NULL;
-       spin_unlock_irqrestore(&dev->slock, flags);
-
-       videobuf_vmalloc_free(&buf->vb);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-static int
-buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
-                                               enum v4l2_field field)
-{
-       struct tm6000_fh     *fh  = vq->priv_data;
-       struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb);
-       struct tm6000_core   *dev = fh->dev;
-       int rc = 0;
-
-       BUG_ON(NULL == fh->fmt);
-
-
-       /* FIXME: It assumes depth=2 */
-       /* The only currently supported format is 16 bits/pixel */
-       buf->vb.size = fh->fmt->depth*fh->width*fh->height >> 3;
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
-               return -EINVAL;
-
-       if (buf->fmt       != fh->fmt    ||
-           buf->vb.width  != fh->width  ||
-           buf->vb.height != fh->height ||
-           buf->vb.field  != field) {
-               buf->fmt       = fh->fmt;
-               buf->vb.width  = fh->width;
-               buf->vb.height = fh->height;
-               buf->vb.field  = field;
-               buf->vb.state = VIDEOBUF_NEEDS_INIT;
-       }
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               rc = videobuf_iolock(vq, &buf->vb, NULL);
-               if (rc != 0)
-                       goto fail;
-       }
-
-       if (!dev->isoc_ctl.num_bufs) {
-               rc = tm6000_prepare_isoc(dev);
-               if (rc < 0)
-                       goto fail;
-
-               rc = tm6000_start_thread(dev);
-               if (rc < 0)
-                       goto fail;
-
-       }
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
-fail:
-       free_buffer(vq, buf);
-       return rc;
-}
-
-static void
-buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
-       struct tm6000_buffer    *buf     = container_of(vb, struct tm6000_buffer, vb);
-       struct tm6000_fh        *fh      = vq->priv_data;
-       struct tm6000_core      *dev     = fh->dev;
-       struct tm6000_dmaqueue  *vidq    = &dev->vidq;
-
-       buf->vb.state = VIDEOBUF_QUEUED;
-       list_add_tail(&buf->vb.queue, &vidq->active);
-}
-
-static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
-       struct tm6000_buffer   *buf  = container_of(vb, struct tm6000_buffer, vb);
-
-       free_buffer(vq, buf);
-}
-
-static struct videobuf_queue_ops tm6000_video_qops = {
-       .buf_setup      = buffer_setup,
-       .buf_prepare    = buffer_prepare,
-       .buf_queue      = buffer_queue,
-       .buf_release    = buffer_release,
-};
-
-/* ------------------------------------------------------------------
- *     IOCTL handling
- * ------------------------------------------------------------------
- */
-
-static bool is_res_read(struct tm6000_core *dev, struct tm6000_fh *fh)
-{
-       /* Is the current fh handling it? if so, that's OK */
-       if (dev->resources == fh && dev->is_res_read)
-               return true;
-
-       return false;
-}
-
-static bool is_res_streaming(struct tm6000_core *dev, struct tm6000_fh *fh)
-{
-       /* Is the current fh handling it? if so, that's OK */
-       if (dev->resources == fh)
-               return true;
-
-       return false;
-}
-
-static bool res_get(struct tm6000_core *dev, struct tm6000_fh *fh,
-                  bool is_res_read)
-{
-       /* Is the current fh handling it? if so, that's OK */
-       if (dev->resources == fh && dev->is_res_read == is_res_read)
-               return true;
-
-       /* is it free? */
-       if (dev->resources)
-               return false;
-
-       /* grab it */
-       dev->resources = fh;
-       dev->is_res_read = is_res_read;
-       dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: get\n");
-       return true;
-}
-
-static void res_free(struct tm6000_core *dev, struct tm6000_fh *fh)
-{
-       /* Is the current fh handling it? if so, that's OK */
-       if (dev->resources != fh)
-               return;
-
-       dev->resources = NULL;
-       dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: put\n");
-}
-
-/* ------------------------------------------------------------------
- *     IOCTL vidioc handling
- * ------------------------------------------------------------------
- */
-static int vidioc_querycap(struct file *file, void  *priv,
-                                       struct v4l2_capability *cap)
-{
-       struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
-
-       strlcpy(cap->driver, "tm6000", sizeof(cap->driver));
-       strlcpy(cap->card, "Trident TVMaster TM5600/6000/6010", sizeof(cap->card));
-       cap->version = TM6000_VERSION;
-       cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
-                               V4L2_CAP_STREAMING     |
-                               V4L2_CAP_AUDIO         |
-                               V4L2_CAP_READWRITE;
-
-       if (dev->tuner_type != TUNER_ABSENT)
-               cap->capabilities |= V4L2_CAP_TUNER;
-
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       if (unlikely(f->index >= ARRAY_SIZE(format)))
-               return -EINVAL;
-
-       strlcpy(f->description, format[f->index].name, sizeof(f->description));
-       f->pixelformat = format[f->index].fourcc;
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct tm6000_fh  *fh = priv;
-
-       f->fmt.pix.width        = fh->width;
-       f->fmt.pix.height       = fh->height;
-       f->fmt.pix.field        = fh->vb_vidq.field;
-       f->fmt.pix.pixelformat  = fh->fmt->fourcc;
-       f->fmt.pix.bytesperline =
-               (f->fmt.pix.width * fh->fmt->depth) >> 3;
-       f->fmt.pix.sizeimage =
-               f->fmt.pix.height * f->fmt.pix.bytesperline;
-
-       return 0;
-}
-
-static struct tm6000_fmt *format_by_fourcc(unsigned int fourcc)
-{
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(format); i++)
-               if (format[i].fourcc == fourcc)
-                       return format+i;
-       return NULL;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                       struct v4l2_format *f)
-{
-       struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
-       struct tm6000_fmt *fmt;
-       enum v4l2_field field;
-
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-       if (NULL == fmt) {
-               dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Fourcc format (0x%08x)"
-                               " invalid.\n", f->fmt.pix.pixelformat);
-               return -EINVAL;
-       }
-
-       field = f->fmt.pix.field;
-
-       if (field == V4L2_FIELD_ANY)
-               field = V4L2_FIELD_SEQ_TB;
-       else if (V4L2_FIELD_INTERLACED != field) {
-               dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Field type invalid.\n");
-               return -EINVAL;
-       }
-
-       tm6000_get_std_res(dev);
-
-       f->fmt.pix.width  = dev->width;
-       f->fmt.pix.height = dev->height;
-
-       f->fmt.pix.width &= ~0x01;
-
-       f->fmt.pix.field = field;
-
-       f->fmt.pix.bytesperline =
-               (f->fmt.pix.width * fmt->depth) >> 3;
-       f->fmt.pix.sizeimage =
-               f->fmt.pix.height * f->fmt.pix.bytesperline;
-
-       return 0;
-}
-
-/*FIXME: This seems to be generic enough to be at videodev2 */
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct tm6000_fh  *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-       int ret = vidioc_try_fmt_vid_cap(file, fh, f);
-       if (ret < 0)
-               return ret;
-
-       fh->fmt           = format_by_fourcc(f->fmt.pix.pixelformat);
-       fh->width         = f->fmt.pix.width;
-       fh->height        = f->fmt.pix.height;
-       fh->vb_vidq.field = f->fmt.pix.field;
-       fh->type          = f->type;
-
-       dev->fourcc       = f->fmt.pix.pixelformat;
-
-       tm6000_set_fourcc_format(dev);
-
-       return 0;
-}
-
-static int vidioc_reqbufs(struct file *file, void *priv,
-                          struct v4l2_requestbuffers *p)
-{
-       struct tm6000_fh  *fh = priv;
-
-       return videobuf_reqbufs(&fh->vb_vidq, p);
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
-                           struct v4l2_buffer *p)
-{
-       struct tm6000_fh  *fh = priv;
-
-       return videobuf_querybuf(&fh->vb_vidq, p);
-}
-
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       struct tm6000_fh  *fh = priv;
-
-       return videobuf_qbuf(&fh->vb_vidq, p);
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       struct tm6000_fh  *fh = priv;
-
-       return videobuf_dqbuf(&fh->vb_vidq, p,
-                               file->f_flags & O_NONBLOCK);
-}
-
-static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct tm6000_fh *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       if (i != fh->type)
-               return -EINVAL;
-
-       if (!res_get(dev, fh, false))
-               return -EBUSY;
-       return videobuf_streamon(&fh->vb_vidq);
-}
-
-static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct tm6000_fh *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       if (i != fh->type)
-               return -EINVAL;
-
-       videobuf_streamoff(&fh->vb_vidq);
-       res_free(dev, fh);
-
-       return 0;
-}
-
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
-{
-       int rc = 0;
-       struct tm6000_fh *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       dev->norm = *norm;
-       rc = tm6000_init_analog_mode(dev);
-
-       fh->width  = dev->width;
-       fh->height = dev->height;
-
-       if (rc < 0)
-               return rc;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
-
-       return 0;
-}
-
-static const char *iname[] = {
-       [TM6000_INPUT_TV] = "Television",
-       [TM6000_INPUT_COMPOSITE1] = "Composite 1",
-       [TM6000_INPUT_COMPOSITE2] = "Composite 2",
-       [TM6000_INPUT_SVIDEO] = "S-Video",
-};
-
-static int vidioc_enum_input(struct file *file, void *priv,
-                               struct v4l2_input *i)
-{
-       struct tm6000_fh   *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-       unsigned int n;
-
-       n = i->index;
-       if (n >= 3)
-               return -EINVAL;
-
-       if (!dev->vinput[n].type)
-               return -EINVAL;
-
-       i->index = n;
-
-       if (dev->vinput[n].type == TM6000_INPUT_TV)
-               i->type = V4L2_INPUT_TYPE_TUNER;
-       else
-               i->type = V4L2_INPUT_TYPE_CAMERA;
-
-       strcpy(i->name, iname[dev->vinput[n].type]);
-
-       i->std = TM6000_STD;
-
-       return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       struct tm6000_fh   *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       *i = dev->input;
-
-       return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-       struct tm6000_fh   *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-       int rc = 0;
-
-       if (i >= 3)
-               return -EINVAL;
-       if (!dev->vinput[i].type)
-               return -EINVAL;
-
-       dev->input = i;
-
-       rc = vidioc_s_std(file, priv, &dev->vfd->current_norm);
-
-       return rc;
-}
-
-/* --- controls ---------------------------------------------- */
-static int vidioc_queryctrl(struct file *file, void *priv,
-                               struct v4l2_queryctrl *qc)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)
-               if (qc->id && qc->id == tm6000_qctrl[i].id) {
-                       memcpy(qc, &(tm6000_qctrl[i]),
-                               sizeof(*qc));
-                       return 0;
-               }
-
-       return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctrl)
-{
-       struct tm6000_fh  *fh = priv;
-       struct tm6000_core *dev    = fh->dev;
-       int  val;
-
-       /* FIXME: Probably, those won't work! Maybe we need shadow regs */
-       switch (ctrl->id) {
-       case V4L2_CID_CONTRAST:
-               val = tm6000_get_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0);
-               break;
-       case V4L2_CID_BRIGHTNESS:
-               val = tm6000_get_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0);
-               return 0;
-       case V4L2_CID_SATURATION:
-               val = tm6000_get_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0);
-               return 0;
-       case V4L2_CID_HUE:
-               val = tm6000_get_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, 0);
-               return 0;
-       case V4L2_CID_AUDIO_MUTE:
-               val = dev->ctl_mute;
-               return 0;
-       case V4L2_CID_AUDIO_VOLUME:
-               val = dev->ctl_volume;
-               return 0;
-       default:
-               return -EINVAL;
-       }
-
-       if (val < 0)
-               return val;
-
-       ctrl->value = val;
-
-       return 0;
-}
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctrl)
-{
-       struct tm6000_fh   *fh  = priv;
-       struct tm6000_core *dev = fh->dev;
-       u8  val = ctrl->value;
-
-       switch (ctrl->id) {
-       case V4L2_CID_CONTRAST:
-               tm6000_set_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, val);
-               return 0;
-       case V4L2_CID_BRIGHTNESS:
-               tm6000_set_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, val);
-               return 0;
-       case V4L2_CID_SATURATION:
-               tm6000_set_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, val);
-               return 0;
-       case V4L2_CID_HUE:
-               tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val);
-               return 0;
-       case V4L2_CID_AUDIO_MUTE:
-               dev->ctl_mute = val;
-               tm6000_tvaudio_set_mute(dev, val);
-               return 0;
-       case V4L2_CID_AUDIO_VOLUME:
-               dev->ctl_volume = val;
-               tm6000_set_volume(dev, val);
-               return 0;
-       }
-       return -EINVAL;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct tm6000_fh   *fh  = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (unlikely(UNSET == dev->tuner_type))
-               return -EINVAL;
-       if (0 != t->index)
-               return -EINVAL;
-
-       strcpy(t->name, "Television");
-       t->type       = V4L2_TUNER_ANALOG_TV;
-       t->capability = V4L2_TUNER_CAP_NORM;
-       t->rangehigh  = 0xffffffffUL;
-       t->rxsubchans = V4L2_TUNER_SUB_STEREO;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
-
-       t->audmode = dev->amode;
-
-       return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct tm6000_fh   *fh  = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (UNSET == dev->tuner_type)
-               return -EINVAL;
-       if (0 != t->index)
-               return -EINVAL;
-
-       dev->amode = t->audmode;
-       dprintk(dev, 3, "audio mode: %x\n", t->audmode);
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
-
-       return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-                               struct v4l2_frequency *f)
-{
-       struct tm6000_fh   *fh  = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (unlikely(UNSET == dev->tuner_type))
-               return -EINVAL;
-
-       f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-       f->frequency = dev->freq;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, f);
-
-       return 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
-                               struct v4l2_frequency *f)
-{
-       struct tm6000_fh   *fh  = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (unlikely(UNSET == dev->tuner_type))
-               return -EINVAL;
-       if (unlikely(f->tuner != 0))
-               return -EINVAL;
-       if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type)
-               return -EINVAL;
-       if (1 == fh->radio && V4L2_TUNER_RADIO != f->type)
-               return -EINVAL;
-
-       dev->freq = f->frequency;
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f);
-
-       return 0;
-}
-
-static int radio_querycap(struct file *file, void *priv,
-                                       struct v4l2_capability *cap)
-{
-       struct tm6000_fh *fh = file->private_data;
-       struct tm6000_core *dev = fh->dev;
-
-       strcpy(cap->driver, "tm6000");
-       strlcpy(cap->card, dev->name, sizeof(dev->name));
-       sprintf(cap->bus_info, "USB%04x:%04x",
-               le16_to_cpu(dev->udev->descriptor.idVendor),
-               le16_to_cpu(dev->udev->descriptor.idProduct));
-       cap->version = dev->dev_type;
-       cap->capabilities = V4L2_CAP_TUNER |
-                       V4L2_CAP_AUDIO     |
-                       V4L2_CAP_RADIO     |
-                       V4L2_CAP_READWRITE |
-                       V4L2_CAP_STREAMING;
-
-       return 0;
-}
-
-static int radio_g_tuner(struct file *file, void *priv,
-                                       struct v4l2_tuner *t)
-{
-       struct tm6000_fh *fh = file->private_data;
-       struct tm6000_core *dev = fh->dev;
-
-       if (0 != t->index)
-               return -EINVAL;
-
-       memset(t, 0, sizeof(*t));
-       strcpy(t->name, "Radio");
-       t->type = V4L2_TUNER_RADIO;
-       t->rxsubchans = V4L2_TUNER_SUB_STEREO;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
-
-       return 0;
-}
-
-static int radio_s_tuner(struct file *file, void *priv,
-                                       struct v4l2_tuner *t)
-{
-       struct tm6000_fh *fh = file->private_data;
-       struct tm6000_core *dev = fh->dev;
-
-       if (0 != t->index)
-               return -EINVAL;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
-
-       return 0;
-}
-
-static int radio_enum_input(struct file *file, void *priv,
-                                       struct v4l2_input *i)
-{
-       struct tm6000_fh *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (i->index != 0)
-               return -EINVAL;
-
-       if (!dev->rinput.type)
-               return -EINVAL;
-
-       strcpy(i->name, "Radio");
-       i->type = V4L2_INPUT_TYPE_TUNER;
-
-       return 0;
-}
-
-static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
-{
-       struct tm6000_fh *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (dev->input != 5)
-               return -EINVAL;
-
-       *i = dev->input - 5;
-
-       return 0;
-}
-
-static int radio_g_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *a)
-{
-       memset(a, 0, sizeof(*a));
-       strcpy(a->name, "Radio");
-       return 0;
-}
-
-static int radio_s_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *a)
-{
-       return 0;
-}
-
-static int radio_s_input(struct file *filp, void *priv, unsigned int i)
-{
-       struct tm6000_fh *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (i)
-               return -EINVAL;
-
-       if (!dev->rinput.type)
-               return -EINVAL;
-
-       dev->input = i + 5;
-
-       return 0;
-}
-
-static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
-{
-       return 0;
-}
-
-static int radio_queryctrl(struct file *file, void *priv,
-                                       struct v4l2_queryctrl *c)
-{
-       const struct v4l2_queryctrl *ctrl;
-
-       if (c->id <  V4L2_CID_BASE ||
-           c->id >= V4L2_CID_LASTP1)
-               return -EINVAL;
-       if (c->id == V4L2_CID_AUDIO_MUTE) {
-               ctrl = ctrl_by_id(c->id);
-               *c = *ctrl;
-       } else
-               *c = no_ctrl;
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------
-       File operations for the device
-   ------------------------------------------------------------------*/
-
-static int tm6000_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct tm6000_core *dev = video_drvdata(file);
-       struct tm6000_fh *fh;
-       enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       int i, rc;
-       int radio = 0;
-
-       dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called (dev=%s)\n",
-               video_device_node_name(vdev));
-
-       switch (vdev->vfl_type) {
-       case VFL_TYPE_GRABBER:
-               type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               break;
-       case VFL_TYPE_VBI:
-               type = V4L2_BUF_TYPE_VBI_CAPTURE;
-               break;
-       case VFL_TYPE_RADIO:
-               radio = 1;
-               break;
-       }
-
-       /* If more than one user, mutex should be added */
-       dev->users++;
-
-       dprintk(dev, V4L2_DEBUG_OPEN, "open dev=%s type=%s users=%d\n",
-               video_device_node_name(vdev), v4l2_type_names[type],
-               dev->users);
-
-       /* allocate + initialize per filehandle data */
-       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-       if (NULL == fh) {
-               dev->users--;
-               return -ENOMEM;
-       }
-
-       file->private_data = fh;
-       fh->dev      = dev;
-       fh->radio    = radio;
-       dev->radio   = radio;
-       fh->type     = type;
-       dev->fourcc  = format[0].fourcc;
-
-       fh->fmt      = format_by_fourcc(dev->fourcc);
-
-       tm6000_get_std_res(dev);
-
-       fh->width = dev->width;
-       fh->height = dev->height;
-
-       dprintk(dev, V4L2_DEBUG_OPEN, "Open: fh=0x%08lx, dev=0x%08lx, "
-                                               "dev->vidq=0x%08lx\n",
-                       (unsigned long)fh, (unsigned long)dev,
-                       (unsigned long)&dev->vidq);
-       dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "
-                               "queued=%d\n", list_empty(&dev->vidq.queued));
-       dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "
-                               "active=%d\n", list_empty(&dev->vidq.active));
-
-       /* initialize hardware on analog mode */
-       rc = tm6000_init_analog_mode(dev);
-       if (rc < 0)
-               return rc;
-
-       if (dev->mode != TM6000_MODE_ANALOG) {
-               /* Put all controls at a sane state */
-               for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)
-                       qctl_regs[i] = tm6000_qctrl[i].default_value;
-
-               dev->mode = TM6000_MODE_ANALOG;
-       }
-
-       if (!fh->radio) {
-               videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops,
-                               NULL, &dev->slock,
-                               fh->type,
-                               V4L2_FIELD_INTERLACED,
-                               sizeof(struct tm6000_buffer), fh, &dev->lock);
-       } else {
-               dprintk(dev, V4L2_DEBUG_OPEN, "video_open: setting radio device\n");
-               dev->input = 5;
-               tm6000_set_audio_rinput(dev);
-               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio);
-               tm6000_prepare_isoc(dev);
-               tm6000_start_thread(dev);
-       }
-
-       return 0;
-}
-
-static ssize_t
-tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos)
-{
-       struct tm6000_fh        *fh = file->private_data;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               if (!res_get(fh->dev, fh, true))
-                       return -EBUSY;
-
-               return videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0,
-                                       file->f_flags & O_NONBLOCK);
-       }
-       return 0;
-}
-
-static unsigned int
-tm6000_poll(struct file *file, struct poll_table_struct *wait)
-{
-       struct tm6000_fh        *fh = file->private_data;
-       struct tm6000_buffer    *buf;
-
-       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
-               return POLLERR;
-
-       if (!!is_res_streaming(fh->dev, fh))
-               return POLLERR;
-
-       if (!is_res_read(fh->dev, fh)) {
-               /* streaming capture */
-               if (list_empty(&fh->vb_vidq.stream))
-                       return POLLERR;
-               buf = list_entry(fh->vb_vidq.stream.next, struct tm6000_buffer, vb.stream);
-       } else {
-               /* read() capture */
-               return videobuf_poll_stream(file, &fh->vb_vidq, wait);
-       }
-       poll_wait(file, &buf->vb.done, wait);
-       if (buf->vb.state == VIDEOBUF_DONE ||
-           buf->vb.state == VIDEOBUF_ERROR)
-               return POLLIN | POLLRDNORM;
-       return 0;
-}
-
-static int tm6000_release(struct file *file)
-{
-       struct tm6000_fh         *fh = file->private_data;
-       struct tm6000_core      *dev = fh->dev;
-       struct video_device    *vdev = video_devdata(file);
-
-       dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: close called (dev=%s, users=%d)\n",
-               video_device_node_name(vdev), dev->users);
-
-       dev->users--;
-
-       res_free(dev, fh);
-
-       if (!dev->users) {
-               int err;
-
-               tm6000_uninit_isoc(dev);
-
-               if (!fh->radio)
-                       videobuf_mmap_free(&fh->vb_vidq);
-
-               err = tm6000_reset(dev);
-               if (err < 0)
-                       dev_err(&vdev->dev, "reset failed: %d\n", err);
-       }
-
-       kfree(fh);
-
-       return 0;
-}
-
-static int tm6000_mmap(struct file *file, struct vm_area_struct * vma)
-{
-       struct tm6000_fh *fh = file->private_data;
-
-       return videobuf_mmap_mapper(&fh->vb_vidq, vma);
-}
-
-static struct v4l2_file_operations tm6000_fops = {
-       .owner = THIS_MODULE,
-       .open = tm6000_open,
-       .release = tm6000_release,
-       .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
-       .read = tm6000_read,
-       .poll = tm6000_poll,
-       .mmap = tm6000_mmap,
-};
-
-static const struct v4l2_ioctl_ops video_ioctl_ops = {
-       .vidioc_querycap          = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
-       .vidioc_s_std             = vidioc_s_std,
-       .vidioc_enum_input        = vidioc_enum_input,
-       .vidioc_g_input           = vidioc_g_input,
-       .vidioc_s_input           = vidioc_s_input,
-       .vidioc_queryctrl         = vidioc_queryctrl,
-       .vidioc_g_ctrl            = vidioc_g_ctrl,
-       .vidioc_s_ctrl            = vidioc_s_ctrl,
-       .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_streamon          = vidioc_streamon,
-       .vidioc_streamoff         = vidioc_streamoff,
-       .vidioc_reqbufs           = vidioc_reqbufs,
-       .vidioc_querybuf          = vidioc_querybuf,
-       .vidioc_qbuf              = vidioc_qbuf,
-       .vidioc_dqbuf             = vidioc_dqbuf,
-};
-
-static struct video_device tm6000_template = {
-       .name           = "tm6000",
-       .fops           = &tm6000_fops,
-       .ioctl_ops      = &video_ioctl_ops,
-       .release        = video_device_release,
-       .tvnorms        = TM6000_STD,
-       .current_norm   = V4L2_STD_NTSC_M,
-};
-
-static const struct v4l2_file_operations radio_fops = {
-       .owner          = THIS_MODULE,
-       .open           = tm6000_open,
-       .release        = tm6000_release,
-       .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops radio_ioctl_ops = {
-       .vidioc_querycap        = radio_querycap,
-       .vidioc_g_tuner         = radio_g_tuner,
-       .vidioc_enum_input      = radio_enum_input,
-       .vidioc_g_audio         = radio_g_audio,
-       .vidioc_s_tuner         = radio_s_tuner,
-       .vidioc_s_audio         = radio_s_audio,
-       .vidioc_s_input         = radio_s_input,
-       .vidioc_s_std           = radio_s_std,
-       .vidioc_queryctrl       = radio_queryctrl,
-       .vidioc_g_input         = radio_g_input,
-       .vidioc_g_ctrl          = vidioc_g_ctrl,
-       .vidioc_s_ctrl          = vidioc_s_ctrl,
-       .vidioc_g_frequency     = vidioc_g_frequency,
-       .vidioc_s_frequency     = vidioc_s_frequency,
-};
-
-static struct video_device tm6000_radio_template = {
-       .name                   = "tm6000",
-       .fops                   = &radio_fops,
-       .ioctl_ops              = &radio_ioctl_ops,
-};
-
-/* -----------------------------------------------------------------
- *     Initialization and module stuff
- * ------------------------------------------------------------------
- */
-
-static struct video_device *vdev_init(struct tm6000_core *dev,
-               const struct video_device
-               *template, const char *type_name)
-{
-       struct video_device *vfd;
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
-
-       *vfd = *template;
-       vfd->v4l2_dev = &dev->v4l2_dev;
-       vfd->release = video_device_release;
-       vfd->debug = tm6000_debug;
-       vfd->lock = &dev->lock;
-
-       snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
-
-       video_set_drvdata(vfd, dev);
-       return vfd;
-}
-
-int tm6000_v4l2_register(struct tm6000_core *dev)
-{
-       int ret = -1;
-
-       dev->vfd = vdev_init(dev, &tm6000_template, "video");
-
-       if (!dev->vfd) {
-               printk(KERN_INFO "%s: can't register video device\n",
-                      dev->name);
-               return -ENOMEM;
-       }
-
-       /* init video dma queues */
-       INIT_LIST_HEAD(&dev->vidq.active);
-       INIT_LIST_HEAD(&dev->vidq.queued);
-
-       ret = video_register_device(dev->vfd, VFL_TYPE_GRABBER, video_nr);
-
-       if (ret < 0) {
-               printk(KERN_INFO "%s: can't register video device\n",
-                      dev->name);
-               return ret;
-       }
-
-       printk(KERN_INFO "%s: registered device %s\n",
-              dev->name, video_device_node_name(dev->vfd));
-
-       if (dev->caps.has_radio) {
-               dev->radio_dev = vdev_init(dev, &tm6000_radio_template,
-                                                          "radio");
-               if (!dev->radio_dev) {
-                       printk(KERN_INFO "%s: can't register radio device\n",
-                              dev->name);
-                       return ret; /* FIXME release resource */
-               }
-
-               ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
-                                           radio_nr);
-               if (ret < 0) {
-                       printk(KERN_INFO "%s: can't register radio device\n",
-                              dev->name);
-                       return ret; /* FIXME release resource */
-               }
-
-               printk(KERN_INFO "%s: registered device %s\n",
-                      dev->name, video_device_node_name(dev->radio_dev));
-       }
-
-       printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret);
-       return ret;
-}
-
-int tm6000_v4l2_unregister(struct tm6000_core *dev)
-{
-       video_unregister_device(dev->vfd);
-
-       if (dev->radio_dev) {
-               if (video_is_registered(dev->radio_dev))
-                       video_unregister_device(dev->radio_dev);
-               else
-                       video_device_release(dev->radio_dev);
-               dev->radio_dev = NULL;
-       }
-
-       return 0;
-}
-
-int tm6000_v4l2_exit(void)
-{
-       return 0;
-}
-
-module_param(video_nr, int, 0);
-MODULE_PARM_DESC(video_nr, "Allow changing video device number");
-
-module_param_named(debug, tm6000_debug, int, 0444);
-MODULE_PARM_DESC(debug, "activates debug info");
-
-module_param(vid_limit, int, 0644);
-MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
-
diff --git a/drivers/staging/tm6000/tm6000.h b/drivers/staging/tm6000/tm6000.h
deleted file mode 100644 (file)
index 2777e51..0000000
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- *  tm6000.h - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
- *     - DVB-T support
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/videobuf-vmalloc.h>
-#include "tm6000-usb-isoc.h"
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <media/v4l2-device.h>
-
-#include <linux/dvb/frontend.h>
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dmxdev.h"
-
-#define TM6000_VERSION KERNEL_VERSION(0, 0, 2)
-
-/* Inputs */
-enum tm6000_itype {
-       TM6000_INPUT_TV = 1,
-       TM6000_INPUT_COMPOSITE1,
-       TM6000_INPUT_COMPOSITE2,
-       TM6000_INPUT_SVIDEO,
-       TM6000_INPUT_DVB,
-       TM6000_INPUT_RADIO,
-};
-
-enum tm6000_mux {
-       TM6000_VMUX_VIDEO_A = 1,
-       TM6000_VMUX_VIDEO_B,
-       TM6000_VMUX_VIDEO_AB,
-       TM6000_AMUX_ADC1,
-       TM6000_AMUX_ADC2,
-       TM6000_AMUX_SIF1,
-       TM6000_AMUX_SIF2,
-       TM6000_AMUX_I2S,
-};
-
-enum tm6000_devtype {
-       TM6000 = 0,
-       TM5600,
-       TM6010,
-};
-
-struct tm6000_input {
-       enum tm6000_itype       type;
-       enum tm6000_mux         vmux;
-       enum tm6000_mux         amux;
-       unsigned int            v_gpio;
-       unsigned int            a_gpio;
-};
-
-/* ------------------------------------------------------------------
- *     Basic structures
- * ------------------------------------------------------------------
- */
-
-struct tm6000_fmt {
-       char  *name;
-       u32   fourcc;          /* v4l2 format id */
-       int   depth;
-};
-
-/* buffer for one video frame */
-struct tm6000_buffer {
-       /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer vb;
-
-       struct tm6000_fmt      *fmt;
-};
-
-struct tm6000_dmaqueue {
-       struct list_head       active;
-       struct list_head       queued;
-
-       /* thread for generating video stream*/
-       struct task_struct         *kthread;
-       wait_queue_head_t          wq;
-       /* Counters to control fps rate */
-       int                        frame;
-       int                        ini_jiffies;
-};
-
-/* device states */
-enum tm6000_core_state {
-       DEV_INITIALIZED   = 0x01,
-       DEV_DISCONNECTED  = 0x02,
-       DEV_MISCONFIGURED = 0x04,
-};
-
-/* io methods */
-enum tm6000_io_method {
-       IO_NONE,
-       IO_READ,
-       IO_MMAP,
-};
-
-enum tm6000_mode {
-       TM6000_MODE_UNKNOWN = 0,
-       TM6000_MODE_ANALOG,
-       TM6000_MODE_DIGITAL,
-};
-
-struct tm6000_gpio {
-       int             tuner_reset;
-       int             tuner_on;
-       int             demod_reset;
-       int             demod_on;
-       int             power_led;
-       int             dvb_led;
-       int             ir;
-};
-
-struct tm6000_capabilities {
-       unsigned int    has_tuner:1;
-       unsigned int    has_tda9874:1;
-       unsigned int    has_dvb:1;
-       unsigned int    has_zl10353:1;
-       unsigned int    has_eeprom:1;
-       unsigned int    has_remote:1;
-       unsigned int    has_radio:1;
-};
-
-struct tm6000_dvb {
-       struct dvb_adapter      adapter;
-       struct dvb_demux        demux;
-       struct dvb_frontend     *frontend;
-       struct dmxdev           dmxdev;
-       unsigned int            streams;
-       struct urb              *bulk_urb;
-       struct mutex            mutex;
-};
-
-struct snd_tm6000_card {
-       struct snd_card                 *card;
-       spinlock_t                      reg_lock;
-       struct tm6000_core              *core;
-       struct snd_pcm_substream        *substream;
-
-       /* temporary data for buffer fill processing */
-       unsigned                        buf_pos;
-       unsigned                        period_pos;
-};
-
-struct tm6000_endpoint {
-       struct usb_host_endpoint        *endp;
-       __u8                            bInterfaceNumber;
-       __u8                            bAlternateSetting;
-       unsigned                        maxsize;
-};
-
-#define TM6000_QUIRK_NO_USB_DELAY (1 << 0)
-
-struct tm6000_core {
-       /* generic device properties */
-       char                            name[30];       /* name (including minor) of the device */
-       int                             model;          /* index in the device_data struct */
-       int                             devno;          /* marks the number of this device */
-       enum tm6000_devtype             dev_type;       /* type of device */
-       unsigned char                   eedata[256];    /* Eeprom data */
-       unsigned                        eedata_size;    /* Size of the eeprom info */
-
-       v4l2_std_id                     norm;           /* Current norm */
-       int                             width, height;  /* Selected resolution */
-
-       enum tm6000_core_state          state;
-
-       /* Device Capabilities*/
-       struct tm6000_capabilities      caps;
-
-       /* Tuner configuration */
-       int                             tuner_type;             /* type of the tuner */
-       int                             tuner_addr;             /* tuner address */
-
-       struct tm6000_gpio              gpio;
-
-       char                            *ir_codes;
-
-       __u8                            radio;
-
-       /* Demodulator configuration */
-       int                             demod_addr;     /* demodulator address */
-
-       int                             audio_bitrate;
-       /* i2c i/o */
-       struct i2c_adapter              i2c_adap;
-       struct i2c_client               i2c_client;
-
-
-       /* extension */
-       struct list_head                devlist;
-
-       /* video for linux */
-       int                             users;
-
-       /* various device info */
-       struct tm6000_fh                *resources;     /* Points to fh that is streaming */
-       bool                            is_res_read;
-
-       struct video_device             *vfd;
-       struct video_device             *radio_dev;
-       struct tm6000_dmaqueue          vidq;
-       struct v4l2_device              v4l2_dev;
-
-       int                             input;
-       struct tm6000_input             vinput[3];      /* video input */
-       struct tm6000_input             rinput;         /* radio input */
-
-       int                             freq;
-       unsigned int                    fourcc;
-
-       enum tm6000_mode                mode;
-
-       int                             ctl_mute;             /* audio */
-       int                             ctl_volume;
-       int                             amode;
-
-       /* DVB-T support */
-       struct tm6000_dvb               *dvb;
-
-       /* audio support */
-       struct snd_tm6000_card          *adev;
-       struct work_struct              wq_trigger;   /* Trigger to start/stop audio for alsa module */
-       atomic_t                        stream_started;  /* stream should be running if true */
-
-       struct tm6000_IR                *ir;
-
-       /* locks */
-       struct mutex                    lock;
-       struct mutex                    usb_lock;
-
-       /* usb transfer */
-       struct usb_device               *udev;          /* the usb device */
-
-       struct tm6000_endpoint          bulk_in, bulk_out, isoc_in, isoc_out;
-       struct tm6000_endpoint          int_in, int_out;
-
-       /* scaler!=0 if scaler is active*/
-       int                             scaler;
-
-               /* Isoc control struct */
-       struct usb_isoc_ctl          isoc_ctl;
-
-       spinlock_t                   slock;
-
-       unsigned long quirks;
-};
-
-enum tm6000_ops_type {
-       TM6000_AUDIO = 0x10,
-       TM6000_DVB = 0x20,
-};
-
-struct tm6000_ops {
-       struct list_head        next;
-       char                    *name;
-       enum tm6000_ops_type    type;
-       int (*init)(struct tm6000_core *);
-       int (*fini)(struct tm6000_core *);
-       int (*fillbuf)(struct tm6000_core *, char *buf, int size);
-};
-
-struct tm6000_fh {
-       struct tm6000_core           *dev;
-       unsigned int                 radio;
-
-       /* video capture */
-       struct tm6000_fmt            *fmt;
-       unsigned int                 width, height;
-       struct videobuf_queue        vb_vidq;
-
-       enum v4l2_buf_type           type;
-};
-
-#define TM6000_STD     (V4L2_STD_PAL|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|    \
-                       V4L2_STD_PAL_M|V4L2_STD_PAL_60|V4L2_STD_NTSC_M| \
-                       V4L2_STD_NTSC_M_JP|V4L2_STD_SECAM)
-
-/* In tm6000-cards.c */
-
-int tm6000_tuner_callback(void *ptr, int component, int command, int arg);
-int tm6000_xc5000_callback(void *ptr, int component, int command, int arg);
-int tm6000_cards_setup(struct tm6000_core *dev);
-void tm6000_flash_led(struct tm6000_core *dev, u8 state);
-
-/* In tm6000-core.c */
-
-int tm6000_read_write_usb(struct tm6000_core *dev, u8 reqtype, u8 req,
-                          u16 value, u16 index, u8 *buf, u16 len);
-int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index);
-int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index);
-int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index);
-int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index);
-int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
-                                               u16 index, u16 mask);
-int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep);
-int tm6000_init(struct tm6000_core *dev);
-int tm6000_reset(struct tm6000_core *dev);
-
-int tm6000_init_analog_mode(struct tm6000_core *dev);
-int tm6000_init_digital_mode(struct tm6000_core *dev);
-int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate);
-int tm6000_set_audio_rinput(struct tm6000_core *dev);
-int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute);
-void tm6000_set_volume(struct tm6000_core *dev, int vol);
-
-int tm6000_v4l2_register(struct tm6000_core *dev);
-int tm6000_v4l2_unregister(struct tm6000_core *dev);
-int tm6000_v4l2_exit(void);
-void tm6000_set_fourcc_format(struct tm6000_core *dev);
-
-void tm6000_remove_from_devlist(struct tm6000_core *dev);
-void tm6000_add_into_devlist(struct tm6000_core *dev);
-int tm6000_register_extension(struct tm6000_ops *ops);
-void tm6000_unregister_extension(struct tm6000_ops *ops);
-void tm6000_init_extension(struct tm6000_core *dev);
-void tm6000_close_extension(struct tm6000_core *dev);
-int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type,
-                       char *buf, int size);
-
-
-/* In tm6000-stds.c */
-void tm6000_get_std_res(struct tm6000_core *dev);
-int tm6000_set_standard(struct tm6000_core *dev);
-
-/* In tm6000-i2c.c */
-int tm6000_i2c_register(struct tm6000_core *dev);
-int tm6000_i2c_unregister(struct tm6000_core *dev);
-
-/* In tm6000-queue.c */
-
-int tm6000_v4l2_mmap(struct file *filp, struct vm_area_struct *vma);
-
-int tm6000_vidioc_streamon(struct file *file, void *priv,
-                          enum v4l2_buf_type i);
-int tm6000_vidioc_streamoff(struct file *file, void *priv,
-                           enum v4l2_buf_type i);
-int tm6000_vidioc_reqbufs(struct file *file, void *priv,
-                         struct v4l2_requestbuffers *rb);
-int tm6000_vidioc_querybuf(struct file *file, void *priv,
-                          struct v4l2_buffer *b);
-int tm6000_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b);
-int tm6000_vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b);
-ssize_t tm6000_v4l2_read(struct file *filp, char __user * buf, size_t count,
-                        loff_t *f_pos);
-unsigned int tm6000_v4l2_poll(struct file *file,
-                             struct poll_table_struct *wait);
-int tm6000_queue_init(struct tm6000_core *dev);
-
-/* In tm6000-alsa.c */
-/*int tm6000_audio_init(struct tm6000_core *dev, int idx);*/
-
-/* In tm6000-input.c */
-int tm6000_ir_init(struct tm6000_core *dev);
-int tm6000_ir_fini(struct tm6000_core *dev);
-void tm6000_ir_wait(struct tm6000_core *dev, u8 state);
-int tm6000_ir_int_start(struct tm6000_core *dev);
-void tm6000_ir_int_stop(struct tm6000_core *dev);
-
-/* Debug stuff */
-
-extern int tm6000_debug;
-
-#define dprintk(dev, level, fmt, arg...) do {\
-       if (tm6000_debug & level) \
-               printk(KERN_INFO "(%lu) %s %s :"fmt, jiffies, \
-                        dev->name, __func__ , ##arg); } while (0)
-
-#define V4L2_DEBUG_REG         0x0004
-#define V4L2_DEBUG_I2C         0x0008
-#define V4L2_DEBUG_QUEUE       0x0010
-#define V4L2_DEBUG_ISOC                0x0020
-#define V4L2_DEBUG_RES_LOCK    0x0040  /* Resource locking */
-#define V4L2_DEBUG_OPEN                0x0080  /* video open/close debug */
-
-#define tm6000_err(fmt, arg...) do {\
-       printk(KERN_ERR "tm6000 %s :"fmt, \
-               __func__ , ##arg); } while (0)