V4L/DVB (10954): Add cx231xx USB driver
Sri Deevi [Tue, 3 Mar 2009 17:37:50 +0000 (14:37 -0300)]
Signed-off-by: Srinivasa Deevi <srinivasa.deevi@conexant.com>
[mchehab@redhat.com: Remove the Kconfig changes, to avoid git breakages]
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

17 files changed:
drivers/media/video/Makefile
drivers/media/video/cx231xx/Kconfig [new file with mode: 0644]
drivers/media/video/cx231xx/Makefile [new file with mode: 0644]
drivers/media/video/cx231xx/cx231xx-audio.c [new file with mode: 0644]
drivers/media/video/cx231xx/cx231xx-avcore.c [new file with mode: 0644]
drivers/media/video/cx231xx/cx231xx-cards.c [new file with mode: 0644]
drivers/media/video/cx231xx/cx231xx-conf-reg.h [new file with mode: 0644]
drivers/media/video/cx231xx/cx231xx-core.c [new file with mode: 0644]
drivers/media/video/cx231xx/cx231xx-dvb.c [new file with mode: 0644]
drivers/media/video/cx231xx/cx231xx-i2c.c [new file with mode: 0644]
drivers/media/video/cx231xx/cx231xx-input.c [new file with mode: 0644]
drivers/media/video/cx231xx/cx231xx-reg.h [new file with mode: 0644]
drivers/media/video/cx231xx/cx231xx-vbi.c [new file with mode: 0644]
drivers/media/video/cx231xx/cx231xx-vbi.h [new file with mode: 0644]
drivers/media/video/cx231xx/cx231xx-video.c [new file with mode: 0644]
drivers/media/video/cx231xx/cx231xx.h [new file with mode: 0644]
include/linux/i2c-id.h

index ba02977..7c0bd6e 100644 (file)
@@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o
 obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
 obj-$(CONFIG_VIDEO_CX88) += cx88/
 obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
+obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
 obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
 obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
 obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig
new file mode 100644 (file)
index 0000000..0f0e2b9
--- /dev/null
@@ -0,0 +1,35 @@
+config VIDEO_CX231XX
+       tristate "Conexant cx231xx USB video capture support"
+       depends on VIDEO_DEV && I2C && INPUT
+       select VIDEO_TUNER
+       select VIDEO_TVEEPROM
+       select VIDEO_IR
+       select VIDEOBUF_VMALLOC
+       select VIDEO_CX25840
+       select VIDEO_CX231XX_ALSA
+
+       ---help---
+         This is a video4linux driver for Conexant 231xx USB based TV cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx231xx
+
+config VIDEO_CX231XX_ALSA
+    tristate "Conexant Cx231xx ALSA audio module"
+       depends on VIDEO_CX231XX && SND
+       select SND_PCM
+
+       ---help---
+         This is an ALSA driver for Cx231xx USB based TV cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx231xx-alsa
+
+config VIDEO_CX231XX_DVB
+       tristate "DVB/ATSC Support for Cx231xx based TV cards"
+       depends on VIDEO_CX231XX && DVB_CORE
+       select VIDEOBUF_DVB
+       select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE
+       ---help---
+         This adds support for DVB cards based on the
+         Conexant cx231xx chips.
diff --git a/drivers/media/video/cx231xx/Makefile b/drivers/media/video/cx231xx/Makefile
new file mode 100644 (file)
index 0000000..2590a09
--- /dev/null
@@ -0,0 +1,15 @@
+cx231xx-objs     := cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o \
+                    cx231xx-avcore.o cx231xx-pcb-config.o cx231xx-vbi.o
+
+cx231xx-alsa-objs := cx231xx-audio.o
+
+
+obj-$(CONFIG_VIDEO_CX231XX) += cx231xx.o
+obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o
+obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o
+
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/common/tuners
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+
diff --git a/drivers/media/video/cx231xx/cx231xx-audio.c b/drivers/media/video/cx231xx/cx231xx-audio.c
new file mode 100644 (file)
index 0000000..e4335e2
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ *  Conexant Cx231xx audio extension
+ *
+ *  Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+ *       Based on em28xx driver
+ *
+ *
+ *  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; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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/usb.h>
+#include <linux/init.h>
+#include <linux/sound.h>
+#include <linux/spinlock.h>
+#include <linux/soundcard.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/info.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#include <media/v4l2-common.h>
+#include "cx231xx.h"
+#include "cx231xx-pcb-config.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "activates debug info");
+
+#define dprintk(fmt, arg...) do {                                      \
+           if (debug)                                                  \
+               printk(KERN_INFO "cx231xx-audio %s: " fmt,              \
+                                 __func__, ##arg);             \
+       } while (0)
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+
+static int cx231xx_isoc_audio_deinit(struct cx231xx *dev)
+{
+       int i;
+
+       dprintk("Stopping isoc\n");
+
+
+       for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
+        if(dev->adev.urb[i]) {
+            if (!irqs_disabled())
+                           usb_kill_urb(dev->adev.urb[i]);
+                   else
+                       usb_unlink_urb(dev->adev.urb[i]);
+
+                   usb_free_urb(dev->adev.urb[i]);
+                   dev->adev.urb[i] = NULL;
+
+            kfree(dev->adev.transfer_buffer[i]);
+                   dev->adev.transfer_buffer[i] = NULL;
+
+        }
+       }
+
+       return 0;
+}
+
+static void cx231xx_audio_isocirq(struct urb *urb)
+{
+       struct cx231xx            *dev = urb->context;
+       int                      i;
+       unsigned int             oldptr;
+       int                      period_elapsed = 0;
+       int                      status;
+       unsigned char            *cp;
+       unsigned int             stride;
+       struct snd_pcm_substream *substream;
+       struct snd_pcm_runtime   *runtime;
+
+    switch (urb->status) {
+           case 0:             /* success */
+           case -ETIMEDOUT:    /* NAK */
+                   break;
+           case -ECONNRESET:   /* kill */
+           case -ENOENT:
+           case -ESHUTDOWN:
+                   return;
+           default:            /* error */
+                   dprintk("urb completition error %d.\n", urb->status);
+                   break;
+       }
+
+       if (dev->adev.capture_pcm_substream) {
+               substream = dev->adev.capture_pcm_substream;
+               runtime = substream->runtime;
+               stride = runtime->frame_bits >> 3;
+
+               for (i = 0; i < urb->number_of_packets; i++) {
+                       int length =
+                           urb->iso_frame_desc[i].actual_length / stride;
+                       cp = (unsigned char *)urb->transfer_buffer +
+                           urb->iso_frame_desc[i].offset;
+
+                       if (!length)
+                               continue;
+
+                       oldptr = dev->adev.hwptr_done_capture;
+                       if (oldptr + length >= runtime->buffer_size) {
+                               unsigned int cnt =
+                                   runtime->buffer_size - oldptr;
+                               memcpy(runtime->dma_area + oldptr * stride, cp,
+                                      cnt * stride);
+                               memcpy(runtime->dma_area, cp + cnt * stride,
+                                      length * stride - cnt * stride);
+                       } else {
+                               memcpy(runtime->dma_area + oldptr * stride, cp,
+                                      length * stride);
+                       }
+
+                       snd_pcm_stream_lock(substream);
+
+                       dev->adev.hwptr_done_capture += length;
+                       if (dev->adev.hwptr_done_capture >=
+                           runtime->buffer_size)
+                               dev->adev.hwptr_done_capture -=
+                                   runtime->buffer_size;
+
+                       dev->adev.capture_transfer_done += length;
+                       if (dev->adev.capture_transfer_done >=
+                           runtime->period_size) {
+                               dev->adev.capture_transfer_done -=
+                                   runtime->period_size;
+                               period_elapsed = 1;
+                       }
+
+                       snd_pcm_stream_unlock(substream);
+               }
+               if (period_elapsed)
+                       snd_pcm_period_elapsed(substream);
+       }
+       urb->status = 0;
+
+       status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (status < 0) {
+               cx231xx_errdev("resubmit of audio urb failed (error=%i)\n",
+                             status);
+       }
+       return;
+}
+
+static int cx231xx_init_audio_isoc(struct cx231xx *dev)
+{
+       int       i, errCode;
+       int       sb_size;
+
+    cx231xx_info("%s: Starting AUDIO transfers\n",__func__);
+
+    sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
+
+       for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
+               struct urb *urb;
+               int j, k;
+
+               dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
+               if (!dev->adev.transfer_buffer[i])
+                       return -ENOMEM;
+
+               memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
+               urb = usb_alloc_urb(CX231XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
+               if (!urb) {
+                       cx231xx_errdev("usb_alloc_urb failed!\n");
+                       for (j = 0; j < i; j++) {
+                               usb_free_urb(dev->adev.urb[j]);
+                               kfree(dev->adev.transfer_buffer[j]);
+                       }
+                       return -ENOMEM;
+               }
+
+               urb->dev = dev->udev;
+               urb->context = dev;
+               urb->pipe = usb_rcvisocpipe(dev->udev, dev->adev.end_point_addr);
+               urb->transfer_flags = URB_ISO_ASAP;
+               urb->transfer_buffer = dev->adev.transfer_buffer[i];
+               urb->interval = 1;
+               urb->complete = cx231xx_audio_isocirq;
+               urb->number_of_packets = CX231XX_NUM_AUDIO_PACKETS;
+               urb->transfer_buffer_length = sb_size;
+
+               for (j = k = 0; j < CX231XX_NUM_AUDIO_PACKETS;
+                            j++, k += dev->adev.max_pkt_size) {
+                       urb->iso_frame_desc[j].offset = k;
+                       urb->iso_frame_desc[j].length =
+                           dev->adev.max_pkt_size;
+               }
+               dev->adev.urb[i] = urb;
+       }
+
+       for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
+               errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
+               if (errCode < 0) {
+                       cx231xx_isoc_audio_deinit(dev);
+                       return errCode;
+               }
+       }
+
+       return errCode;
+}
+
+static int cx231xx_cmd(struct cx231xx *dev, int cmd, int arg)
+{
+       dprintk("%s transfer\n", (dev->adev.capture_stream == STREAM_ON)?
+                                "stop" : "start");
+
+       switch (cmd) {
+    case CX231XX_CAPTURE_STREAM_EN:
+               if (dev->adev.capture_stream == STREAM_OFF && arg == 1) {
+                       dev->adev.capture_stream = STREAM_ON;
+                       cx231xx_init_audio_isoc(dev);
+               } else if (dev->adev.capture_stream == STREAM_ON && arg == 0) {
+                       dev->adev.capture_stream = STREAM_OFF;
+                       cx231xx_isoc_audio_deinit(dev);
+               } else {
+                       cx231xx_errdev( "An underrun very likely occurred. "
+                                       "Ignoring it.\n");
+               }
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
+                                       size_t size)
+{
+       struct snd_pcm_runtime *runtime = subs->runtime;
+
+       dprintk("Allocating vbuffer\n");
+       if (runtime->dma_area) {
+               if (runtime->dma_bytes > size)
+                       return 0;
+
+               vfree(runtime->dma_area);
+       }
+       runtime->dma_area = vmalloc(size);
+       if (!runtime->dma_area)
+               return -ENOMEM;
+
+       runtime->dma_bytes = size;
+
+       return 0;
+}
+
+static struct snd_pcm_hardware snd_cx231xx_hw_capture = {
+       .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP           |
+               SNDRV_PCM_INFO_INTERLEAVED    |
+               SNDRV_PCM_INFO_MMAP_VALID,
+
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+       .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT,
+
+       .rate_min = 48000,
+       .rate_max = 48000,
+       .channels_min = 2,
+       .channels_max = 2,
+       .buffer_bytes_max = 62720 * 8,  /* just about the value in usbaudio.c */
+       .period_bytes_min = 64,             /* 12544/2, */
+       .period_bytes_max = 12544,
+       .periods_min = 2,
+       .periods_max = 98,                      /* 12544, */
+};
+
+static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream)
+{
+       struct cx231xx *dev = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int ret = 0;
+
+       dprintk("opening device and trying to acquire exclusive lock\n");
+
+       if (!dev) {
+               cx231xx_errdev("BUG: cx231xx can't find device struct."
+                               " Can't proceed with open\n");
+               return -ENODEV;
+       }
+
+       /* Sets volume, mute, etc */
+       dev->mute = 0;
+
+    /* set alternate setting for audio interface */
+    ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1); /* 1 - 48000 samples per sec */
+    if (ret < 0) {
+        cx231xx_errdev("failed to set alternate setting !\n");
+
+        return ret;
+    }
+
+    /* inform hardware to start streaming */
+    ret = cx231xx_capture_start(dev, 1, Audio);
+
+       runtime->hw = snd_cx231xx_hw_capture;
+
+    mutex_lock(&dev->lock);
+       dev->adev.users++;
+    mutex_unlock(&dev->lock);
+
+       snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+       dev->adev.capture_pcm_substream = substream;
+       runtime->private_data = dev;
+
+       return 0;
+}
+
+static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream)
+{
+    int ret;
+       struct cx231xx *dev = snd_pcm_substream_chip(substream);
+
+
+       dprintk("closing device\n");
+
+    /* set alternate setting for audio interface */
+    ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0); /* 1 - 48000 samples per sec */
+    if (ret < 0) {
+        cx231xx_errdev("failed to set alternate setting !\n");
+
+        return ret;
+    }
+
+    /* inform hardware to start streaming */
+    ret = cx231xx_capture_start(dev, 0, Audio);
+
+       dev->mute = 1;
+       mutex_lock(&dev->lock);
+    dev->adev.users--;
+       mutex_unlock(&dev->lock);
+
+       if (dev->adev.users == 0 && dev->adev.shutdown == 1) {
+               dprintk("audio users: %d\n", dev->adev.users);
+               dprintk("disabling audio stream!\n");
+               dev->adev.shutdown = 0;
+               dprintk("released lock\n");
+               cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, 0);
+       }
+       return 0;
+}
+
+static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream,
+                                       struct snd_pcm_hw_params *hw_params)
+{
+       unsigned int channels, rate, format;
+       int ret;
+
+       dprintk("Setting capture parameters\n");
+
+       ret = snd_pcm_alloc_vmalloc_buffer(substream,
+                               params_buffer_bytes(hw_params));
+       format = params_format(hw_params);
+       rate = params_rate(hw_params);
+       channels = params_channels(hw_params);
+
+       /* TODO: set up cx231xx audio chip to deliver the correct audio format,
+          current default is 48000hz multiplexed => 96000hz mono
+          which shouldn't matter since analogue TV only supports mono */
+       return 0;
+}
+
+static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream)
+{
+       struct cx231xx *dev = snd_pcm_substream_chip(substream);
+
+       dprintk("Stop capture, if needed\n");
+
+       if (dev->adev.capture_stream == STREAM_ON)
+               cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, CX231XX_STOP_AUDIO);
+
+       return 0;
+}
+
+static int snd_cx231xx_prepare(struct snd_pcm_substream *substream)
+{
+       return 0;
+}
+
+static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream,
+                                     int cmd)
+{
+       struct cx231xx *dev = snd_pcm_substream_chip(substream);
+    int retval;
+
+
+       dprintk("Should %s capture\n", (cmd == SNDRV_PCM_TRIGGER_START)?
+                                      "start": "stop");
+
+    spin_lock(&dev->adev.slock);
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, CX231XX_START_AUDIO);
+               retval = 0;
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+        cx231xx_cmd(dev, CX231XX_CAPTURE_STREAM_EN, CX231XX_STOP_AUDIO);
+               retval = 0;
+        break;
+       default:
+               retval = -EINVAL;
+       }
+
+    spin_unlock(&dev->adev.slock);
+       return retval;
+}
+
+static snd_pcm_uframes_t snd_cx231xx_capture_pointer(struct snd_pcm_substream
+                                                   *substream)
+{
+       struct cx231xx *dev;
+    unsigned long flags;
+       snd_pcm_uframes_t hwptr_done;
+
+       dev = snd_pcm_substream_chip(substream);
+
+    spin_lock_irqsave(&dev->adev.slock, flags);
+       hwptr_done = dev->adev.hwptr_done_capture;
+    spin_unlock_irqrestore(&dev->adev.slock, flags);
+
+       return hwptr_done;
+}
+
+static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
+                                            unsigned long offset)
+{
+       void *pageptr = subs->runtime->dma_area + offset;
+
+       return vmalloc_to_page(pageptr);
+}
+
+static struct snd_pcm_ops snd_cx231xx_pcm_capture = {
+       .open      = snd_cx231xx_capture_open,
+       .close     = snd_cx231xx_pcm_close,
+       .ioctl     = snd_pcm_lib_ioctl,
+       .hw_params = snd_cx231xx_hw_capture_params,
+       .hw_free   = snd_cx231xx_hw_capture_free,
+       .prepare   = snd_cx231xx_prepare,
+       .trigger   = snd_cx231xx_capture_trigger,
+       .pointer   = snd_cx231xx_capture_pointer,
+       .page      = snd_pcm_get_vmalloc_page,
+};
+
+static int cx231xx_audio_init(struct cx231xx *dev)
+{
+       struct cx231xx_audio *adev = &dev->adev;
+       struct snd_pcm      *pcm;
+       struct snd_card     *card;
+       static int          devnr;
+       int                 err;
+    struct usb_interface *uif;
+    int i, isoc_pipe = 0;
+
+       if (dev->has_alsa_audio != 1) {
+               /* This device does not support the extension (in this case
+                  the device is expecting the snd-usb-audio module or
+                  doesn't have analog audio support at all) */
+               return 0;
+       }
+
+       cx231xx_info("cx231xx-audio.c: probing for cx231xx "
+                        "non standard usbaudio\n");
+
+       card = snd_card_new(index[devnr], "Cx231xx Audio", THIS_MODULE, 0);
+       if (card == NULL) {
+               return -ENOMEM;
+       }
+
+       spin_lock_init(&adev->slock);
+       err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx231xx_pcm_capture);
+       pcm->info_flags = 0;
+       pcm->private_data = dev;
+       strcpy(pcm->name, "Conexant cx231xx Capture");
+       strcpy(card->driver, "Conexant cx231xx Audio");
+       strcpy(card->shortname, "Cx231xx Audio");
+       strcpy(card->longname, "Conexant cx231xx Audio");
+
+       err = snd_card_register(card);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+       adev->sndcard = card;
+       adev->udev = dev->udev;
+
+    /* compute alternate max packet sizes for Audio */
+    uif = dev->udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.audio_index+1];
+
+    adev->end_point_addr = le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress);
+
+    adev->num_alt = uif->num_altsetting;
+    cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", adev->end_point_addr,
+                                    adev->num_alt);
+    adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL);
+
+    if (adev->alt_max_pkt_size == NULL) {
+        cx231xx_errdev("out of memory!\n");
+        return -ENOMEM;
+    }
+
+    for (i = 0; i < adev->num_alt ; i++) {
+        u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.
+                                               wMaxPacketSize);
+        adev->alt_max_pkt_size[i] =
+            (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+        cx231xx_info("Alternate setting %i, max size= %i\n", i,
+                                       adev->alt_max_pkt_size[i]);
+    }
+
+       return 0;
+}
+
+static int cx231xx_audio_fini(struct cx231xx *dev)
+{
+       if (dev == NULL)
+               return 0;
+
+       if (dev->has_alsa_audio != 1) {
+               /* This device does not support the extension (in this case
+                  the device is expecting the snd-usb-audio module or
+                  doesn't have analog audio support at all) */
+               return 0;
+       }
+
+       if (dev->adev.sndcard) {
+               snd_card_free(dev->adev.sndcard);
+        kfree(dev->adev.alt_max_pkt_size);
+               dev->adev.sndcard = NULL;
+       }
+
+       return 0;
+}
+
+static struct cx231xx_ops audio_ops = {
+    .id   = CX231XX_AUDIO,
+       .name = "Cx231xx Audio Extension",
+       .init = cx231xx_audio_init,
+       .fini = cx231xx_audio_fini,
+};
+
+static int __init cx231xx_alsa_register(void)
+{
+       return cx231xx_register_extension(&audio_ops);
+}
+
+static void __exit cx231xx_alsa_unregister(void)
+{
+       cx231xx_unregister_extension(&audio_ops);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
+MODULE_DESCRIPTION("Cx231xx Audio driver");
+
+module_init(cx231xx_alsa_register);
+module_exit(cx231xx_alsa_unregister);
diff --git a/drivers/media/video/cx231xx/cx231xx-avcore.c b/drivers/media/video/cx231xx/cx231xx-avcore.c
new file mode 100644 (file)
index 0000000..b559733
--- /dev/null
@@ -0,0 +1,2289 @@
+/*
+   cx231xx_avcore.c - driver for Conexant Cx23100/101/102 USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+
+   This program contains the specific code to control the avdecoder chip and
+   other related usb control functions for cx231xx based chipset.
+
+   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; either version 2 of the License, or
+   (at your option) any later version.
+
+   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/list.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/bitmap.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <linux/version.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-chip-ident.h>
+
+#include "cx231xx.h"
+
+
+/*************************************************************************************
+ *            C O L I B R I - B L O C K    C O N T R O L   functions                 *
+ *************************************************************************************/
+int cx231xx_colibri_init_super_block(struct cx231xx *dev, u32 ref_count)
+{
+    int status = 0;
+    u8 temp = 0;
+    u32 colibri_power_status = 0;
+    int i = 0;
+
+    /* super block initialize */
+    temp = (u8)(ref_count & 0xff);
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE2, 2, temp, 1);
+
+    status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE2, 2, &colibri_power_status, 1);
+
+    temp = (u8)((ref_count & 0x300) >> 8);
+    temp |= 0x40;
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE1, 2, temp, 1);
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PLL2, 2, 0x0f, 1);
+
+    /* enable pll     */
+    while(colibri_power_status != 0x18)
+    {
+        status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, 0x18, 1);
+        status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_PWRDN, 2, &colibri_power_status, 1);
+        colibri_power_status &= 0xff;
+        if(status < 0) {
+            cx231xx_info(": Init Super Block failed in sending/receiving cmds\n");
+            break;
+        }
+        i++;
+        if( i == 10) {
+            cx231xx_info(": Init Super Block force break in loop !!!!\n");
+            status = -1;
+            break;
+        }
+    }
+
+    if(status < 0 )
+        return status;
+
+    /* start tuning filter */
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE3, 2, 0x40, 1);
+    msleep(5);
+
+    /* exit tuning */
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, SUP_BLK_TUNE3, 2, 0x00, 1);
+
+    return status;
+}
+
+int cx231xx_colibri_init_channels(struct cx231xx *dev)
+{
+    int status = 0;
+
+    /* power up all 3 channels, clear pd_buffer */
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1);
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1);
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1);
+
+    /* Enable quantizer calibration */
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_COM_QUANT, 2, 0x02, 1);
+
+    /* channel initialize, force modulator (fb) reset */
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH1, 2, 0x17, 1);
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH2, 2, 0x17, 1);
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH3, 2, 0x17, 1);
+
+    /* start quantilizer calibration  */
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_CAL_ATEST_CH1, 2, 0x10, 1);
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_CAL_ATEST_CH2, 2, 0x10, 1);
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_CAL_ATEST_CH3, 2, 0x10, 1);
+    msleep(5);
+
+    /* exit modulator (fb) reset */
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH1, 2, 0x07, 1);
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH2, 2, 0x07, 1);
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_FB_FRCRST_CH3, 2, 0x07, 1);
+
+    /* enable the pre_clamp in each channel for single-ended input */
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH1, 2, 0xf0, 1);
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH2, 2, 0xf0, 1);
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_NTF_PRECLMP_EN_CH3, 2, 0xf0, 1);
+
+    /* use diode instead of resistor, so set term_en to 0, res_en to 0  */
+    status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH1, 3, 7, 0x00);
+    status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH2, 3, 7, 0x00);
+    status = cx231xx_reg_mask_write(dev, Colibri_DEVICE_ADDRESS, 8, ADC_QGAIN_RES_TRM_CH3, 3, 7, 0x00);
+
+    /* dynamic element matching off */
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_DCSERVO_DEM_CH1, 2, 0x03, 1);
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_DCSERVO_DEM_CH2, 2, 0x03, 1);
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_DCSERVO_DEM_CH3, 2, 0x03, 1);
+
+    return status;
+}
+
+int cx231xx_colibri_setup_AFE_for_baseband(struct cx231xx *dev)
+{
+    u32 c_value = 0;
+    int status = 0;
+
+    status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, &c_value, 1);
+    c_value &= (~(0x50));
+    status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_PWRDN_CLAMP_CH2, 2, c_value, 1);
+
+    return status;
+}
+
+/*
+       we have 3 channel
+       channel 1 ----- pin 1  to pin4(in reg is 1-4)
+       channel 2 ----- pin 5  to pin8(in reg is 5-8)
+       channel 3 ----- pin 9 to pin 12(in reg is 9-11)
+*/
+int cx231xx_colibri_set_input_mux(struct cx231xx *dev, u32 input_mux)
+{
+    u8 ch1_setting = (u8)input_mux;
+    u8 ch2_setting = (u8)(input_mux >> 8);
+    u8 ch3_setting = (u8)(input_mux >> 16);
+    int status = 0;
+    u32 value = 0;
+
+    if(ch1_setting != 0)
+    {
+        status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH1, 2, &value, 1);
+        value &= (!INPUT_SEL_MASK);
+        value |= (ch1_setting-1)<<4;
+        value &= 0xff;
+        status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH1, 2, value, 1);
+    }
+
+    if(ch2_setting != 0)
+    {
+        status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH2, 2, &value, 1);
+        value &= (!INPUT_SEL_MASK);
+        value |= (ch2_setting-1)<<4;
+        value &= 0xff;
+        status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH2, 2, value, 1);
+    }
+
+    /* For ch3_setting, the value to put in the register is 7 less than the input number */
+    if(ch3_setting != 0)
+    {
+        status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH3, 2, &value, 1);
+        value &= (!INPUT_SEL_MASK);
+        value |= (ch3_setting-1)<<4;
+        value &= 0xff;
+        status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH3, 2, value, 1);
+    }
+
+    return status;
+}
+
+int cx231xx_colibri_set_mode(struct cx231xx *dev, enum AFE_MODE mode)
+{
+    int status = 0;
+
+    switch(mode) {
+        case AFE_MODE_LOW_IF:
+            /* SetupAFEforLowIF();  */
+            break;
+        case AFE_MODE_BASEBAND:
+            status = cx231xx_colibri_setup_AFE_for_baseband(dev);
+            break;
+        case AFE_MODE_EU_HI_IF:
+            /* SetupAFEforEuHiIF(); */
+            break;
+        case AFE_MODE_US_HI_IF:
+            /* SetupAFEforUsHiIF(); */
+            break;
+        case AFE_MODE_JAPAN_HI_IF:
+            /* SetupAFEforJapanHiIF(); */
+            break;
+    }
+
+    if((mode != dev->colibri_mode) && (dev->video_input == CX231XX_VMUX_TELEVISION)) {
+        status = cx231xx_colibri_adjust_ref_count(dev, CX231XX_VMUX_TELEVISION);
+    }
+
+    dev->colibri_mode  = mode;
+
+    return status;
+}
+
+/* For power saving in the EVK */
+int cx231xx_colibri_update_power_control(struct cx231xx *dev, AV_MODE avmode)
+{
+   u32 colibri_power_status = 0;
+   int status = 0;
+
+   switch (dev->model) {
+       case CX231XX_BOARD_CNXT_RDE_250:
+       case CX231XX_BOARD_CNXT_RDU_250:
+
+              if(avmode==POLARIS_AVMODE_ANALOGT_TV)
+              {
+                      while(colibri_power_status != 0x18) {
+                   status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     SUP_BLK_PWRDN, 2, 0x18, 1);
+                   status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     SUP_BLK_PWRDN, 2, &colibri_power_status, 1);
+                   if(status < 0 )
+                       break;
+                      }
+
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1);
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1);
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1);
+              }
+           else if(avmode==POLARIS_AVMODE_DIGITAL)  {
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH1, 2, 0x70, 1);
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH2, 2, 0x70, 1);
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH3, 2, 0x70, 1);
+
+               status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     SUP_BLK_PWRDN, 2, &colibri_power_status, 1);
+                      colibri_power_status |=0x07;
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     SUP_BLK_PWRDN, 2, colibri_power_status, 1);
+              }
+              else if(avmode==POLARIS_AVMODE_ENXTERNAL_AV)  {
+
+                      while(colibri_power_status != 0x18) {
+                              status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     SUP_BLK_PWRDN, 2, 0x18, 1);
+                   status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     SUP_BLK_PWRDN, 2, &colibri_power_status, 1);
+                   if(status < 0 )
+                       break;
+                      }
+
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1);
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1);
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1);
+              }
+              else {
+                      cx231xx_info("Invalid AV mode input\n");
+               status = -1;
+              }
+              break;
+       default:
+              if(avmode==POLARIS_AVMODE_ANALOGT_TV)
+              {
+                      while(colibri_power_status != 0x18)  {
+                              status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     SUP_BLK_PWRDN, 2, 0x18, 1);
+                   status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     SUP_BLK_PWRDN, 2, &colibri_power_status, 1);
+                   if(status < 0 )
+                       break;
+                      }
+
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH1, 2, 0x40, 1);
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH2, 2, 0x40, 1);
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH3, 2, 0x00, 1);
+           }
+           else if(avmode==POLARIS_AVMODE_DIGITAL)  {
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH1, 2, 0x70, 1);
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH2, 2, 0x70, 1);
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH3, 2, 0x70, 1);
+
+               status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     SUP_BLK_PWRDN, 2, &colibri_power_status, 1);
+               colibri_power_status |=0x07;
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     SUP_BLK_PWRDN, 2, colibri_power_status, 1);
+           }
+           else if(avmode==POLARIS_AVMODE_ENXTERNAL_AV) {
+               while(colibri_power_status != 0x18)  {
+                              status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     SUP_BLK_PWRDN, 2, 0x18, 1);
+                   status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     SUP_BLK_PWRDN, 2, &colibri_power_status, 1);
+                   if(status < 0 )
+                       break;
+                      }
+
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH1, 2, 0x00, 1);
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH2, 2, 0x00, 1);
+               status = cx231xx_write_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                                     ADC_PWRDN_CLAMP_CH3, 2, 0x40, 1);
+           }
+           else  {
+                cx231xx_info("Invalid AV mode input\n");
+                status = -1;
+           }
+    } /* switch  */
+
+    return status;
+}
+
+int cx231xx_colibri_adjust_ref_count(struct cx231xx *dev, u32 video_input)
+{
+    u32 input_mode = 0;
+    u32 ntf_mode = 0;
+    int status = 0;
+
+    dev->video_input = video_input;
+
+    if(video_input == CX231XX_VMUX_TELEVISION) {
+        status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH3, 2, &input_mode, 1);
+        status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                            ADC_NTF_PRECLMP_EN_CH3, 2, &ntf_mode, 1);
+    }
+    else {
+        status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS, ADC_INPUT_CH1, 2, &input_mode, 1);
+        status = cx231xx_read_i2c_data(dev, Colibri_DEVICE_ADDRESS,
+                            ADC_NTF_PRECLMP_EN_CH1, 2, &ntf_mode, 1);
+    }
+
+    input_mode = (ntf_mode & 0x3) | ((input_mode & 0x6) << 1);
+
+    switch(input_mode)
+    {
+    case SINGLE_ENDED:
+        dev->colibri_ref_count = 0x23C;
+        break;
+    case LOW_IF:
+        dev->colibri_ref_count = 0x24C;
+        break;
+    case EU_IF:
+        dev->colibri_ref_count = 0x258;
+        break;
+    case US_IF:
+        dev->colibri_ref_count = 0x260;
+        break;
+    default:
+        break;
+    }
+
+    status = cx231xx_colibri_init_super_block(dev, dev->colibri_ref_count);
+
+    return status;
+}
+
+
+
+/*************************************************************************************
+ *       V I D E O / A U D I O    D E C O D E R    C O N T R O L   functions         *
+ *************************************************************************************/
+int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input)
+{
+    int status = 0;
+
+    switch(INPUT(input)->type) {
+        case CX231XX_VMUX_COMPOSITE1:
+        case CX231XX_VMUX_SVIDEO:
+            if((dev->current_pcb_config.type == USB_BUS_POWER) &&
+                        (dev->power_mode != POLARIS_AVMODE_ENXTERNAL_AV)) {
+                status = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ENXTERNAL_AV); /* External AV */
+                if (status < 0) {
+                    cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n",
+                                   __func__, status);
+                           return status;
+                   }
+            }
+            status = cx231xx_set_decoder_video_input(dev, INPUT(input)->type, INPUT(input)->vmux);
+            break;
+        case CX231XX_VMUX_TELEVISION:
+        case CX231XX_VMUX_CABLE:
+            if((dev->current_pcb_config.type == USB_BUS_POWER) &&
+                        (dev->power_mode != POLARIS_AVMODE_ANALOGT_TV)) {
+                status = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); /* Tuner */
+                if (status < 0) {
+                    cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n",
+                                   __func__, status);
+                           return status;
+                   }
+            }
+            status = cx231xx_set_decoder_video_input(dev, CX231XX_VMUX_COMPOSITE1, INPUT(input)->vmux);
+            break;
+        default:
+            cx231xx_errdev("%s: cx231xx_set_power_mode : Unknown Input %d !\n",
+                                   __func__, INPUT(input)->type);
+            break;
+    }
+
+    /* save the selection */
+    dev->video_input = input;
+
+    return status;
+}
+
+int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input)
+{
+    int status = 0;
+    u32 value = 0;
+
+    if(pin_type != dev->video_input) {
+        status = cx231xx_colibri_adjust_ref_count(dev, pin_type);
+        if(status < 0 ) {
+            cx231xx_errdev("%s: cx231xx_colibri_adjust_ref_count :Failed to set Colibri input mux - errCode [%d]!\n",
+                                       __func__, status);
+            return status;
+        }
+    }
+
+    /* call colibri block to set video inputs */
+    status = cx231xx_colibri_set_input_mux(dev, input);
+    if(status < 0 ) {
+        cx231xx_errdev("%s: cx231xx_colibri_set_input_mux :Failed to set Colibri input mux - errCode [%d]!\n",
+                                   __func__, status);
+        return status;
+    }
+
+    switch(pin_type) {
+        case CX231XX_VMUX_COMPOSITE1:
+            {
+                status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4);
+                value |= (0<<13)|(1<<4);
+                value  &= ~(1<<5);
+
+                value &= (~(0x1FF8000));        /* set [24:23] [22:15] to 0  */
+                value |= 0x1000000;             /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0  */
+                status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4);
+
+                status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, &value, 4);
+                value |= (1<<7);
+                status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, value, 4);
+
+                /* Set vip 1.1 output mode */
+                status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       OUT_CTRL1, FLD_OUT_MODE, OUT_MODE_VIP11);
+
+                /* Tell DIF object to go to baseband mode  */
+                status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
+                if (status < 0) {
+                           cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n",
+                                   __func__, status);
+                           return status;
+                   }
+
+                /* Read the DFE_CTRL1 register */
+                status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4);
+
+                /* enable the VBI_GATE_EN */
+                value |= FLD_VBI_GATE_EN;
+
+                /* Enable the auto-VGA enable */
+                value |= FLD_VGA_AUTO_EN;
+
+                /* Write it back */
+                status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4);
+
+                /* Disable auto config of registers */
+                status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1));
+
+                /* Set CVBS input mode */
+                status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       MODE_CTRL, FLD_INPUT_MODE,
+                                       cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0));
+            }
+            break;
+        case CX231XX_VMUX_SVIDEO:
+            {
+                /* Disable the use of  DIF */
+
+                status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4);
+
+                value &= (~(0x1FF8000));    /* set [24:23] [22:15] to 0 */
+                value |= 0x1000010;         /* set FUNC_MODE[24:23] = 2
+                                               IF_MOD[22:15] = 0 DCR_BYP_CH2[4:4] = 1; */
+                status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4);
+
+                /* Tell DIF object to go to baseband mode */
+                status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
+                if (status < 0) {
+                           cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n",
+                                   __func__, status);
+                           return status;
+                   }
+
+                /* Read the DFE_CTRL1 register */
+                status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4);
+
+                /* enable the VBI_GATE_EN */
+                value |= FLD_VBI_GATE_EN;
+
+                /* Enable the auto-VGA enable */
+                value |= FLD_VGA_AUTO_EN;
+
+                /* Write it back */
+                status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4);
+
+                /* Disable auto config of registers  */
+                status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1));
+
+                /* Set YC input mode */
+                status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       MODE_CTRL, FLD_INPUT_MODE,
+                                       cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_YC_1));
+
+                /* Chroma to ADC2 */
+                status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4);
+                value |= FLD_CHROMA_IN_SEL;         /* set the chroma in select */
+
+                /* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8)  This sets them to use video
+                   rather than audio.  Only one of the two will be in use. */
+                value &= ~(FLD_VGA_SEL_CH2 | FLD_VGA_SEL_CH3);
+
+                status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4);
+
+                status = cx231xx_colibri_set_mode(dev, AFE_MODE_BASEBAND);
+            }
+            break;
+        case CX231XX_VMUX_TELEVISION:
+        case CX231XX_VMUX_CABLE:
+        default:
+            {
+                switch(dev->model)  {
+                       case CX231XX_BOARD_CNXT_RDE_250:
+                       case CX231XX_BOARD_CNXT_RDU_250:
+                               {
+                                       /* Disable the use of  DIF   */
+
+                        status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4);
+                                       value |= (0<<13)|(1<<4);
+                                       value  &= ~(1<<5);
+
+                                       value &= (~(0x1FF8000));    /* set [24:23] [22:15] to 0 */
+                                       value |= 0x1000000;         /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */
+                        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4);
+
+                        status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, &value, 4);
+                                       value |= (1<<7);
+                        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, value, 4);
+
+                                       /* Set vip 1.1 output mode */
+                        status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       OUT_CTRL1, FLD_OUT_MODE, OUT_MODE_VIP11);
+
+                        /* Tell DIF object to go to baseband mode */
+                        status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
+                        if (status < 0) {
+                                   cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n",
+                                           __func__, status);
+                                   return status;
+                           }
+
+                                       /* Read the DFE_CTRL1 register */
+                        status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4);
+
+                                       /* enable the VBI_GATE_EN */
+                                       value |= FLD_VBI_GATE_EN;
+
+                                       /* Enable the auto-VGA enable */
+                                       value |= FLD_VGA_AUTO_EN;
+
+                                       /* Write it back */
+                        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4);
+
+                                       /* Disable auto config of registers */
+                        status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1));
+
+                        /* Set CVBS input mode */
+                        status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       MODE_CTRL, FLD_INPUT_MODE,
+                                       cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0));
+                               }
+                               break;
+                       default:
+                               {
+                                       /* Enable the DIF for the tuner */
+
+                                       /* Reinitialize the DIF */
+                        status = cx231xx_dif_set_standard(dev, dev->norm);
+                        if (status < 0) {
+                                   cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n",
+                                           __func__, status);
+                                   return status;
+                           }
+
+                                       /* Make sure bypass is cleared */
+                        status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, 2, &value, 4);
+
+                                       /* Clear the bypass bit */
+                                       value &= ~FLD_DIF_DIF_BYPASS;
+
+                                       /* Enable the use of the DIF block */
+                        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, 2, value, 4);
+
+                                       /* Read the DFE_CTRL1 register */
+                        status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, &value, 4);
+
+                                       /* Disable the VBI_GATE_EN */
+                                       value &= ~FLD_VBI_GATE_EN;
+
+                                       /* Enable the auto-VGA enable, AGC, and set the skip count to 2 */
+                                       value |= FLD_VGA_AUTO_EN | FLD_AGC_AUTO_EN | 0x00200000;
+
+                                       /* Write it back */
+                        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4);
+
+                                       /* Wait 15 ms */
+                                       msleep(1);
+
+                                       /* Disable the auto-VGA enable AGC */
+                                       value &= ~(FLD_VGA_AUTO_EN);
+
+                                       /* Write it back */
+                        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL1, 2, value, 4);
+
+                                       /* Enable Polaris B0 AGC output */
+                        status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, &value, 4);
+                                       value |=(FLD_OEF_AGC_RF)|(FLD_OEF_AGC_IFVGA)|(FLD_OEF_AGC_IF);
+                        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, value, 4);
+
+                                       /* Set vip 1.1 output mode */
+                        status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       OUT_CTRL1, FLD_OUT_MODE, OUT_MODE_VIP11);
+
+                                       /* Disable auto config of registers */
+                        status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       MODE_CTRL, FLD_ACFG_DIS, cx231xx_set_field(FLD_ACFG_DIS, 1));
+
+                                       /* Set CVBS input mode */
+                        status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       MODE_CTRL, FLD_INPUT_MODE,
+                                       cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0));
+
+                                       /* Set some bits in AFE_CTRL so that channel 2 or 3 is ready to receive audio */
+                                       /* Clear clamp for channels 2 and 3      (bit 16-17) */
+                                       /* Clear droop comp                      (bit 19-20) */
+                                       /* Set VGA_SEL (for audio control)       (bit 7-8) */
+                        status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, &value, 4);
+
+                                       value |= FLD_VGA_SEL_CH3 | FLD_VGA_SEL_CH2;
+
+                        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AFE_CTRL, 2, value, 4);
+                               }
+                               break;
+
+                       }
+            }
+            break;
+    }
+
+    /* Set raw VBI mode */
+    status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       OUT_CTRL1, FLD_VBIHACTRAW_EN,
+                                       cx231xx_set_field(FLD_VBIHACTRAW_EN, 1));
+
+    status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, &value, 4);
+    if(value & 0x02) {
+        value |=(1<<19);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, OUT_CTRL1, 2, value, 4);
+    }
+
+    return status;
+}
+
+/*
+ * Handle any video-mode specific overrides that are different on a per video standards
+ * basis after touching the MODE_CTRL register which resets many values for autodetect
+ */
+int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev)
+{
+    int status = 0;
+
+    cx231xx_info("do_mode_ctrl_overrides : 0x%x\n", (unsigned int)dev->norm);
+
+    /* Change the DFE_CTRL3 bp_percent to fix flagging */
+    status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DFE_CTRL3, 2, 0xCD3F0280, 4);
+
+    if( dev->norm & (V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_PAL_M) ) {
+        cx231xx_info("do_mode_ctrl_overrides NTSC\n");
+
+            /* Move the close caption lines out of active video, adjust the active video start point */
+            status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       VERT_TIM_CTRL, FLD_VBLANK_CNT,0x18);
+            status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       VERT_TIM_CTRL, FLD_VACTIVE_CNT,0x1E6000);
+            status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       VERT_TIM_CTRL, FLD_V656BLANK_CNT,0x1E000000);
+
+            status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       HORIZ_TIM_CTRL, FLD_HBLANK_CNT,
+                                       cx231xx_set_field(FLD_HBLANK_CNT, 0x79));
+    } else if ( dev->norm & ( V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_D |
+        V4L2_STD_PAL_I | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc) ) {
+            cx231xx_info("do_mode_ctrl_overrides PAL\n");
+            status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       VERT_TIM_CTRL, FLD_VBLANK_CNT,0x24);
+            /* Adjust the active video horizontal start point */
+            status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       HORIZ_TIM_CTRL, FLD_HBLANK_CNT,
+                                       cx231xx_set_field(FLD_HBLANK_CNT, 0x85));
+    } else if (dev->norm & ( V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G |
+                            V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1 | V4L2_STD_SECAM_L |
+                            V4L2_STD_SECAM_LC) ) {
+            cx231xx_info("do_mode_ctrl_overrides SECAM\n");
+            status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       VERT_TIM_CTRL, FLD_VBLANK_CNT,0x24);
+            /* Adjust the active video horizontal start point */
+            status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                       HORIZ_TIM_CTRL, FLD_HBLANK_CNT,
+                                       cx231xx_set_field(FLD_HBLANK_CNT, 0x85));
+    }
+
+    return status;
+}
+
+int cx231xx_set_audio_input(struct cx231xx *dev, u8 input)
+{
+    int status = 0;
+    enum AUDIO_INPUT ainput = AUDIO_INPUT_LINE;
+
+    switch(INPUT(input)->amux) {
+        case CX231XX_AMUX_VIDEO:
+            ainput = AUDIO_INPUT_TUNER_TV;
+            break;
+        case CX231XX_AMUX_LINE_IN:
+            status = cx231xx_flatiron_set_audio_input(dev, input);
+            ainput = AUDIO_INPUT_LINE;
+            break;
+        default:
+            break;
+    }
+
+    status = cx231xx_set_audio_decoder_input(dev, ainput);
+
+    return status;
+}
+
+int cx231xx_set_audio_decoder_input(struct cx231xx *dev, enum AUDIO_INPUT audio_input)
+{
+    u32 dwval;
+    int status;
+    u32 gen_ctrl;
+    u32 value = 0;
+
+    /* Put it in soft reset   */
+    status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, &gen_ctrl, 1);
+    gen_ctrl |= 1;
+    status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, gen_ctrl, 1);
+
+    switch(audio_input)
+    {
+    case AUDIO_INPUT_LINE:
+
+        /* setup AUD_IO control from Merlin paralle output */
+        value = cx231xx_set_field(FLD_AUD_CHAN1_SRC, AUD_CHAN_SRC_PARALLEL);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AUD_IO_CTRL, 2, value, 4);
+
+        /* setup input to Merlin, SRC2 connect to AC97
+           bypass upsample-by-2, slave mode, sony mode, left justify
+           adr 091c, dat 01000000 */
+        status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AC97_CTL, 2, &dwval, 4);
+
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AC97_CTL, 2, (dwval | FLD_AC97_UP2X_BYPASS), 4);
+
+        /* select the parallel1 and SRC3 */
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, BAND_OUT_SEL, 2,
+                     cx231xx_set_field(FLD_SRC3_IN_SEL, 0x0)|
+                     cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x0)|
+                     cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x0), 4);
+
+        /* unmute all, AC97 in, independence mode
+          adr 08d0, data 0x00063073 */
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x00063073, 4);
+
+        /* set AVC maximum threshold, adr 08d4, dat ffff0024 */
+        status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_VOL_CTL, 2, &dwval, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_VOL_CTL, 2,
+                            (dwval | FLD_PATH1_AVC_THRESHOLD), 4);
+
+        /* set SC maximum threshold, adr 08ec, dat ffffb3a3 */
+        status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_SC_CTL, 2, &dwval, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_SC_CTL, 2,
+                            (dwval | FLD_PATH1_SC_THRESHOLD), 4);
+        break;
+
+    case AUDIO_INPUT_TUNER_TV:
+    default:
+
+         /* Setup SRC sources and clocks */
+         status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, BAND_OUT_SEL, 2,
+                cx231xx_set_field(FLD_SRC6_IN_SEL, 0x00)|
+                cx231xx_set_field(FLD_SRC6_CLK_SEL, 0x01)|
+                cx231xx_set_field(FLD_SRC5_IN_SEL, 0x00)|
+                cx231xx_set_field(FLD_SRC5_CLK_SEL, 0x02)|
+                cx231xx_set_field(FLD_SRC4_IN_SEL, 0x02)|
+                cx231xx_set_field(FLD_SRC4_CLK_SEL, 0x03)|
+                cx231xx_set_field(FLD_SRC3_IN_SEL, 0x00)|
+                cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x00)|
+                cx231xx_set_field(FLD_BASEBAND_BYPASS_CTL, 0x00)|
+                cx231xx_set_field(FLD_AC97_SRC_SEL, 0x03)|
+                cx231xx_set_field(FLD_I2S_SRC_SEL, 0x00)|
+                cx231xx_set_field(FLD_PARALLEL2_SRC_SEL, 0x02)|
+                cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x01) , 4);
+
+         /* Setup the AUD_IO control */
+         status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, AUD_IO_CTRL, 2,
+                cx231xx_set_field(FLD_I2S_PORT_DIR, 0x00)|
+                cx231xx_set_field(FLD_I2S_OUT_SRC, 0x00)|
+                cx231xx_set_field(FLD_AUD_CHAN3_SRC,0x00)|
+                cx231xx_set_field(FLD_AUD_CHAN2_SRC, 0x00)|
+                cx231xx_set_field(FLD_AUD_CHAN1_SRC,0x03 ), 4);
+
+         status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x1F063870, 4);
+
+         /* setAudioStandard(_audio_standard); */
+
+         status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x00063870, 4);
+            switch(dev->model)
+            {
+                case CX231XX_BOARD_CNXT_RDE_250:
+                case CX231XX_BOARD_CNXT_RDU_250:
+                 status = cx231xx_read_modify_write_i2c_dword(dev, HAMMERHEAD_I2C_ADDRESS,
+                                               CHIP_CTRL, FLD_SIF_EN,
+                                               cx231xx_set_field(FLD_SIF_EN, 1));
+                       break;
+                default:
+                break;
+            }
+         break;
+
+    case AUDIO_INPUT_TUNER_FM:
+        /*  use SIF for FM radio
+        setupFM();
+        setAudioStandard(_audio_standard);
+        */
+        break;
+
+    case AUDIO_INPUT_MUTE:
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PATH1_CTL1, 2, 0x1F011012, 4);
+        break;
+    }
+
+    /* Take it out of soft reset */
+    status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, &gen_ctrl, 1);
+    gen_ctrl &= ~1;
+    status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, GENERAL_CTL, 2, gen_ctrl, 1);
+
+    return status;
+}
+
+
+
+/* Set resolution of the video */
+int cx231xx_resolution_set(struct cx231xx *dev)
+{
+       int width, height;
+    u32 hscale, vscale;
+    int status = 0;
+
+       width = dev->width;
+       height = dev->height;
+
+    get_scale(dev,width, height,&hscale, &vscale);
+
+    /* set horzontal scale */
+    status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, HSCALE_CTRL, 2, hscale, 4);
+
+    /* set vertical scale */
+    status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, VSCALE_CTRL, 2, vscale, 4);
+
+    return status;
+}
+
+/*************************************************************************************
+ *                        C H I P Specific  C O N T R O L   functions                *
+ *************************************************************************************/
+int cx231xx_init_ctrl_pin_status(struct cx231xx *dev)
+{
+    u32 value;
+    int status = 0;
+
+    status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, &value, 4);
+    value |=(~dev->board.ctl_pin_status_mask);
+    status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, PIN_CTRL, 2, value, 4);
+
+    return status;
+}
+
+int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev, u8 analog_or_digital)
+{
+    int status = 0;
+
+    /* first set the direction to output */
+    status = cx231xx_set_gpio_direction(dev, dev->board.agc_analog_digital_select_gpio, 1);
+
+    /* 0 - demod ; 1 - Analog mode */
+    status = cx231xx_set_gpio_value(dev, dev->board.agc_analog_digital_select_gpio,
+                                    analog_or_digital);
+
+    return status;
+}
+
+int cx231xx_enable_i2c_for_tuner(struct cx231xx *dev, u8 I2CIndex)
+{
+    u8 value[4] ={0,0,0,0};
+    int status = 0;
+
+    cx231xx_info("Changing the i2c port for tuner to %d\n",I2CIndex);
+
+    status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4);
+    if(status < 0)
+        return status;
+
+    if(I2CIndex==I2C_1) {
+        if(value[0] & I2C_DEMOD_EN) {
+            value[0] &= ~I2C_DEMOD_EN;
+            status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+        }
+    } else  {
+        if(!(value[0] & I2C_DEMOD_EN)) {
+            value[0] |= I2C_DEMOD_EN;
+            status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+        }
+    }
+
+    return status;
+
+}
+
+
+/*************************************************************************************
+ *                     D I F - B L O C K    C O N T R O L   functions                *
+ *************************************************************************************/
+int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode,
+                                          u32 function_mode, u32 standard)
+{
+    int status = 0;
+
+    if(mode == V4L2_TUNER_RADIO) {
+        /* C2HH */
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                            AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);           /* lo if big signal */
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                            AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                            AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xFF);          /* IF_MODE */
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                            AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);             /* no inv */
+    }
+    else {
+        switch(standard) {
+            case V4L2_STD_NTSC_M:                                           /* 75 IRE Setup */
+            case V4L2_STD_NTSC_M_JP:                                        /* Japan,  0 IRE Setup */
+            case V4L2_STD_PAL_M:
+            case V4L2_STD_PAL_N:
+            case V4L2_STD_PAL_Nc:
+                 status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                                AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);           /* lo if big signal */
+                 status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                                AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */
+                 status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                                AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xb);           /* IF_MODE */
+                 status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                                AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);             /* no inv */
+                 status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                                AUD_IO_CTRL, 0, 31, 0x00000003);                /* 0x124, AUD_CHAN1_SRC = 0x3 */
+            break;
+
+            case V4L2_STD_PAL_B:
+            case V4L2_STD_PAL_G:
+                 /* C2HH setup */
+                 status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                                AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);           /* lo if big signal */
+                 status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                                AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */
+                 status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                                AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE);           /* IF_MODE */
+                 status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                                AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);             /* no inv */
+                 break;
+
+            case V4L2_STD_PAL_D:
+            case V4L2_STD_PAL_I:
+            case V4L2_STD_SECAM_L:
+            case V4L2_STD_SECAM_LC:
+            case V4L2_STD_SECAM_B:
+            case V4L2_STD_SECAM_D:
+            case V4L2_STD_SECAM_G:
+            case V4L2_STD_SECAM_K:
+            case V4L2_STD_SECAM_K1:
+                 /* C2HH setup */
+                 status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                                AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);           /* lo if big signal */
+                 status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                                AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode); /* FUNC_MODE = DIF */
+                 status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                                AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF);           /* IF_MODE */
+                 status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS, 32,
+                                AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);             /* no inv */
+                            break;
+
+            case DIF_USE_BASEBAND:
+            default:
+                /* do nothing to config C2HH for baseband */
+                break;
+        }
+    }
+
+    return status;
+}
+
+int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard)
+{
+    int status = 0;
+    u32 dif_misc_ctrl_value = 0;
+    u32 func_mode = 0;
+
+    cx231xx_info("%s: setStandard to %x\n",__func__,standard);
+
+    status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                     DIF_MISC_CTRL, 2, &dif_misc_ctrl_value, 4);
+    if(standard != DIF_USE_BASEBAND )
+        dev->norm = standard;
+
+    switch (dev->model) {
+       case CX231XX_BOARD_CNXT_RDE_250:
+       case CX231XX_BOARD_CNXT_RDU_250:
+            func_mode=0x03;
+            break;
+        default:
+            func_mode=0x01;
+    }
+
+    status = cx231xx_dif_configure_C2HH_for_low_IF(dev, dev->active_mode, func_mode, standard);
+
+
+    if(standard == DIF_USE_BASEBAND ) {  /* base band */
+
+        /* There is a different SRC_PHASE_INC value for baseband vs. DIF */
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_SRC_PHASE_INC, 2, 0xDF7DF83, 4);
+        status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_MISC_CTRL, 2, &dif_misc_ctrl_value, 4);
+        dif_misc_ctrl_value |= FLD_DIF_DIF_BYPASS;
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_MISC_CTRL, 2, dif_misc_ctrl_value, 4);
+
+    } else if ( standard & (V4L2_STD_PAL_B | V4L2_STD_PAL_G) ) {
+
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL, 0, 31,  0x6503bc0c);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL1, 0, 31,  0xbd038c85);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL2, 0, 31,  0x1db4640a);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL3, 0, 31,  0x00008800);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_IF_REF, 0, 31, 0x444C1380);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_IF_INT_CURRENT, 0, 31,  0x26001700);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_RF_CURRENT, 0, 31,  0x00002660);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_VIDEO_AGC_CTRL, 0, 31,  0x72500800);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_VID_AUD_OVERRIDE, 0, 31,  0x27000100);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AV_SEP_CTRL, 0, 31,  0x3F3530EC);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_COMP_FLT_CTRL, 0, 31,  0x00A653A8);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_SRC_PHASE_INC, 0, 31,  0x1befbf06);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_SRC_GAIN_CONTROL, 0, 31,  0x000035e8);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_RPT_VARIANCE, 0, 31,  0x00000000);
+        /* Save the Spec Inversion value */
+        dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+        dif_misc_ctrl_value |=0x3a013F11;
+
+    } else if( standard & V4L2_STD_PAL_D ) {
+
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL, 0, 31,  0x6503bc0c);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL1, 0, 31,  0xbd038c85);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL2, 0, 31,  0x1db4640a);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL3, 0, 31,  0x00008800);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_IF_REF, 0, 31, 0x444C1380);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_IF_INT_CURRENT, 0, 31,  0x26001700);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_RF_CURRENT, 0, 31,  0x00002660);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_VIDEO_AGC_CTRL, 0, 31,  0x72500800);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_VID_AUD_OVERRIDE, 0, 31,  0x27000100);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AV_SEP_CTRL, 0, 31,   0x3F3934EA);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_COMP_FLT_CTRL, 0, 31,  0x00000000);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_SRC_PHASE_INC, 0, 31,  0x1befbf06);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_SRC_GAIN_CONTROL, 0, 31,  0x000035e8);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_RPT_VARIANCE, 0, 31,  0x00000000);
+        /* Save the Spec Inversion value */
+        dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+        dif_misc_ctrl_value |=0x3a023F11;
+
+    } else if( standard & V4L2_STD_PAL_I ) {
+
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL, 0, 31,  0x6503bc0c);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL1, 0, 31,  0xbd038c85);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL2, 0, 31,  0x1db4640a);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL3, 0, 31,  0x00008800);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_IF_REF, 0, 31, 0x444C1380);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_CTRL_IF, 0, 31, 0xDA302600);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_CTRL_INT, 0, 31, 0xDA261700);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_CTRL_RF, 0, 31, 0xDA262600);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_IF_INT_CURRENT, 0, 31,  0x26001700);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_RF_CURRENT, 0, 31,  0x00002660);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_VIDEO_AGC_CTRL, 0, 31,  0x72500800);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_VID_AUD_OVERRIDE, 0, 31,  0x27000100);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AV_SEP_CTRL, 0, 31,   0x5F39A934);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_COMP_FLT_CTRL, 0, 31,  0x00000000);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_SRC_PHASE_INC, 0, 31,  0x1befbf06);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_SRC_GAIN_CONTROL, 0, 31,  0x000035e8);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_RPT_VARIANCE, 0, 31,  0x00000000);
+        /* Save the Spec Inversion value */
+        dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+        dif_misc_ctrl_value |=0x3a033F11;
+
+    } else if( standard & V4L2_STD_PAL_M ) {
+
+        /* improved Low Frequency Phase Noise */
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_PLL_CTRL, 2, 0xFF01FF0C, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_PLL_CTRL1, 2, 0xbd038c85, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_PLL_CTRL2,  2, 0x1db4640a, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_PLL_CTRL3,  2, 0x00008800, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_AGC_IF_REF, 2, 0x444C1380, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_AGC_IF_INT_CURRENT,  2, 0x26001700, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_AGC_RF_CURRENT,  2, 0x00002660, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_VIDEO_AGC_CTRL,  2, 0x72500800, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_VID_AUD_OVERRIDE, 2, 0x27000100, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_AV_SEP_CTRL,  2, 0x012c405d, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                 DIF_SOFT_RST_CTRL_REVB, 2, 0x00000000, 4);
+
+        /* Save the Spec Inversion value */
+        dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+        dif_misc_ctrl_value |= 0x3A0A3F10;
+
+    } else if( standard & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc) ) {
+
+        /* improved Low Frequency Phase Noise */
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL, 2, 0xFF01FF0C, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL1, 2, 0xbd038c85, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL2, 2, 0x1db4640a, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL3, 2, 0x00008800, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_REF, 2, 0x444C1380, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_INT_CURRENT, 2, 0x26001700, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_RF_CURRENT, 2, 0x00002660, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VIDEO_AGC_CTRL, 2, 0x72500800, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VID_AUD_OVERRIDE, 2, 0x27000100, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AV_SEP_CTRL, 2, 0x012c405d, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SOFT_RST_CTRL_REVB, 2, 0x00000000, 4);
+
+        /* Save the Spec Inversion value */
+        dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+        dif_misc_ctrl_value = 0x3A093F10;
+
+    } else if( standard & ( V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G |
+                            V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1) ) {
+
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL, 0, 31,  0x6503bc0c);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL1, 0, 31,  0xbd038c85);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL2, 0, 31,  0x1db4640a);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL3, 0, 31,  0x00008800);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_IF_REF, 0, 31, 0x888C0380);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_CTRL_IF, 0, 31, 0xe0262600);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_CTRL_INT, 0, 31, 0xc2171700);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_CTRL_RF, 0, 31, 0xc2262600);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_IF_INT_CURRENT, 0, 31,  0x26001700);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_RF_CURRENT, 0, 31,  0x00002660);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_VID_AUD_OVERRIDE, 0, 31,  0x27000100);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AV_SEP_CTRL, 0, 31,   0x3F3530ec);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_COMP_FLT_CTRL, 0, 31,  0x00000000);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_SRC_PHASE_INC, 0, 31,  0x1befbf06);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_SRC_GAIN_CONTROL, 0, 31,  0x000035e8);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_RPT_VARIANCE, 0, 31,  0x00000000);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_VIDEO_AGC_CTRL, 0, 31,  0xf4000000);
+
+        /* Save the Spec Inversion value */
+        dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+        dif_misc_ctrl_value |=0x3a023F11;
+
+    } else if( standard & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC) ) {
+
+        /* Is it SECAM_L1? */
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL, 0, 31,  0x6503bc0c);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL1, 0, 31,  0xbd038c85);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL2, 0, 31,  0x1db4640a);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_PLL_CTRL3, 0, 31,  0x00008800);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_IF_REF, 0, 31, 0x888C0380);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_CTRL_IF, 0, 31, 0xe0262600);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_CTRL_INT, 0, 31, 0xc2171700);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_CTRL_RF, 0, 31, 0xc2262600);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_IF_INT_CURRENT, 0, 31,  0x26001700);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AGC_RF_CURRENT, 0, 31,  0x00002660);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_VID_AUD_OVERRIDE, 0, 31,  0x27000100);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_AV_SEP_CTRL, 0, 31,   0x3F3530ec);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_COMP_FLT_CTRL, 0, 31,  0x00000000);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_SRC_PHASE_INC, 0, 31,  0x1befbf06);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_SRC_GAIN_CONTROL, 0, 31,  0x000035e8);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_RPT_VARIANCE, 0, 31,  0x00000000);
+        status = cx231xx_reg_mask_write(dev, HAMMERHEAD_I2C_ADDRESS,  32, DIF_VIDEO_AGC_CTRL, 0, 31,  0xf2560000);
+
+        /* Save the Spec Inversion value */
+        dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+        dif_misc_ctrl_value |=0x3a023F11;
+
+    } else  { /* V4L2_STD_NTSC_M (75 IRE Setup) Or  V4L2_STD_NTSC_M_JP (Japan,  0 IRE Setup) */
+
+        /* For NTSC the centre frequency of video coming out of sidewinder is
+           around 7.1MHz or 3.6MHz depending on the spectral inversion.
+           so for a non spectrally inverted channel the pll freq word is 0x03420c49
+        */
+
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL, 2, 0x6503BC0C, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL1, 2, 0xBD038C85, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL2, 2, 0x1DB4640A, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_PLL_CTRL3, 2, 0x00008800, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_REF, 2, 0x444C0380, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_IF_INT_CURRENT, 2, 0x26001700, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_RF_CURRENT, 2, 0x00002660, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VIDEO_AGC_CTRL, 2, 0x04000800, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_VID_AUD_OVERRIDE, 2, 0x27000100, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AV_SEP_CTRL, 2, 0x01296e1f, 4);
+
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_COMP_FLT_CTRL, 2, 0x009f50c1, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_PHASE_INC, 2, 0x1befbf06, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_SRC_GAIN_CONTROL, 2, 0x000035e8, 4);
+
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_CTRL_IF, 2, 0xC2262600, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_CTRL_INT, 2, 0xC2262600, 4);
+        status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_AGC_CTRL_RF, 2, 0xC2262600, 4);
+
+        /* Save the Spec Inversion value */
+        dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+        dif_misc_ctrl_value |= 0x3a003F10;
+
+    }
+
+    /* The AGC values should be the same for all standards,
+       AUD_SRC_SEL[19] should always be disabled    */
+    dif_misc_ctrl_value &= ~FLD_DIF_AUD_SRC_SEL;
+
+    /* It is still possible to get Set Standard calls even when we are in FM mode
+       This is done to override the value for FM. */
+    if (dev->active_mode == V4L2_TUNER_RADIO)
+        dif_misc_ctrl_value = 0x7a080000;
+
+    /* Write the calculated value for misc ontrol register     */
+    status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS, DIF_MISC_CTRL, 2, dif_misc_ctrl_value, 4);
+
+    return status;
+}
+
+int cx231xx_tuner_pre_channel_change(struct cx231xx *dev)
+{
+       int status = 0;
+       u32 dwval;
+
+       /* Set the RF and IF k_agc values to 3 */
+    status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                     DIF_AGC_IF_REF, 2, &dwval, 4);
+       dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF);
+       dwval |= 0x33000000;
+
+    status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                     DIF_AGC_IF_REF, 2, dwval, 4);
+
+    return status;
+}
+
+int cx231xx_tuner_post_channel_change(struct cx231xx *dev)
+{
+    int status = 0;
+       u32 dwval;
+
+    /* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for SECAM */
+    status = cx231xx_read_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                     DIF_AGC_IF_REF, 2, &dwval, 4);
+    dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF);
+
+    if(dev->norm & ( V4L2_STD_SECAM_L | V4L2_STD_SECAM_B | V4L2_STD_SECAM_D) ) {
+        dwval |= 0x88000000;
+    } else {
+        dwval |= 0x44000000;
+    }
+
+    status = cx231xx_write_i2c_data(dev, HAMMERHEAD_I2C_ADDRESS,
+                                     DIF_AGC_IF_REF, 2, dwval, 4);
+
+    return status;
+}
+
+
+
+/*************************************************************************************
+ *            F L A T I R O N - B L O C K    C O N T R O L   functions               *
+ *************************************************************************************/
+int cx231xx_flatiron_initialize(struct cx231xx *dev)
+{
+    int status = 0;
+    u32 value;
+
+    status = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, CH_PWR_CTRL1, 1, &value, 1);
+    /* enables clock to delta-sigma and decimation filter */
+    value |= 0x80;
+    status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS,
+                                     CH_PWR_CTRL1, 1, value, 1);
+    /* power up all channel */
+    status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS,
+                                     CH_PWR_CTRL2, 1, 0x00, 1);
+
+    return status;
+}
+
+int cx231xx_flatiron_update_power_control(struct cx231xx *dev, AV_MODE avmode)
+{
+    int status = 0;
+    u32 value=0;
+
+    if(avmode!=POLARIS_AVMODE_ENXTERNAL_AV) {
+        status = cx231xx_read_i2c_data(dev, Flatrion_DEVICE_ADDRESS, CH_PWR_CTRL2, 1, &value, 1);
+        value |= 0xfe;
+        status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS,
+                                     CH_PWR_CTRL2, 1, value, 1);
+    }
+    else {
+        status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS,
+                                     CH_PWR_CTRL2, 1, 0x00, 1);
+    }
+
+    return status;
+}
+
+/* set flatiron for audio input types */
+int cx231xx_flatiron_set_audio_input(struct cx231xx *dev, u8 audio_input)
+{
+    int status = 0;
+
+    switch(audio_input) {
+        case CX231XX_AMUX_LINE_IN:
+
+            status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS,
+                                     CH_PWR_CTRL2, 1, 0x00, 1);
+            status = cx231xx_write_i2c_data(dev, Flatrion_DEVICE_ADDRESS,
+                                     CH_PWR_CTRL1, 1, 0x80, 1);
+            break;
+        case CX231XX_AMUX_VIDEO:
+        default:
+            break;
+    }
+
+    dev->ctl_ainput = audio_input;
+
+    return status;
+}
+
+/*************************************************************************************
+ *                      P O W E R      C O N T R O L   functions                     *
+ *************************************************************************************/
+int cx231xx_set_power_mode(struct cx231xx *dev, AV_MODE mode)
+{
+    u8 value[4] ={0,0,0,0};
+    u32 tmp = 0;
+    int status = 0;
+
+    if(dev->power_mode != mode)
+        dev->power_mode = mode;
+    else {
+        cx231xx_info(" setPowerMode::mode = %d, No Change req.\n",mode);
+        return 0;
+    }
+
+    cx231xx_info(" setPowerMode::mode = %d\n",mode);
+
+    status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4);
+    if(status < 0)
+        return status;
+
+    tmp = *((u32 *)value);
+
+    switch(mode)  {
+        case POLARIS_AVMODE_ENXTERNAL_AV:
+
+            tmp &= (~PWR_MODE_MASK);
+
+            tmp |= PWR_AV_EN;
+            value[0]=(u8)tmp;
+            value[1]=(u8)(tmp>>8);
+            value[2]=(u8)(tmp>>16);
+            value[3]=(u8)(tmp>>24);
+            status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+            msleep(PWR_SLEEP_INTERVAL);
+
+            tmp |= PWR_ISO_EN;
+            value[0]=(u8)tmp;
+            value[1]=(u8)(tmp>>8);
+            value[2]=(u8)(tmp>>16);
+            value[3]=(u8)(tmp>>24);
+            status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+            msleep(PWR_SLEEP_INTERVAL);
+
+            tmp |=POLARIS_AVMODE_ENXTERNAL_AV;
+            value[0]=(u8)tmp;
+            value[1]=(u8)(tmp>>8);
+            value[2]=(u8)(tmp>>16);
+            value[3]=(u8)(tmp>>24);
+            status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+
+            dev->xc_fw_load_done = 0; /* reset state of xceive tuner */
+            break;
+
+        case POLARIS_AVMODE_ANALOGT_TV:
+
+            tmp &= (~PWR_DEMOD_EN);
+            tmp |= (I2C_DEMOD_EN);
+            value[0]=(u8)tmp;
+            value[1]=(u8)(tmp>>8);
+            value[2]=(u8)(tmp>>16);
+            value[3]=(u8)(tmp>>24);
+            status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+            msleep(PWR_SLEEP_INTERVAL);
+
+            if(!(tmp & PWR_TUNER_EN)) {
+                tmp |= (PWR_TUNER_EN);
+                value[0]=(u8)tmp;
+                value[1]=(u8)(tmp>>8);
+                value[2]=(u8)(tmp>>16);
+                value[3]=(u8)(tmp>>24);
+                status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+                msleep(PWR_SLEEP_INTERVAL);
+            }
+
+            if(!(tmp & PWR_AV_EN)) {
+                tmp |= PWR_AV_EN;
+                value[0]=(u8)tmp;
+                value[1]=(u8)(tmp>>8);
+                value[2]=(u8)(tmp>>16);
+                value[3]=(u8)(tmp>>24);
+                status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+                msleep(PWR_SLEEP_INTERVAL);
+            }
+            if(!(tmp & PWR_ISO_EN )) {
+                tmp |= PWR_ISO_EN;
+                value[0]=(u8)tmp;
+                value[1]=(u8)(tmp>>8);
+                value[2]=(u8)(tmp>>16);
+                value[3]=(u8)(tmp>>24);
+                status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+                msleep(PWR_SLEEP_INTERVAL);
+            }
+
+            if(!(tmp & POLARIS_AVMODE_ANALOGT_TV )) {
+                tmp |= POLARIS_AVMODE_ANALOGT_TV;
+                value[0]=(u8)tmp;
+                value[1]=(u8)(tmp>>8);
+                value[2]=(u8)(tmp>>16);
+                value[3]=(u8)(tmp>>24);
+                status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+                msleep(PWR_SLEEP_INTERVAL);
+            }
+
+            if( (dev->model == CX231XX_BOARD_CNXT_RDE_250) ||
+                (dev->model == CX231XX_BOARD_CNXT_RDU_250)) {
+
+                    /* tuner path to channel 1 from port 3 */
+                    cx231xx_enable_i2c_for_tuner(dev, I2C_3);
+
+                    if(dev->cx231xx_reset_analog_tuner)
+                        dev->cx231xx_reset_analog_tuner(dev);
+            }
+            break;
+
+        case POLARIS_AVMODE_DIGITAL:
+
+            if(!(tmp & PWR_TUNER_EN)) {
+                tmp |= (PWR_TUNER_EN);
+                value[0]=(u8)tmp;
+                value[1]=(u8)(tmp>>8);
+                value[2]=(u8)(tmp>>16);
+                value[3]=(u8)(tmp>>24);
+                status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+                msleep(PWR_SLEEP_INTERVAL);
+            }
+            if(!(tmp & PWR_AV_EN)) {
+                tmp |= PWR_AV_EN;
+                value[0]=(u8)tmp;
+                value[1]=(u8)(tmp>>8);
+                value[2]=(u8)(tmp>>16);
+                value[3]=(u8)(tmp>>24);
+                status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+                msleep(PWR_SLEEP_INTERVAL);
+            }
+            if(!(tmp & PWR_ISO_EN)) {
+                tmp |= PWR_ISO_EN;
+                value[0]=(u8)tmp;
+                value[1]=(u8)(tmp>>8);
+                value[2]=(u8)(tmp>>16);
+                value[3]=(u8)(tmp>>24);
+                status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+                msleep(PWR_SLEEP_INTERVAL);
+            }
+
+            tmp |= POLARIS_AVMODE_DIGITAL|I2C_DEMOD_EN;
+            value[0]=(u8)tmp;
+            value[1]=(u8)(tmp>>8);
+            value[2]=(u8)(tmp>>16);
+            value[3]=(u8)(tmp>>24);
+            status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+            msleep(PWR_SLEEP_INTERVAL);
+
+            if(!(tmp & PWR_DEMOD_EN)) {
+                tmp |= PWR_DEMOD_EN;
+                value[0]=(u8)tmp;
+                value[1]=(u8)(tmp>>8);
+                value[2]=(u8)(tmp>>16);
+                value[3]=(u8)(tmp>>24);
+                status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+                msleep(PWR_SLEEP_INTERVAL);
+            }
+
+            if( (dev->model == CX231XX_BOARD_CNXT_RDE_250) ||
+                (dev->model == CX231XX_BOARD_CNXT_RDU_250)) {
+
+                    /* tuner path to channel 1 from port 3 */
+                    cx231xx_enable_i2c_for_tuner(dev, I2C_3);
+
+                    if(dev->cx231xx_reset_analog_tuner)
+                        dev->cx231xx_reset_analog_tuner(dev);
+            }
+            break;
+
+        default:
+            break;
+    }
+
+    msleep(PWR_SLEEP_INTERVAL);
+
+    /* For power saving, only enable Pwr_resetout_n when digital TV is selected. */
+    if(mode == POLARIS_AVMODE_DIGITAL) {
+        tmp |= PWR_RESETOUT_EN;
+        value[0]=(u8)tmp;
+        value[1]=(u8)(tmp>>8);
+        value[2]=(u8)(tmp>>16);
+        value[3]=(u8)(tmp>>24);
+        status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+        msleep(PWR_SLEEP_INTERVAL);
+    }
+
+    /* update power control for colibri */
+    status = cx231xx_colibri_update_power_control(dev, mode);
+
+    /* update power control for flatiron */
+    status = cx231xx_flatiron_update_power_control(dev, mode);
+
+    status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4);
+    cx231xx_info(" The data of PWR_CTL_EN register 0x74=0x%0x,0x%0x,0x%0x,0x%0x\n",value[0],value[1],value[2],value[3]);
+
+    return status;
+}
+
+int cx231xx_power_suspend(struct cx231xx *dev)
+{
+    u8 value[4] ={0,0,0,0};
+    u32 tmp = 0;
+    int status = 0;
+
+    status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, PWR_CTL_EN, value, 4);
+    if(status > 0)
+        return status;
+
+    tmp = *((u32 *)value);
+    tmp &= (~PWR_MODE_MASK);
+
+    value[0]=(u8)tmp;
+    value[1]=(u8)(tmp>>8);
+    value[2]=(u8)(tmp>>16);
+    value[3]=(u8)(tmp>>24);
+    status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, PWR_CTL_EN,value,4);
+
+    return status;
+}
+
+
+/*************************************************************************************
+ *                      S T R E A M    C O N T R O L   functions                     *
+ *************************************************************************************/
+int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask)
+{
+       u8  value[4] = {0x0, 0x0, 0x0, 0x0};
+    u32 tmp =0;
+    int status = 0;
+
+    cx231xx_info("cx231xx_start_stream():: ep_mask = %x\n", ep_mask);
+    status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, EP_MODE_SET,value,4);
+    if(status < 0)
+        return status;
+
+    tmp = *((u32 *)value);
+    tmp |= ep_mask;
+    value[0]=(u8) tmp;
+    value[1]=(u8)(tmp>>8);
+    value[2]=(u8)(tmp>>16);
+    value[3]=(u8)(tmp>>24);
+
+    status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, EP_MODE_SET,value,4);
+
+    return status;
+}
+
+int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask)
+{
+    u8  value[4] = {0x0, 0x0, 0x0, 0x0};
+    u32 tmp =0;
+    int status = 0;
+
+    cx231xx_info("cx231xx_stop_stream():: ep_mask = %x\n", ep_mask);
+    status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, EP_MODE_SET,value,4);
+    if(status < 0)
+        return status;
+
+    tmp = *((u32 *)value);
+    tmp&= (~ep_mask);
+    value[0]=(u8) tmp;
+    value[1]=(u8)(tmp>>8);
+    value[2]=(u8)(tmp>>16);
+    value[3]=(u8)(tmp>>24);
+
+    status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, EP_MODE_SET,value,4);
+
+    return status;
+}
+
+int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type)
+{
+    int status = 0;
+
+    if(dev->udev->speed == USB_SPEED_HIGH)
+    {
+        switch(media_type)
+        {
+            case 81: /* audio */
+                cx231xx_info("%s: Audio enter HANC\n",__func__);
+                status = cx231xx_mode_register(dev, TS_MODE_REG, 0x9300);
+                break;
+
+            case 2: /* vbi */
+                cx231xx_info("%s: set vanc registers\n",__func__);
+                status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300);
+                break;
+
+            case 3: /* sliced cc */
+                cx231xx_info("%s: set hanc registers\n",__func__);
+                status = cx231xx_mode_register(dev, TS_MODE_REG, 0x1300);
+                break;
+
+            case 0: /* video */
+                cx231xx_info("%s: set video registers\n",__func__);
+                status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
+                break;
+
+            case 4: /* ts1 */
+                cx231xx_info("%s: set ts1 registers\n",__func__);
+                status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101);
+                status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400);
+                break;
+            case 6: /* ts1 parallel mode */
+                cx231xx_info("%s: set ts1 parrallel mode registers\n",__func__);
+                status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
+                status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400);
+                break;
+        }
+    }
+    else
+    {
+        status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101);
+    }
+
+    return status;
+}
+
+
+
+
+int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type)
+{
+       int rc;
+    u32 ep_mask = -1;
+    PPCB_CONFIG pcb_config;
+
+    /* get EP for media type */
+    pcb_config  = &dev->current_pcb_config;
+
+    if(pcb_config->config_num==1)
+    {
+        switch (media_type)
+        {
+            case 0:                     /* Video */
+                ep_mask =ENABLE_EP4;    /* ep4  [00:1000] */
+                break;
+            case 1:                     /* Audio */
+                ep_mask =ENABLE_EP3;    /* ep3  [00:0100] */
+                break;
+            case 2:                     /* Vbi */
+                ep_mask = ENABLE_EP5;   /* ep5 [01:0000] */
+                break;
+            case 3:                     /* Sliced_cc */
+                ep_mask = ENABLE_EP6;   /* ep6 [10:0000] */
+                break;
+            case 4:                     /* ts1 */
+            case 6:                     /* ts1 parallel mode */
+                ep_mask = ENABLE_EP1;   /* ep1 [00:0001] */
+                break;
+            case 5:                     /* ts2 */
+                ep_mask = ENABLE_EP2;   /* ep2 [00:0010] */
+                break;
+            }
+
+    }
+    else if(pcb_config->config_num>1)
+    {
+        switch (media_type)
+        {
+            case 0:                     /* Video */
+                ep_mask = ENABLE_EP4;   /* ep4  [00:1000] */
+                break;
+            case 1:                     /* Audio */
+                ep_mask = ENABLE_EP3;   /* ep3  [00:0100] */
+                break;
+            case 2:                     /* Vbi */
+                ep_mask = ENABLE_EP5;   /* ep5 [01:0000] */
+                break;
+            case 3:                     /* Sliced_cc */
+                ep_mask = ENABLE_EP6;   /* ep6 [10:0000] */
+                break;
+            case 4:                     /* ts1 */
+            case 6:                     /* ts1 parallel mode */
+                ep_mask = ENABLE_EP1;   /* ep1 [00:0001] */
+                break;
+            case 5:                     /* ts2 */
+                ep_mask = ENABLE_EP2;   /* ep2 [00:0010] */
+                break;
+            }
+
+    }
+
+    if(start) {
+        rc = cx231xx_initialize_stream_xfer(dev, media_type);
+
+        if(rc < 0) {
+            return rc;
+        }
+
+        /* enable video capture */
+        if(ep_mask > 0 )
+            rc = cx231xx_start_stream(dev, ep_mask);
+    }
+    else {
+        /* disable video capture */
+        if(ep_mask > 0 )
+            rc = cx231xx_stop_stream(dev, ep_mask);
+    }
+
+    if (dev->mode == CX231XX_ANALOG_MODE){
+        /* do any in Analog mode */
+    }
+    else {
+        /* do any in digital mode */
+    }
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(cx231xx_capture_start);
+
+
+/************************************************************************************
+*                       G P I O   B I T control functions                           *
+*************************************************************************************/
+int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val)
+{
+    int status = 0;
+
+    status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 0);
+
+    return status;
+}
+
+int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val)
+{
+    int status = 0;
+
+    status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 1);
+
+    return status;
+}
+
+/*
+* cx231xx_set_gpio_direction
+*      Sets the direction of the GPIO pin to input or output
+*
+* Parameters :
+*      pin_number : The GPIO Pin number to program the direction for
+*                   from 0 to 31
+*      pin_value : The Direction of the GPIO Pin under reference.
+*                      0 = Input direction
+*                      1 = Output direction
+*/
+int cx231xx_set_gpio_direction(struct cx231xx *dev,
+        int    pin_number,
+        int    pin_value)
+{
+       int status = 0;
+    u32 value = 0;
+
+    /* Check for valid pin_number - if 32 , bail out */
+    if (pin_number >= 32) {
+        return -EINVAL;
+    }
+
+    if (pin_value == 0) {                           /* input */
+        value = dev->gpio_dir &(~(1<<pin_number)) ; /* clear */
+    } else {
+        value = dev->gpio_dir | (1<<pin_number) ;
+    }
+
+       status = cx231xx_set_gpio_bit(dev, value, (u8*) & dev->gpio_val);
+
+    /* cache the value for future */
+       dev->gpio_dir = value;
+
+    return status;
+}
+
+
+/*
+* SetGpioPinLogicValue
+*      Sets the value of the GPIO pin to Logic high or low. The Pin under
+*      reference should ALREADY BE SET IN OUTPUT MODE !!!!!!!!!
+*
+* Parameters :
+*      pin_number : The GPIO Pin number to program the direction for
+*      pin_value : The value of the GPIO Pin under reference.
+*                      0 = set it to 0
+*                      1 = set it to 1
+*/
+int cx231xx_set_gpio_value(struct cx231xx *dev,
+        int    pin_number,
+        int    pin_value)
+{
+    int status = 0;
+    u32 value = 0;
+
+    /* Check for valid pin_number - if 0xFF , bail out */
+    if (pin_number >= 32)
+        return -EINVAL;
+
+    /* first do a sanity check - if the Pin is not output, make it output */
+    if ((dev->gpio_dir & (1<<pin_number)) == 0x00)
+    {
+        /* It was in input mode */
+        value = dev->gpio_dir | (1<<pin_number) ;
+        dev->gpio_dir = value;
+        status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+               value = 0;
+    }
+
+    if (pin_value == 0) {
+        value = dev->gpio_val & (~(1<<pin_number));
+    } else {
+        value = dev->gpio_val | (1<<pin_number);
+    }
+
+    /* store the value */
+    dev->gpio_val=value;
+
+    /* toggle bit0 of GP_IO */
+    status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+    return status;
+}
+
+
+/************************************************************************************
+*                          G P I O I2C related functions                            *
+*************************************************************************************/
+int cx231xx_gpio_i2c_start(struct cx231xx *dev)
+{
+       int status = 0;
+
+       /* set SCL to output 1 ; set SDA to output 1 */
+       dev->gpio_dir |= 1<< dev->board.tuner_scl_gpio;
+       dev->gpio_dir |= 1<<dev->board.tuner_sda_gpio;
+       dev->gpio_val |= 1<<dev->board.tuner_scl_gpio;
+       dev->gpio_val |= 1<<dev->board.tuner_sda_gpio;
+
+    status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+    if(status < 0){
+               return -EINVAL;
+       }
+
+       /* set SCL to output 1; set SDA to output 0 */
+       dev->gpio_val |= 1<<dev->board.tuner_scl_gpio;
+       dev->gpio_val &= ~(1<<dev->board.tuner_sda_gpio);
+
+    status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+    if(status < 0){
+               return -EINVAL;
+       }
+
+       /* set SCL to output 0; set SDA to output 0      */
+       dev->gpio_val &= ~(1<<dev->board.tuner_scl_gpio);
+       dev->gpio_val &= ~(1<<dev->board.tuner_sda_gpio);
+
+    status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+    if(status < 0){
+               return -EINVAL;
+       }
+
+       return status;
+}
+
+
+int cx231xx_gpio_i2c_end(struct cx231xx *dev)
+{
+    int status = 0;
+
+       /* set SCL to output 0; set SDA to output 0      */
+       dev->gpio_dir |= 1<<dev->board.tuner_scl_gpio;
+       dev->gpio_dir |= 1<<dev->board.tuner_sda_gpio;
+
+       dev->gpio_val &= ~(1<<dev->board.tuner_scl_gpio);
+       dev->gpio_val &= ~(1<<dev->board.tuner_sda_gpio);
+
+    status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+    if(status < 0){
+               return -EINVAL;
+       }
+
+       /* set SCL to output 1; set SDA to output 0      */
+       dev->gpio_val |= 1<<dev->board.tuner_scl_gpio;
+       dev->gpio_val &= ~(1<<dev->board.tuner_sda_gpio);
+
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+    if(status < 0){
+               return -EINVAL;
+       }
+
+       /* set SCL to input ,release SCL cable control
+          set SDA to input ,release SDA cable control */
+       dev->gpio_dir &= ~(1<<dev->board.tuner_scl_gpio);
+       dev->gpio_dir &= ~(1<<dev->board.tuner_sda_gpio);
+
+    status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+    if(status < 0){
+               return -EINVAL;
+       }
+       return status;
+}
+
+
+int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data)
+{
+       int  status = 0;
+    u8 i;
+
+       /* set SCL to output ; set SDA to output */
+       dev->gpio_dir |= 1<<dev->board.tuner_scl_gpio;
+       dev->gpio_dir |= 1<<dev->board.tuner_sda_gpio;
+
+       for(i = 0;i<8;i++) {
+               if(((data<<i) & 0x80) == 0) {
+                       /* set SCL to output 0; set SDA to output 0     */
+                       dev->gpio_val  &= ~(1<<dev->board.tuner_scl_gpio);
+                       dev->gpio_val &= ~(1<<dev->board.tuner_sda_gpio);
+                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+                       /* set SCL to output 1; set SDA to output 0     */
+                       dev->gpio_val  |= 1<<dev->board.tuner_scl_gpio;
+                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+                       /* set SCL to output 0; set SDA to output 0     */
+                       dev->gpio_val  &= ~(1<<dev->board.tuner_scl_gpio);
+                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+               } else {
+                       /* set SCL to output 0; set SDA to output 1     */
+                       dev->gpio_val  &= ~(1<<dev->board.tuner_scl_gpio);
+                       dev->gpio_val |= 1<<dev->board.tuner_sda_gpio;
+                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+                       /* set SCL to output 1; set SDA to output 1     */
+                       dev->gpio_val  |= 1<<dev->board.tuner_scl_gpio;
+                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+                       /* set SCL to output 0; set SDA to output 1     */
+                       dev->gpio_val  &= ~(1<<dev->board.tuner_scl_gpio);
+                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+        }
+       }
+       return status;
+}
+
+int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf)
+{
+       u8 value = 0;
+       int  status = 0;
+       u32 gpio_logic_value =0;
+    u8 i;
+
+       /* read byte */
+    for(i=0;i<8;i++) {      /* send write I2c addr */
+
+               /* set SCL to output 0; set SDA to input */
+               dev->gpio_val  &= ~(1<<dev->board.tuner_scl_gpio);
+               status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+               /* set SCL to output 1; set SDA to input */
+               dev->gpio_val  |= 1<<dev->board.tuner_scl_gpio;
+               status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+               /* get SDA data bit */
+               gpio_logic_value = dev->gpio_val;
+               status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+               if((dev->gpio_val & (1<<dev->board.tuner_sda_gpio)) != 0) {
+                       value |= (1<<(8-i-1));
+               }
+
+               dev->gpio_val = gpio_logic_value;
+       }
+
+       /* set SCL to output 0,finish the read latest SCL signal.
+          !!!set SDA to input,never to modify SDA direction at the same times */
+       dev->gpio_val  &= ~(1<<dev->board.tuner_scl_gpio);
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+    /* store the value */
+    *buf = value & 0xff;
+
+       return status;
+}
+
+int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev)
+{
+       int  status = 0;
+       u32 gpio_logic_value = 0;
+    int nCnt=10;
+    int nInit=nCnt;
+
+       /* clock stretch; set SCL to input; set SDA to input; get SCL value till SCL = 1 */
+       dev->gpio_dir &= ~(1<<dev->board.tuner_sda_gpio);
+       dev->gpio_dir &= ~(1<<dev->board.tuner_scl_gpio);
+
+       gpio_logic_value = dev->gpio_val;
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+    do{
+               msleep(2);
+               status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+        nCnt--;
+       }while(((dev->gpio_val & (1<<dev->board.tuner_scl_gpio)) == 0) && (nCnt>0));
+
+    if(nCnt==0) {
+        cx231xx_info("No ACK after %d msec for clock stretch. GPIO I2C operation failed!",nInit*10);
+    }
+
+       /* readAck
+          throuth clock stretch ,slave has given a SCL signal,so the SDA data can be directly read.  */
+       status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+       if((dev->gpio_val & 1<< dev->board.tuner_sda_gpio) == 0){
+               dev->gpio_val = gpio_logic_value;
+               dev->gpio_val &= ~(1<< dev->board.tuner_sda_gpio);
+               status = 0;
+       } else {
+               dev->gpio_val = gpio_logic_value;
+               dev->gpio_val |= (1<< dev->board.tuner_sda_gpio);
+       }
+
+       /* read SDA end, set the SCL to output 0, after this operation, SDA direction can be changed. */
+       dev->gpio_val = gpio_logic_value;
+       dev->gpio_dir |= (1<<dev->board.tuner_scl_gpio);
+       dev->gpio_val  &= ~(1<<dev->board.tuner_scl_gpio);
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+       return status;
+}
+
+
+int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev)
+{
+       int  status = 0;
+
+       /* set SDA to ouput */
+       dev->gpio_dir |= 1<<dev->board.tuner_sda_gpio;
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+       /* set SCL = 0 (output); set SDA = 0 (output) */
+       dev->gpio_val &= ~(1<<dev->board.tuner_sda_gpio);
+       dev->gpio_val  &= ~(1<<dev->board.tuner_scl_gpio);
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+       /* set SCL = 1 (output); set SDA = 0 (output) */
+       dev->gpio_val  |= 1<<dev->board.tuner_scl_gpio;
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+       /* set SCL = 0 (output); set SDA = 0 (output) */
+       dev->gpio_val  &= ~(1<<dev->board.tuner_scl_gpio);
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+       /* set SDA to input,and then the slave will read data from SDA. */
+       dev->gpio_dir  &= ~(1<<dev->board.tuner_sda_gpio);
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+       return status;
+}
+
+int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev)
+{
+       int  status = 0;
+
+       /* set scl to output ; set sda to input */
+       dev->gpio_dir |= 1<<dev->board.tuner_scl_gpio;
+       dev->gpio_dir &= ~(1<<dev->board.tuner_sda_gpio);
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+       /* set scl to output 0; set sda to input */
+       dev->gpio_val  &= ~(1<<dev->board.tuner_scl_gpio);
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+       /* set scl to output 1; set sda to input */
+       dev->gpio_val  |= 1<<dev->board.tuner_scl_gpio;
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8*) &dev->gpio_val);
+
+       return status;
+}
+
+
+
+/************************************************************************************
+*                          G P I O I2C related functions                            *
+*************************************************************************************/
+/* cx231xx_gpio_i2c_read
+ * Function to read data from gpio based I2C interface
+ */
+int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len)
+{
+       int  status = 0;
+    int i = 0;
+
+    /* get the lock */
+       mutex_lock(&dev->gpio_i2c_lock);
+
+       /* start */
+       status = cx231xx_gpio_i2c_start(dev);
+
+       /* write dev_addr */
+       status = cx231xx_gpio_i2c_write_byte(dev, (dev_addr << 1) +1);
+
+       /* readAck */
+       status = cx231xx_gpio_i2c_read_ack(dev);
+
+    /* read data */
+    for(i = 0; i < len; i++ ) {
+        /* read data */
+        buf[i] = 0;
+           status = cx231xx_gpio_i2c_read_byte(dev, & buf[i]);
+
+        if( (i+1) != len) {
+               /* only do write ack if we more length */
+               status = cx231xx_gpio_i2c_write_ack(dev);
+        }
+    }
+
+       /* write NAK - inform reads are complete */
+       status = cx231xx_gpio_i2c_write_nak(dev);
+
+       /* write end */
+       status = cx231xx_gpio_i2c_end(dev);
+
+       /* release the lock */
+       mutex_unlock(&dev->gpio_i2c_lock);
+
+       return status;
+}
+
+
+/* cx231xx_gpio_i2c_write
+ * Function to write data to gpio based I2C interface
+ */
+int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf ,u8 len)
+{
+       int  status = 0;
+       int i=0;
+
+       /* get the lock */
+       mutex_lock(&dev->gpio_i2c_lock);
+
+       /* start */
+       status = cx231xx_gpio_i2c_start(dev);
+
+       /* write dev_addr */
+       status = cx231xx_gpio_i2c_write_byte(dev, dev_addr << 1);
+
+       /* read Ack */
+    status = cx231xx_gpio_i2c_read_ack(dev);
+
+    for(i = 0; i < len; i++ ) {
+               /* Write data */
+        status = cx231xx_gpio_i2c_write_byte(dev, buf[i]);
+
+           /* read Ack */
+        status = cx231xx_gpio_i2c_read_ack(dev);
+    }
+
+    /* write End */
+       status = cx231xx_gpio_i2c_end(dev);
+
+       /* release the lock */
+       mutex_unlock(&dev->gpio_i2c_lock);
+
+       return 0;
+}
+
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c
new file mode 100644 (file)
index 0000000..c567e5a
--- /dev/null
@@ -0,0 +1,935 @@
+/*
+   cx231xx-cards.c - driver for Conexant Cx23100/101/102 USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+        Based on em28xx driver
+
+   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; either version 2 of the License, or
+   (at your option) any later version.
+
+   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/delay.h>
+#include <linux/i2c.h>
+#include <linux/usb.h>
+#include <media/tuner.h>
+#include <media/tveeprom.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+
+#include <media/cx25840.h>
+#include "xc5000.h"
+
+#include "cx231xx.h"
+
+static int tuner = -1;
+module_param(tuner, int, 0444);
+MODULE_PARM_DESC(tuner, "tuner type");
+
+static unsigned int disable_ir;
+module_param(disable_ir, int, 0444);
+MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
+
+/* Bitmask marking allocated devices from 0 to CX231XX_MAXBOARDS */
+static unsigned long cx231xx_devused;
+
+/*
+ *  Reset sequences for analog/digital modes
+ */
+
+static struct cx231xx_reg_seq RDE250_XCV_TUNER[] = {
+    { 0x03, 0x01, 10 },
+    { 0x03, 0x00, 30 },
+    { 0x03, 0x01, 10 },
+    {   -1,   -1, -1 },
+};
+
+
+
+/*
+ *  Board definitions
+ */
+struct cx231xx_board cx231xx_boards[] = {
+
+       [CX231XX_BOARD_UNKNOWN] = {
+               .name          = "Unknown CX231xx video grabber",
+               .tuner_type    = TUNER_ABSENT,
+        .input        = { {
+                       .type     = CX231XX_VMUX_TELEVISION,
+                       .vmux     = CX231XX_VIN_3_1,
+                       .amux     = CX231XX_AMUX_VIDEO,
+                       .gpio     = 0,
+               }, {
+                       .type     = CX231XX_VMUX_COMPOSITE1,
+                       .vmux     = CX231XX_VIN_2_1,
+                       .amux     = CX231XX_AMUX_LINE_IN,
+                       .gpio     = 0,
+               }, {
+                       .type     = CX231XX_VMUX_SVIDEO,
+                       .vmux     = CX231XX_VIN_1_1 | (CX231XX_VIN_1_2 << 8 ) |
+                                           CX25840_SVIDEO_ON,
+                       .amux     = CX231XX_AMUX_LINE_IN,
+                       .gpio     = 0,
+               } },
+       },
+
+       [CX231XX_BOARD_CNXT_RDE_250] = {
+               .name         = "Conexant Hybrid TV - RDE250",
+               .valid        = CX231XX_BOARD_VALIDATED,
+               .tuner_type   = TUNER_XC5000,
+        .tuner_addr   = 0x61,
+               .tuner_gpio   = RDE250_XCV_TUNER,
+        .tuner_sif_gpio = 0x05,
+               .tuner_scl_gpio = 0x1a,
+        .tuner_sda_gpio = 0x1b,
+        .decoder      = CX231XX_AVDECODER,
+        .demod_xfer_mode                = 0,
+        .ctl_pin_status_mask            = 0xFFFFFFC4,
+        .agc_analog_digital_select_gpio = 0x0c,
+        .gpio_pin_status_mask           = 0x4001000,
+        .tuner_i2c_master               = 1,
+        .demod_i2c_master               = 2,
+               .has_dvb      = 1,
+        .demod_addr   = 0x02,
+        .norm         = V4L2_STD_PAL,
+
+               .input        = { {
+                       .type     = CX231XX_VMUX_TELEVISION,
+                       .vmux     = CX231XX_VIN_3_1,
+                       .amux     = CX231XX_AMUX_VIDEO,
+                       .gpio     = 0,
+               }, {
+                       .type     = CX231XX_VMUX_COMPOSITE1,
+                       .vmux     = CX231XX_VIN_2_1,
+                       .amux     = CX231XX_AMUX_LINE_IN,
+                       .gpio     = 0,
+               }, {
+                       .type     = CX231XX_VMUX_SVIDEO,
+                       .vmux     = CX231XX_VIN_1_1 | (CX231XX_VIN_1_2 << 8 ) |
+                                           CX25840_SVIDEO_ON,
+                       .amux     = CX231XX_AMUX_LINE_IN,
+                       .gpio     = 0,
+               } },
+       },
+
+    [CX231XX_BOARD_CNXT_RDU_250] = {
+               .name         = "Conexant Hybrid TV - RDU250",
+               .valid        = CX231XX_BOARD_VALIDATED,
+               .tuner_type   = TUNER_XC5000,
+        .tuner_addr   = 0x61,
+               .tuner_gpio   = RDE250_XCV_TUNER,
+        .tuner_sif_gpio = 0x05,
+               .tuner_scl_gpio = 0x1a,
+        .tuner_sda_gpio = 0x1b,
+        .decoder      = CX231XX_AVDECODER,
+        .demod_xfer_mode                = 0,
+        .ctl_pin_status_mask            = 0xFFFFFFC4,
+        .agc_analog_digital_select_gpio = 0x0c,
+        .gpio_pin_status_mask           = 0x4001000,
+        .tuner_i2c_master               = 1,
+        .demod_i2c_master               = 2,
+               .has_dvb      = 1,
+        .demod_addr   = 0x32,
+        .norm         = V4L2_STD_NTSC,
+
+               .input        = { {
+                       .type     = CX231XX_VMUX_TELEVISION,
+                       .vmux     = CX231XX_VIN_3_1,
+                       .amux     = CX231XX_AMUX_VIDEO,
+                       .gpio     = 0,
+               }, {
+                       .type     = CX231XX_VMUX_COMPOSITE1,
+                       .vmux     = CX231XX_VIN_2_1,
+                       .amux     = CX231XX_AMUX_LINE_IN,
+                       .gpio     = 0,
+               }, {
+                       .type     = CX231XX_VMUX_SVIDEO,
+                       .vmux     = CX231XX_VIN_1_1 | (CX231XX_VIN_1_2 << 8 ) |
+                                           CX25840_SVIDEO_ON,
+                       .amux     = CX231XX_AMUX_LINE_IN,
+                       .gpio     = 0,
+               } },
+       },
+};
+const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
+
+/* table of devices that work with this driver */
+struct usb_device_id cx231xx_id_table [] = {
+       { USB_DEVICE(0x0572, 0x58A0),
+                       .driver_info = CX231XX_BOARD_UNKNOWN },
+       { USB_DEVICE(0x0572, 0x58A2),
+                       .driver_info = CX231XX_BOARD_CNXT_RDE_250 },
+    { USB_DEVICE(0x0572, 0x5A3C),
+                       .driver_info = CX231XX_BOARD_CNXT_RDU_250 },
+       { },
+};
+MODULE_DEVICE_TABLE(usb, cx231xx_id_table);
+
+/* cx231xx_tuner_callback
+ * will be used to reset XC5000 tuner using GPIO pin
+ */
+
+int cx231xx_tuner_callback(void *ptr, int component, int command, int arg)
+{
+       int rc = 0;
+       struct cx231xx *dev = ptr;
+
+    if (dev->tuner_type == TUNER_XC5000) {
+        if (command == XC5000_TUNER_RESET) {
+            cx231xx_info("Tuner Call back : RESET : command %d : tuner type %d \n",
+                command, dev->tuner_type);
+
+            cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1);
+            msleep(10);
+            cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,0);
+            msleep(330);
+            cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1);
+            msleep(10);
+        }
+    }
+       return rc;
+}
+EXPORT_SYMBOL_GPL(cx231xx_tuner_callback);
+
+static void inline cx231xx_set_model(struct cx231xx *dev)
+{
+       memcpy(&dev->board, &cx231xx_boards[dev->model], sizeof(dev->board));
+}
+
+/* Since cx231xx_pre_card_setup() requires a proper dev->model,
+ * this won't work for boards with generic PCI IDs
+ */
+void cx231xx_pre_card_setup(struct cx231xx *dev)
+{
+
+       cx231xx_set_model(dev);
+
+       cx231xx_info("Identified as %s (card=%d)\n",
+                   dev->board.name, dev->model);
+
+       /* Do card specific if any */
+       switch (dev->model) {
+        case CX231XX_BOARD_CNXT_RDE_250:
+            /* do card specific GPIO settings if required */
+            cx231xx_info("Precard: Board is Conexnat RDE 250\n");
+            /* set the direction for GPIO pins */
+            cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit,1);
+            cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1);
+            cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio,1);
+            break;
+        case CX231XX_BOARD_CNXT_RDU_250:
+            /* do card specific GPIO settings if required */
+            cx231xx_info("Precard: Board is Conexnat RDU 250\n");
+            /* set the direction for GPIO pins */
+            cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit,1);
+            cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,1);
+            cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio,1);
+            break;
+       }
+
+       /* request some modules if any required */
+
+    /* reset the Tuner */
+       cx231xx_gpio_set(dev, dev->board.tuner_gpio);
+
+    /* set the mode to Analog mode initially */
+       cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
+
+       /* Unlock device */
+       /* cx231xx_set_mode(dev, CX231XX_SUSPEND); */
+
+}
+
+#if 0
+
+static void cx231xx_config_tuner(struct cx231xx *dev)
+{
+       struct tuner_setup           tun_setup;
+       struct v4l2_frequency        f;
+
+       if (dev->tuner_type == TUNER_ABSENT)
+               return;
+
+       tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+       tun_setup.type = dev->tuner_type;
+       tun_setup.addr = dev->tuner_addr;
+       tun_setup.tuner_callback = cx231xx_tuner_callback;
+
+       cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_TYPE_ADDR, &tun_setup);
+#if 0
+    if (tun_setup.type == TUNER_XC5000) {
+               static struct xc2028_ctrl ctrl = {
+                       .fname = XC5000_DEFAULT_FIRMWARE,
+                       .max_len = 64,
+            .demod = 0;
+               };
+               struct v4l2_priv_tun_config cfg = {
+                       .tuner = dev->tuner_type,
+                       .priv = &ctrl,
+               };
+               cx231xx_i2c_call_clients(&dev->i2c_bus[1], TUNER_SET_CONFIG, &cfg);
+       }
+#endif
+
+       /* configure tuner */
+       f.tuner = 0;
+       f.type = V4L2_TUNER_ANALOG_TV;
+       f.frequency = 9076;     /* just a magic number */
+       dev->ctl_freq = f.frequency;
+       cx231xx_i2c_call_clients(&dev->i2c_bus[1], VIDIOC_S_FREQUENCY, &f);
+}
+
+#endif
+
+/* ----------------------------------------------------------------------- */
+void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir)
+{
+       if (disable_ir) {
+               ir->get_key = NULL;
+               return ;
+       }
+
+       /* detect & configure */
+       switch (dev->model) {
+
+        case CX231XX_BOARD_CNXT_RDE_250:
+            break;
+        case CX231XX_BOARD_CNXT_RDU_250:
+            break;
+        default:
+                   break;
+       }
+}
+
+void cx231xx_card_setup(struct cx231xx *dev)
+{
+       cx231xx_set_model(dev);
+
+       dev->tuner_type = cx231xx_boards[dev->model].tuner_type;
+       if (cx231xx_boards[dev->model].tuner_addr)
+               dev->tuner_addr = cx231xx_boards[dev->model].tuner_addr;
+
+    cx231xx_info(": tuner type %d, tuner address %d \n",
+        dev->tuner_type, dev->tuner_addr);
+
+       /* Do card specific if any */
+       switch (dev->model) {
+        case CX231XX_BOARD_CNXT_RDE_250:
+            /* do card specific GPIO settings if required */
+            cx231xx_info("Board is Conexnat RDE 250\n");
+            break;
+        case CX231XX_BOARD_CNXT_RDU_250:
+            /* do card specific GPIO settings if required */
+            cx231xx_info("Board is Conexnat RDU 250\n");
+            break;
+       }
+
+       if (dev->board.valid == CX231XX_BOARD_NOT_VALIDATED) {
+               cx231xx_errdev("\n\n");
+               cx231xx_errdev("The support for this board weren't "
+                             "valid yet.\n");
+               cx231xx_errdev("Please send a report of having this working\n");
+               cx231xx_errdev("not to V4L mailing list (and/or to other "
+                               "addresses)\n\n");
+       }
+
+
+       /* request some modules */
+    if (dev->board.decoder == CX231XX_AVDECODER) {
+        cx231xx_info(": Requesting cx25840 module\n");
+               request_module("cx25840");
+    }
+#if 0
+    if (dev->board.tuner_type != TUNER_ABSENT) {
+        cx231xx_info(": Requesting Tuner module\n");
+               request_module("tuner");
+    }
+
+       cx231xx_config_tuner(dev);
+
+    /* TBD  IR will be added later */
+       cx231xx_ir_init(dev);
+#endif
+}
+
+
+
+/*
+ * cx231xx_config()
+ * inits registers with sane defaults
+ */
+int cx231xx_config(struct cx231xx *dev)
+{
+    /* TBD need to add cx231xx specific code */
+       dev->mute = 1;          /* maybe not the right place... */
+       dev->volume = 0x1f;
+
+       return 0;
+}
+
+/*
+ * cx231xx_config_i2c()
+ * configure i2c attached devices
+ */
+void cx231xx_config_i2c(struct cx231xx *dev)
+{
+       struct v4l2_routing route;
+
+       route.input = INPUT(dev->video_input)->vmux;
+       route.output = 0;
+
+       cx231xx_i2c_call_clients(&dev->i2c_bus[0], VIDIOC_STREAMON, NULL);
+}
+
+/*
+ * cx231xx_realease_resources()
+ * unregisters the v4l2,i2c and usb devices
+ * called when the device gets disconected or at module unload
+*/
+void cx231xx_release_resources(struct cx231xx *dev)
+{
+
+#if 0 /* TBD IR related  */
+       if (dev->ir)
+               cx231xx_ir_fini(dev);
+#endif
+
+       cx231xx_release_analog_resources(dev);
+
+    cx231xx_remove_from_devlist(dev);
+
+    cx231xx_dev_uninit(dev);
+
+       usb_put_dev(dev->udev);
+
+       /* Mark device as unused */
+       cx231xx_devused &= ~(1<<dev->devno);
+}
+
+
+/*
+ * cx231xx_init_dev()
+ * allocates and inits the device structs, registers i2c bus and v4l device
+ */
+static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev,
+                          int minor)
+{
+       struct cx231xx *dev = *devhandle;
+       int retval = -ENOMEM;
+       int errCode;
+       unsigned int maxh, maxw;
+
+       dev->udev = udev;
+       mutex_init(&dev->lock);
+       mutex_init(&dev->ctrl_urb_lock);
+    mutex_init(&dev->gpio_i2c_lock);
+
+    spin_lock_init(&dev->video_mode.slock);
+    spin_lock_init(&dev->vbi_mode.slock);
+    spin_lock_init(&dev->sliced_cc_mode.slock);
+
+       init_waitqueue_head(&dev->open);
+       init_waitqueue_head(&dev->wait_frame);
+       init_waitqueue_head(&dev->wait_stream);
+
+    dev->cx231xx_read_ctrl_reg = cx231xx_read_ctrl_reg;
+    dev->cx231xx_write_ctrl_reg = cx231xx_write_ctrl_reg;
+    dev->cx231xx_send_usb_command = cx231xx_send_usb_command;
+    dev->cx231xx_gpio_i2c_read = cx231xx_gpio_i2c_read;
+    dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write;
+
+    /* Query cx231xx to find what pcb config it is related to */
+    initialize_cx231xx(dev);
+
+    /* Cx231xx pre card setup */
+       cx231xx_pre_card_setup(dev);
+
+       errCode = cx231xx_config(dev);
+       if (errCode) {
+               cx231xx_errdev("error configuring device\n");
+               return -ENOMEM;
+       }
+
+    /* set default norm */
+       dev->norm = dev->board.norm;
+
+       /* register i2c bus */
+       errCode = cx231xx_dev_init(dev);
+       if (errCode < 0) {
+               cx231xx_errdev("%s: cx231xx_i2c_register - errCode [%d]!\n",
+                       __func__, errCode);
+               return errCode;
+       }
+
+       /* Do board specific init */
+       cx231xx_card_setup(dev);
+
+       /* configure the device */
+       cx231xx_config_i2c(dev);
+
+       maxw = norm_maxw(dev);
+       maxh = norm_maxh(dev);
+
+       /* set default image size */
+       dev->width = maxw;
+       dev->height = maxh;
+       dev->interlaced = 0;
+       dev->hscale = 0;
+       dev->vscale = 0;
+       dev->video_input = 0;
+
+       errCode = cx231xx_config(dev);
+       if (errCode < 0) {
+               cx231xx_errdev("%s: cx231xx_config - errCode [%d]!\n",
+                       __func__, errCode);
+               return errCode;
+       }
+
+       /* init video dma queues */
+       INIT_LIST_HEAD(&dev->video_mode.vidq.active);
+       INIT_LIST_HEAD(&dev->video_mode.vidq.queued);
+
+    /* init vbi dma queues */
+       INIT_LIST_HEAD(&dev->vbi_mode.vidq.active);
+       INIT_LIST_HEAD(&dev->vbi_mode.vidq.queued);
+
+       /* Reset other chips required if they are tied up with GPIO pins */
+
+    cx231xx_add_into_devlist(dev);
+
+       retval = cx231xx_register_analog_devices(dev);
+       if (retval < 0) {
+               cx231xx_release_resources(dev);
+               goto fail_reg_devices;
+       }
+
+       cx231xx_init_extension(dev);
+
+       return 0;
+
+fail_reg_devices:
+       mutex_unlock(&dev->lock);
+       return retval;
+}
+
+#if defined(CONFIG_MODULES) && defined(MODULE)
+static void request_module_async(struct work_struct *work)
+{
+       struct cx231xx *dev = container_of(work,
+                            struct cx231xx, request_module_wk);
+
+
+       if (dev->has_alsa_audio)
+               request_module("cx231xx-alsa");
+
+       if (dev->board.has_dvb)
+               request_module("cx231xx-dvb");
+
+}
+
+static void request_modules(struct cx231xx *dev)
+{
+       INIT_WORK(&dev->request_module_wk, request_module_async);
+       schedule_work(&dev->request_module_wk);
+}
+#else
+#define request_modules(dev)
+#endif /* CONFIG_MODULES */
+
+
+
+/*
+ * cx231xx_usb_probe()
+ * checks for supported devices
+ */
+static int cx231xx_usb_probe(struct usb_interface *interface,
+                           const struct usb_device_id *id)
+{
+       struct usb_device *udev;
+       struct usb_interface *uif;
+       struct cx231xx *dev = NULL;
+       int retval = -ENODEV;
+    int nr, ifnum;
+       int i, isoc_pipe = 0;
+       char *speed;
+       char descr[255] = "";
+    struct usb_interface *lif = NULL;
+    int skip_interface = 0;
+    struct usb_interface_assoc_descriptor *assoc_desc;
+
+       udev = usb_get_dev(interface_to_usbdev(interface));
+       ifnum = interface->altsetting[0].desc.bInterfaceNumber;
+
+    cx231xx_info(": Interface Number %d\n", ifnum);
+
+    /* Interface number 0 - IR interface */
+    if(ifnum == 0 ){
+        /* Check to see next free device and mark as used */
+           nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
+           cx231xx_devused |= 1<<nr;
+
+        if (nr >= CX231XX_MAXBOARDS) {
+                   cx231xx_info(": Supports only %i cx231xx boards.\n",
+                                   CX231XX_MAXBOARDS);
+                   cx231xx_devused &= ~(1<<nr);
+                   return -ENOMEM;
+           }
+
+        /* allocate memory for our device state and initialize it */
+           dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+           if (dev == NULL) {
+                   cx231xx_err(DRIVER_NAME ": out of memory!\n");
+                   cx231xx_devused &= ~(1<<nr);
+                   return -ENOMEM;
+           }
+
+           snprintf(dev->name, 29, "cx231xx #%d", nr);
+           dev->devno = nr;
+           dev->model = id->driver_info;
+           dev->video_mode.alt   = -1;
+        dev->interface_count++;
+
+        /* reset gpio dir and value */
+        dev->gpio_dir = 0;
+        dev->gpio_val = 0;
+        dev->xc_fw_load_done = 0;
+               dev->has_alsa_audio = 1;
+        dev->power_mode = -1;
+
+        dev->vbi_or_sliced_cc_mode = 0; /* 0 - vbi ; 1 -sliced cc mode */
+
+        /* get maximum no.of IAD interfaces */
+        assoc_desc = udev->actconfig->intf_assoc[0];
+        dev->max_iad_interface_count  = assoc_desc->bInterfaceCount;
+        cx231xx_info(": Found IAD interface count %d\n", dev->max_iad_interface_count);
+
+        /* init CIR module TBD */
+
+        /* store the current interface */
+        lif = interface;
+
+    }
+    else if(ifnum == 1 ){
+
+        /* Get dev structure first */
+        dev = usb_get_intfdata(udev->actconfig->interface[0]);
+        if(dev == NULL){
+                   cx231xx_err(DRIVER_NAME ": out of first interface!\n");
+                   return -ENODEV;
+           }
+
+        /* store the interface 0 back */
+        lif = udev->actconfig->interface[0];
+
+        /* increment interface count */
+        dev->interface_count++;
+
+        /* get device number */
+        nr = dev->devno;
+
+        assoc_desc = udev->actconfig->intf_assoc[0];
+        if(assoc_desc->bFirstInterface == ifnum){
+            cx231xx_info(": Found IAD interface match: AV Descriptor Start!! \n");
+        } else {
+            cx231xx_err(DRIVER_NAME " Not found matching interface\n");
+            return -ENODEV;
+        }
+
+    }
+    else if(ifnum >= 2) {
+        /* Get dev structure first */
+        dev = usb_get_intfdata(udev->actconfig->interface[0]);
+        if(dev == NULL){
+                   cx231xx_err(DRIVER_NAME ": out of first interface!\n");
+                   return -ENODEV;
+           }
+
+        /* store the interface 0 back */
+        lif = udev->actconfig->interface[0];
+
+        /* increment interface count */
+        dev->interface_count++;
+
+        /* get device number */
+        nr = dev->devno;
+
+        /* set skip interface */
+        if((dev->interface_count -1) != dev->max_iad_interface_count )
+            skip_interface = 1; /* set skipping */
+        else{
+            cx231xx_info(": Found IAD interface number match with AV Device number!! \n");
+        }
+    }
+
+       switch (udev->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";
+       }
+
+       if (udev->manufacturer)
+               strlcpy(descr, udev->manufacturer, sizeof(descr));
+
+       if (udev->product) {
+               if (*descr)
+                       strlcat(descr, " ", sizeof(descr));
+               strlcat(descr, udev->product, sizeof(descr));
+       }
+       if (*descr)
+               strlcat(descr, " ", sizeof(descr));
+
+       cx231xx_info("New device %s@ %s Mbps "
+               "(%04x:%04x, interface %d, class %d)\n",
+               descr,
+               speed,
+               le16_to_cpu(udev->descriptor.idVendor),
+               le16_to_cpu(udev->descriptor.idProduct),
+               ifnum,
+               interface->altsetting->desc.bInterfaceNumber);
+
+    /* AV device initialization */
+    if((dev->interface_count -1) == dev->max_iad_interface_count ) {
+        cx231xx_info(" Calling init_dev\n");
+           /* allocate device struct */
+           retval = cx231xx_init_dev(&dev, udev, nr);
+           if (retval) {
+                   cx231xx_devused &= ~(1<<dev->devno);
+                   kfree(dev);
+
+                   return retval;
+           }
+
+        /* compute alternate max packet sizes for video */
+        uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.video_index+1];
+
+        dev->video_mode.end_point_addr = le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress);
+
+        dev->video_mode.num_alt = uif->num_altsetting;
+        cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->video_mode.end_point_addr,
+                                    dev->video_mode.num_alt);
+        dev->video_mode.alt_max_pkt_size = kmalloc(32 * dev->video_mode.num_alt, GFP_KERNEL);
+
+        if (dev->video_mode.alt_max_pkt_size == NULL) {
+               cx231xx_errdev("out of memory!\n");
+               cx231xx_devused &= ~(1<<nr);
+               kfree(dev);
+               return -ENOMEM;
+        }
+
+        for (i = 0; i < dev->video_mode.num_alt ; i++) {
+               u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.
+                                                       wMaxPacketSize);
+               dev->video_mode.alt_max_pkt_size[i] =
+                   (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+            cx231xx_info("Alternate setting %i, max size= %i\n", i,
+                                               dev->video_mode.alt_max_pkt_size[i]);
+        }
+
+
+        /* compute alternate max packet sizes for vbi */
+        uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index+1];
+
+        dev->vbi_mode.end_point_addr =
+            le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress);
+
+        dev->vbi_mode.num_alt = uif->num_altsetting;
+        cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->vbi_mode.end_point_addr,
+                                    dev->vbi_mode.num_alt);
+        dev->vbi_mode.alt_max_pkt_size = kmalloc(32 * dev->vbi_mode.num_alt, GFP_KERNEL);
+
+        if (dev->vbi_mode.alt_max_pkt_size == NULL) {
+               cx231xx_errdev("out of memory!\n");
+               cx231xx_devused &= ~(1<<nr);
+               kfree(dev);
+               return -ENOMEM;
+        }
+
+        for (i = 0; i < dev->vbi_mode.num_alt ; i++) {
+               u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.
+                                                       wMaxPacketSize);
+               dev->vbi_mode.alt_max_pkt_size[i] =
+                   (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+            cx231xx_info("Alternate setting %i, max size= %i\n", i,
+                                               dev->vbi_mode.alt_max_pkt_size[i]);
+        }
+
+        /* compute alternate max packet sizes for sliced CC */
+        uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index+1];
+
+        dev->sliced_cc_mode.end_point_addr =
+            le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress);
+
+        dev->sliced_cc_mode.num_alt = uif->num_altsetting;
+        cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->sliced_cc_mode.end_point_addr,
+                                    dev->sliced_cc_mode.num_alt);
+        dev->sliced_cc_mode.alt_max_pkt_size = kmalloc(32 * dev->sliced_cc_mode.num_alt, GFP_KERNEL);
+
+        if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) {
+               cx231xx_errdev("out of memory!\n");
+               cx231xx_devused &= ~(1<<nr);
+               kfree(dev);
+               return -ENOMEM;
+        }
+
+        for (i = 0; i < dev->sliced_cc_mode.num_alt ; i++) {
+               u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.
+                                                       wMaxPacketSize);
+               dev->sliced_cc_mode.alt_max_pkt_size[i] =
+                   (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+            cx231xx_info("Alternate setting %i, max size= %i\n", i,
+                                               dev->sliced_cc_mode.alt_max_pkt_size[i]);
+        }
+
+        if(dev->current_pcb_config.ts1_source != 0xff ) {
+
+            /* compute alternate max packet sizes for TS1 */
+            uif = udev->actconfig->interface[dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index+1];
+
+            dev->ts1_mode.end_point_addr =
+                le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress);
+
+            dev->ts1_mode.num_alt = uif->num_altsetting;
+            cx231xx_info(": EndPoint Addr 0x%x, Alternate settings: %i\n", dev->ts1_mode.end_point_addr,
+                                        dev->ts1_mode.num_alt);
+            dev->ts1_mode.alt_max_pkt_size = kmalloc(32 * dev->ts1_mode.num_alt, GFP_KERNEL);
+
+            if (dev->ts1_mode.alt_max_pkt_size == NULL) {
+                   cx231xx_errdev("out of memory!\n");
+                   cx231xx_devused &= ~(1<<nr);
+                   kfree(dev);
+                   return -ENOMEM;
+            }
+
+            for (i = 0; i < dev->ts1_mode.num_alt ; i++) {
+                   u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.
+                                                           wMaxPacketSize);
+                   dev->ts1_mode.alt_max_pkt_size[i] =
+                       (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+                cx231xx_info("Alternate setting %i, max size= %i\n", i,
+                                                   dev->ts1_mode.alt_max_pkt_size[i]);
+            }
+        }
+
+    }
+
+       /* save our data pointer in this interface device */
+       usb_set_intfdata(lif, dev);
+
+    /* load other modules required */
+    if((dev->interface_count -1) == dev->max_iad_interface_count )
+    {
+        cx231xx_info("Calling request modules\n");
+        request_modules(dev);
+    }
+
+    if(skip_interface ) {
+        cx231xx_info("Skipping the interface\n");
+        return -ENODEV;
+    }
+
+       return 0;
+}
+
+/*
+ * cx231xx_usb_disconnect()
+ * called when the device gets diconencted
+ * video device will be unregistered on v4l2_close in case it is still open
+ */
+static void cx231xx_usb_disconnect(struct usb_interface *interface)
+{
+       struct cx231xx *dev;
+
+    dev = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
+
+       if (!dev)
+               return;
+
+       /* wait until all current v4l2 io is finished then deallocate
+          resources */
+       mutex_lock(&dev->lock);
+
+       wake_up_interruptible_all(&dev->open);
+
+       if (dev->users) {
+               cx231xx_warn
+                   ("device /dev/video%d is open! Deregistration and memory "
+                    "deallocation are deferred on close.\n",
+                               dev->vdev->num);
+
+               dev->state |= DEV_MISCONFIGURED;
+               cx231xx_uninit_isoc(dev);
+               dev->state |= DEV_DISCONNECTED;
+               wake_up_interruptible(&dev->wait_frame);
+               wake_up_interruptible(&dev->wait_stream);
+       } else {
+               dev->state |= DEV_DISCONNECTED;
+               cx231xx_release_resources(dev);
+       }
+
+    cx231xx_close_extension(dev);
+
+       mutex_unlock(&dev->lock);
+
+       if (!dev->users) {
+               kfree(dev->video_mode.alt_max_pkt_size);
+        kfree(dev->vbi_mode.alt_max_pkt_size);
+        kfree(dev->sliced_cc_mode.alt_max_pkt_size);
+        kfree(dev->ts1_mode.alt_max_pkt_size);
+               kfree(dev);
+       }
+}
+
+static struct usb_driver cx231xx_usb_driver = {
+       .name = "cx231xx",
+       .probe = cx231xx_usb_probe,
+       .disconnect = cx231xx_usb_disconnect,
+       .id_table = cx231xx_id_table,
+};
+
+static int __init cx231xx_module_init(void)
+{
+       int result;
+
+       printk(KERN_INFO DRIVER_NAME " v4l2 driver version %d.%d.%d loaded\n",
+              (CX231XX_VERSION_CODE >> 16) & 0xff,
+              (CX231XX_VERSION_CODE >> 8) & 0xff, CX231XX_VERSION_CODE & 0xff);
+
+       /* register this driver with the USB subsystem */
+       result = usb_register(&cx231xx_usb_driver);
+       if (result)
+               cx231xx_err(DRIVER_NAME
+                          " usb_register failed. Error number %d.\n", result);
+
+       return result;
+}
+
+static void __exit cx231xx_module_exit(void)
+{
+       /* deregister this driver with the USB subsystem */
+       usb_deregister(&cx231xx_usb_driver);
+}
+
+module_init(cx231xx_module_init);
+module_exit(cx231xx_module_exit);
diff --git a/drivers/media/video/cx231xx/cx231xx-conf-reg.h b/drivers/media/video/cx231xx/cx231xx-conf-reg.h
new file mode 100644 (file)
index 0000000..5ccf6bd
--- /dev/null
@@ -0,0 +1,491 @@
+/*
+   cx231xx_conf-reg.h - driver for Conexant Cx23100/101/102 USB
+                        video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot 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; either version 2 of the License, or
+   (at your option) any later version.
+
+   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.
+ */
+
+
+#ifndef _POLARIS_REG_H_
+#define _POLARIS_REG_H_
+
+#define BOARD_CFG_STAT          0x0
+#define TS_MODE_REG             0x4
+#define TS1_CFG_REG             0x8
+#define TS1_LENGTH_REG          0xc
+#define TS2_CFG_REG             0x10
+#define TS2_LENGTH_REG          0x14
+#define EP_MODE_SET             0x18
+#define CIR_PWR_PTN1            0x1c
+#define CIR_PWR_PTN2            0x20
+#define CIR_PWR_PTN3            0x24
+#define CIR_PWR_MASK0           0x28
+#define CIR_PWR_MASK1           0x2c
+#define CIR_PWR_MASK2           0x30
+#define CIR_GAIN                0x34
+#define CIR_CAR_REG             0x38
+#define CIR_OT_CFG1             0x40
+#define CIR_OT_CFG2             0x44
+#define PWR_CTL_EN              0x74
+
+/* Polaris Endpoints capture mask for register EP_MODE_SET */
+#define ENABLE_EP1              0x01    /* Bit[0]=1 */
+#define ENABLE_EP2              0x02    /* Bit[1]=1 */
+#define ENABLE_EP3              0x04    /* Bit[2]=1 */
+#define ENABLE_EP4              0x08    /* Bit[3]=1 */
+#define ENABLE_EP5              0x10    /* Bit[4]=1 */
+#define ENABLE_EP6              0x20    /* Bit[5]=1 */
+
+/* Bit definition for register PWR_CTL_EN */
+#define PWR_MODE_MASK           0x17f
+#define PWR_AV_EN               0x08    /* bit3 */
+#define PWR_ISO_EN              0x40    /* bit6 */
+#define PWR_AV_MODE             0x30    /* bit4,5  */
+#define PWR_TUNER_EN            0x04    /* bit2 */
+#define PWR_DEMOD_EN            0x02    /* bit1 */
+#define I2C_DEMOD_EN            0x01    /* bit0 */
+#define PWR_RESETOUT_EN         0x100   /* bit8 */
+
+typedef enum{
+     POLARIS_AVMODE_DEFAULT         = 0,
+     POLARIS_AVMODE_DIGITAL         = 0x10,
+     POLARIS_AVMODE_ANALOGT_TV      = 0x20,
+     POLARIS_AVMODE_ENXTERNAL_AV    = 0x30,
+
+}AV_MODE;
+
+/* Colibri Registers */
+
+#define SINGLE_ENDED            0x0
+#define LOW_IF                  0x4
+#define EU_IF                   0x9
+#define US_IF                   0xa
+
+
+
+#define SUP_BLK_TUNE1           0x00
+#define SUP_BLK_TUNE2           0x01
+#define SUP_BLK_TUNE3           0x02
+#define SUP_BLK_XTAL            0x03
+#define SUP_BLK_PLL1            0x04
+#define SUP_BLK_PLL2            0x05
+#define SUP_BLK_PLL3            0x06
+#define SUP_BLK_REF             0x07
+#define SUP_BLK_PWRDN           0x08
+#define SUP_BLK_TESTPAD         0x09
+#define ADC_COM_INT5_STAB_REF   0x0a
+#define ADC_COM_QUANT           0x0b
+#define ADC_COM_BIAS1           0x0c
+#define ADC_COM_BIAS2           0x0d
+#define ADC_COM_BIAS3           0x0e
+#define TESTBUS_CTRL            0x12
+
+#define ADC_STATUS_CH1          0x20
+#define ADC_STATUS_CH2          0x40
+#define ADC_STATUS_CH3          0x60
+
+#define ADC_STATUS2_CH1         0x21
+#define ADC_STATUS2_CH2         0x41
+#define ADC_STATUS2_CH3         0x61
+
+#define ADC_CAL_ATEST_CH1       0x22
+#define ADC_CAL_ATEST_CH2       0x42
+#define ADC_CAL_ATEST_CH3       0x62
+
+#define ADC_PWRDN_CLAMP_CH1     0x23
+#define ADC_PWRDN_CLAMP_CH2     0x43
+#define ADC_PWRDN_CLAMP_CH3     0x63
+
+#define ADC_CTRL_DAC23_CH1      0x24
+#define ADC_CTRL_DAC23_CH2      0x44
+#define ADC_CTRL_DAC23_CH3      0x64
+
+#define ADC_CTRL_DAC1_CH1       0x25
+#define ADC_CTRL_DAC1_CH2       0x45
+#define ADC_CTRL_DAC1_CH3       0x65
+
+#define ADC_DCSERVO_DEM_CH1     0x26
+#define ADC_DCSERVO_DEM_CH2     0x46
+#define ADC_DCSERVO_DEM_CH3     0x66
+
+#define ADC_FB_FRCRST_CH1       0x27
+#define ADC_FB_FRCRST_CH2       0x47
+#define ADC_FB_FRCRST_CH3       0x67
+
+#define ADC_INPUT_CH1           0x28
+#define ADC_INPUT_CH2           0x48
+#define ADC_INPUT_CH3           0x68
+#define INPUT_SEL_MASK          0x30    /* [5:4] in_sel */
+
+#define ADC_NTF_PRECLMP_EN_CH1  0x29
+#define ADC_NTF_PRECLMP_EN_CH2  0x49
+#define ADC_NTF_PRECLMP_EN_CH3  0x69
+
+#define ADC_QGAIN_RES_TRM_CH1   0x2a
+#define ADC_QGAIN_RES_TRM_CH2   0x4a
+#define ADC_QGAIN_RES_TRM_CH3   0x6a
+
+#define ADC_SOC_PRECLMP_TERM_CH1    0x2b
+#define ADC_SOC_PRECLMP_TERM_CH2    0x4b
+#define ADC_SOC_PRECLMP_TERM_CH3    0x6b
+
+#define TESTBUS_CTRL_CH1        0x32
+#define TESTBUS_CTRL_CH2        0x52
+#define TESTBUS_CTRL_CH3        0x72
+
+/******************************************************************************
+                            * DIF registers *
+ ******************************************************************************/
+#define      DIRECT_IF_REVB_BASE  0x00300
+
+/*****************************************************************************/
+#define      DIF_PLL_FREQ_WORD        (DIRECT_IF_REVB_BASE + 0x00000000)  /* Reg Size 32 */
+/*****************************************************************************/
+#define      FLD_DIF_PLL_LOCK                           0x80000000
+/*  Reserved                                [30:29] */
+#define      FLD_DIF_PLL_FREE_RUN                       0x10000000
+#define      FLD_DIF_PLL_FREQ                           0x0FFFFFFF
+
+/*****************************************************************************/
+#define      DIF_PLL_CTRL             (DIRECT_IF_REVB_BASE + 0x00000004)  /* Reg Size 32 */
+/*****************************************************************************/
+#define      FLD_DIF_KD_PD                              0xFF000000
+/*  Reserved                             [23:20] */
+#define      FLD_DIF_KDS_PD                             0x000F0000
+#define      FLD_DIF_KI_PD                              0x0000FF00
+/*  Reserved                             [7:4] */
+#define      FLD_DIF_KIS_PD                             0x0000000F
+
+/*****************************************************************************/
+#define      DIF_PLL_CTRL1            (DIRECT_IF_REVB_BASE + 0x00000008)  /* Reg Size 32 */
+/*****************************************************************************/
+#define      FLD_DIF_KD_FD                              0xFF000000
+/*  Reserved                             [23:20] */
+#define      FLD_DIF_KDS_FD                             0x000F0000
+#define      FLD_DIF_KI_FD                              0x0000FF00
+#define      FLD_DIF_SIG_PROP_SZ                        0x000000F0
+#define      FLD_DIF_KIS_FD                             0x0000000F
+
+/*****************************************************************************/
+#define      DIF_PLL_CTRL2            (DIRECT_IF_REVB_BASE + 0x0000000C)  /* Reg Size 32 */
+/*****************************************************************************/
+#define      FLD_DIF_PLL_AGC_REF                        0xFFF00000
+#define      FLD_DIF_PLL_AGC_KI                         0x000F0000
+/*  Reserved                             [15] */
+#define      FLD_DIF_FREQ_LIMIT                         0x00007000
+#define      FLD_DIF_K_FD                               0x00000F00
+#define      FLD_DIF_DOWNSMPL_FD                        0x000000FF
+
+/*****************************************************************************/
+#define      DIF_PLL_CTRL3            (DIRECT_IF_REVB_BASE + 0x00000010)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:16] */
+#define      FLD_DIF_PLL_AGC_EN                         0x00008000
+/*  Reserved                             [14:12] */
+#define      FLD_DIF_PLL_MAN_GAIN                       0x00000FFF
+
+/*****************************************************************************/
+#define      DIF_AGC_IF_REF           (DIRECT_IF_REVB_BASE + 0x00000014)  /* Reg Size 32 */
+/*****************************************************************************/
+#define      FLD_DIF_K_AGC_RF                           0xF0000000
+#define      FLD_DIF_K_AGC_IF                           0x0F000000
+#define      FLD_DIF_K_AGC_INT                          0x00F00000
+/*  Reserved                             [19:12] */
+#define      FLD_DIF_IF_REF                             0x00000FFF
+
+/*****************************************************************************/
+#define      DIF_AGC_CTRL_IF          (DIRECT_IF_REVB_BASE + 0x00000018)  /* Reg Size 32 */
+/*****************************************************************************/
+#define      FLD_DIF_IF_MAX                             0xFF000000
+#define      FLD_DIF_IF_MIN                             0x00FF0000
+#define      FLD_DIF_IF_AGC                             0x0000FFFF
+
+/*****************************************************************************/
+#define      DIF_AGC_CTRL_INT         (DIRECT_IF_REVB_BASE + 0x0000001C)  /* Reg Size 32 */
+/*****************************************************************************/
+#define      FLD_DIF_INT_MAX                            0xFF000000
+#define      FLD_DIF_INT_MIN                            0x00FF0000
+#define      FLD_DIF_INT_AGC                            0x0000FFFF
+
+/*****************************************************************************/
+#define      DIF_AGC_CTRL_RF          (DIRECT_IF_REVB_BASE + 0x00000020)  /* Reg Size 32 */
+/*****************************************************************************/
+#define      FLD_DIF_RF_MAX                             0xFF000000
+#define      FLD_DIF_RF_MIN                             0x00FF0000
+#define      FLD_DIF_RF_AGC                             0x0000FFFF
+
+/*****************************************************************************/
+#define      DIF_AGC_IF_INT_CURRENT   (DIRECT_IF_REVB_BASE + 0x00000024)  /* Reg Size 32 */
+/*****************************************************************************/
+#define      FLD_DIF_IF_AGC_IN                          0xFFFF0000
+#define      FLD_DIF_INT_AGC_IN                         0x0000FFFF
+
+/*****************************************************************************/
+#define      DIF_AGC_RF_CURRENT       (DIRECT_IF_REVB_BASE + 0x00000028)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                            [31:16] */
+#define      FLD_DIF_RF_AGC_IN                          0x0000FFFF
+
+/*****************************************************************************/
+#define      DIF_VIDEO_AGC_CTRL       (DIRECT_IF_REVB_BASE + 0x0000002C)  /* Reg Size 32 */
+/*****************************************************************************/
+#define      FLD_DIF_AFD                                0xC0000000
+#define      FLD_DIF_K_VID_AGC                          0x30000000
+#define      FLD_DIF_LINE_LENGTH                        0x0FFF0000
+#define      FLD_DIF_AGC_GAIN                           0x0000FFFF
+
+/*****************************************************************************/
+#define      DIF_VID_AUD_OVERRIDE     (DIRECT_IF_REVB_BASE + 0x00000030)  /* Reg Size 32 */
+/*****************************************************************************/
+#define      FLD_DIF_AUDIO_AGC_OVERRIDE                 0x80000000
+/*  Reserved                             [30:30] */
+#define      FLD_DIF_AUDIO_MAN_GAIN                     0x3F000000
+/*  Reserved                             [23:17] */
+#define      FLD_DIF_VID_AGC_OVERRIDE                   0x00010000
+#define      FLD_DIF_VID_MAN_GAIN                       0x0000FFFF
+
+/*****************************************************************************/
+#define      DIF_AV_SEP_CTRL          (DIRECT_IF_REVB_BASE + 0x00000034)  /* Reg Size 32 */
+/*****************************************************************************/
+#define      FLD_DIF_LPF_FREQ                           0xC0000000
+#define      FLD_DIF_AV_PHASE_INC                       0x3F000000
+#define      FLD_DIF_AUDIO_FREQ                         0x00FFFFFF
+
+/*****************************************************************************/
+#define      DIF_COMP_FLT_CTRL        (DIRECT_IF_REVB_BASE + 0x00000038)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                            [31:24] */
+#define      FLD_DIF_IIR23_R2                           0x00FF0000
+#define      FLD_DIF_IIR23_R1                           0x0000FF00
+#define      FLD_DIF_IIR1_R1                            0x000000FF
+
+/*****************************************************************************/
+#define      DIF_MISC_CTRL            (DIRECT_IF_REVB_BASE + 0x0000003C)  /* Reg Size 32 */
+/*****************************************************************************/
+#define      FLD_DIF_DIF_BYPASS                         0x80000000
+#define      FLD_DIF_FM_NYQ_GAIN                        0x40000000
+#define      FLD_DIF_RF_AGC_ENA                         0x20000000
+#define      FLD_DIF_INT_AGC_ENA                        0x10000000
+#define      FLD_DIF_IF_AGC_ENA                         0x08000000
+#define      FLD_DIF_FORCE_RF_IF_LOCK                   0x04000000
+#define      FLD_DIF_VIDEO_AGC_ENA                      0x02000000
+#define      FLD_DIF_RF_AGC_INV                         0x01000000
+#define      FLD_DIF_INT_AGC_INV                        0x00800000
+#define      FLD_DIF_IF_AGC_INV                         0x00400000
+#define      FLD_DIF_SPEC_INV                           0x00200000
+#define      FLD_DIF_AUD_FULL_BW                        0x00100000
+#define      FLD_DIF_AUD_SRC_SEL                        0x00080000
+/*  Reserved                             [18] */
+#define      FLD_DIF_IF_FREQ                            0x00030000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_TIP_OFFSET                         0x00003F00
+/*  Reserved                             [7:5] */
+#define      FLD_DIF_DITHER_ENA                         0x00000010
+/*  Reserved                             [3:1] */
+#define      FLD_DIF_RF_IF_LOCK                         0x00000001
+
+/*****************************************************************************/
+#define      DIF_SRC_PHASE_INC        (DIRECT_IF_REVB_BASE + 0x00000040)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:29] */
+#define      FLD_DIF_PHASE_INC                          0x1FFFFFFF
+
+/*****************************************************************************/
+#define      DIF_SRC_GAIN_CONTROL     (DIRECT_IF_REVB_BASE + 0x00000044)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:16] */
+#define      FLD_DIF_SRC_KI                             0x0000FF00
+#define      FLD_DIF_SRC_KD                             0x000000FF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF01          (DIRECT_IF_REVB_BASE + 0x00000048)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:19] */
+#define      FLD_DIF_BPF_COEFF_0                        0x00070000
+/*  Reserved                             [15:4] */
+#define      FLD_DIF_BPF_COEFF_1                        0x0000000F
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF23          (DIRECT_IF_REVB_BASE + 0x0000004c)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:22] */
+#define      FLD_DIF_BPF_COEFF_2                        0x003F0000
+/*  Reserved                             [15:7] */
+#define      FLD_DIF_BPF_COEFF_3                        0x0000007F
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF45          (DIRECT_IF_REVB_BASE + 0x00000050)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:24] */
+#define      FLD_DIF_BPF_COEFF_4                        0x00FF0000
+/*  Reserved                             [15:8] */
+#define      FLD_DIF_BPF_COEFF_5                        0x000000FF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF67          (DIRECT_IF_REVB_BASE + 0x00000054)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:25] */
+#define      FLD_DIF_BPF_COEFF_6                        0x01FF0000
+/*  Reserved                             [15:9] */
+#define      FLD_DIF_BPF_COEFF_7                        0x000001FF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF89          (DIRECT_IF_REVB_BASE + 0x00000058)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:26] */
+#define      FLD_DIF_BPF_COEFF_8                        0x03FF0000
+/*  Reserved                             [15:10] */
+#define      FLD_DIF_BPF_COEFF_9                        0x000003FF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF1011        (DIRECT_IF_REVB_BASE + 0x0000005C)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:27] */
+#define      FLD_DIF_BPF_COEFF_10                       0x07FF0000
+/*  Reserved                             [15:11] */
+#define      FLD_DIF_BPF_COEFF_11                       0x000007FF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF1213        (DIRECT_IF_REVB_BASE + 0x00000060)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:27] */
+#define      FLD_DIF_BPF_COEFF_12                       0x07FF0000
+/*  Reserved                             [15:12] */
+#define      FLD_DIF_BPF_COEFF_13                       0x00000FFF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF1415        (DIRECT_IF_REVB_BASE + 0x00000064)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:28] */
+#define      FLD_DIF_BPF_COEFF_14                       0x0FFF0000
+/*  Reserved                             [15:12] */
+#define      FLD_DIF_BPF_COEFF_15                       0x00000FFF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF1617        (DIRECT_IF_REVB_BASE + 0x00000068)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:29] */
+#define      FLD_DIF_BPF_COEFF_16                       0x1FFF0000
+/*  Reserved                             [15:13] */
+#define      FLD_DIF_BPF_COEFF_17                       0x00001FFF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF1819        (DIRECT_IF_REVB_BASE + 0x0000006C)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:29] */
+#define      FLD_DIF_BPF_COEFF_18                       0x1FFF0000
+/*  Reserved                             [15:13] */
+#define      FLD_DIF_BPF_COEFF_19                       0x00001FFF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF2021        (DIRECT_IF_REVB_BASE + 0x00000070)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:29] */
+#define      FLD_DIF_BPF_COEFF_20                       0x1FFF0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_21                       0x00003FFF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF2223        (DIRECT_IF_REVB_BASE + 0x00000074)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_22                       0x3FFF0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_23                       0x00003FFF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF2425        (DIRECT_IF_REVB_BASE + 0x00000078)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_24                       0x3FFF0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_25                       0x00003FFF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF2627        (DIRECT_IF_REVB_BASE + 0x0000007C)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_26                       0x3FFF0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_27                       0x00003FFF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF2829        (DIRECT_IF_REVB_BASE + 0x00000080)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_28                       0x3FFF0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_29                       0x00003FFF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF3031        (DIRECT_IF_REVB_BASE + 0x00000084)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_30                       0x3FFF0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_31                       0x00003FFF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF3233        (DIRECT_IF_REVB_BASE + 0x00000088)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_32                       0x3FFF0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_33                       0x00003FFF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF3435        (DIRECT_IF_REVB_BASE + 0x0000008C)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_34                       0x3FFF0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_35                       0x00003FFF
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF36          (DIRECT_IF_REVB_BASE + 0x00000090)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_36                       0x3FFF0000
+/*  Reserved                             [15:0] */
+
+/*****************************************************************************/
+#define      DIF_RPT_VARIANCE         (DIRECT_IF_REVB_BASE + 0x00000094)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:20] */
+#define      FLD_DIF_RPT_VARIANCE                       0x000FFFFF
+
+/*****************************************************************************/
+#define      DIF_SOFT_RST_CTRL_REVB       (DIRECT_IF_REVB_BASE + 0x00000098)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:8] */
+#define      FLD_DIF_DIF_SOFT_RST                       0x00000080
+#define      FLD_DIF_DIF_REG_RST_MSK                    0x00000040
+#define      FLD_DIF_AGC_RST_MSK                        0x00000020
+#define      FLD_DIF_CMP_RST_MSK                        0x00000010
+#define      FLD_DIF_AVS_RST_MSK                        0x00000008
+#define      FLD_DIF_NYQ_RST_MSK                        0x00000004
+#define      FLD_DIF_DIF_SRC_RST_MSK                    0x00000002
+#define      FLD_DIF_PLL_RST_MSK                        0x00000001
+
+/*****************************************************************************/
+#define      DIF_PLL_FREQ_ERR         (DIRECT_IF_REVB_BASE + 0x0000009C)  /* Reg Size 32 */
+/*****************************************************************************/
+/*  Reserved                             [31:25] */
+#define      FLD_DIF_CTL_IP                             0x01FFFFFF
+
+
+#endif
diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c
new file mode 100644 (file)
index 0000000..efe0c66
--- /dev/null
@@ -0,0 +1,1167 @@
+/*
+   cx231xx-core.c - driver for Conexant Cx23100/101/102 USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+        Based on em28xx driver
+
+   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; either version 2 of the License, or
+   (at your option) any later version.
+
+   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/list.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/vmalloc.h>
+#include <media/v4l2-common.h>
+
+#include "cx231xx.h"
+#include "cx231xx-reg.h"
+
+/* #define ENABLE_DEBUG_ISOC_FRAMES */
+
+static unsigned int core_debug;
+module_param(core_debug,int,0644);
+MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+
+#define cx231xx_coredbg(fmt, arg...) do {\
+       if (core_debug) \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); } while (0)
+
+static unsigned int reg_debug;
+module_param(reg_debug,int,0644);
+MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]");
+
+#define cx231xx_regdbg(fmt, arg...) do {\
+       if (reg_debug) \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); } while (0)
+
+static int alt = CX231XX_PINOUT;
+module_param(alt, int, 0644);
+MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
+
+/* FIXME */
+#define cx231xx_isocdbg(fmt, arg...) do {\
+       if (core_debug) \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); } while (0)
+
+
+
+/************************************************************************************
+*                              Device control list functions                        *
+*************************************************************************************/
+
+static LIST_HEAD(cx231xx_devlist);
+static DEFINE_MUTEX(cx231xx_devlist_mutex);
+
+struct cx231xx *cx231xx_get_device(int minor,
+                                enum v4l2_buf_type *fh_type,
+                                int *has_radio)
+{
+       struct cx231xx *h, *dev = NULL;
+
+       *fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       *has_radio = 0;
+
+       mutex_lock(&cx231xx_devlist_mutex);
+       list_for_each_entry(h, &cx231xx_devlist, devlist) {
+               if (h->vdev->minor == minor)
+                       dev = h;
+               if (h->vbi_dev->minor == minor) {
+                       dev = h;
+                       *fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
+               }
+               if (h->radio_dev &&
+                   h->radio_dev->minor == minor) {
+                       dev = h;
+                       *has_radio = 1;
+               }
+       }
+       mutex_unlock(&cx231xx_devlist_mutex);
+
+       return dev;
+}
+
+/*
+ * cx231xx_realease_resources()
+ * unregisters the v4l2,i2c and usb devices
+ * called when the device gets disconected or at module unload
+*/
+void cx231xx_remove_from_devlist(struct cx231xx *dev)
+{
+       mutex_lock(&cx231xx_devlist_mutex);
+       list_del(&dev->devlist);
+       mutex_unlock(&cx231xx_devlist_mutex);
+};
+
+void cx231xx_add_into_devlist(struct cx231xx *dev)
+{
+       mutex_lock(&cx231xx_devlist_mutex);
+       list_add_tail(&dev->devlist, &cx231xx_devlist);
+       mutex_unlock(&cx231xx_devlist_mutex);
+};
+
+
+
+
+static LIST_HEAD(cx231xx_extension_devlist);
+static DEFINE_MUTEX(cx231xx_extension_devlist_lock);
+
+int cx231xx_register_extension(struct cx231xx_ops *ops)
+{
+       struct cx231xx *dev = NULL;
+
+       mutex_lock(&cx231xx_devlist_mutex);
+       mutex_lock(&cx231xx_extension_devlist_lock);
+       list_add_tail(&ops->next, &cx231xx_extension_devlist);
+       list_for_each_entry(dev, &cx231xx_devlist, devlist) {
+               if (dev)
+                       ops->init(dev);
+       }
+       cx231xx_info("Cx231xx: Initialized (%s) extension\n", ops->name);
+       mutex_unlock(&cx231xx_extension_devlist_lock);
+       mutex_unlock(&cx231xx_devlist_mutex);
+       return 0;
+}
+EXPORT_SYMBOL(cx231xx_register_extension);
+
+void cx231xx_unregister_extension(struct cx231xx_ops *ops)
+{
+       struct cx231xx *dev = NULL;
+
+       mutex_lock(&cx231xx_devlist_mutex);
+       list_for_each_entry(dev, &cx231xx_devlist, devlist) {
+               if (dev)
+                       ops->fini(dev);
+       }
+
+       mutex_lock(&cx231xx_extension_devlist_lock);
+       cx231xx_info("Cx231xx: Removed (%s) extension\n", ops->name);
+       list_del(&ops->next);
+       mutex_unlock(&cx231xx_extension_devlist_lock);
+       mutex_unlock(&cx231xx_devlist_mutex);
+}
+EXPORT_SYMBOL(cx231xx_unregister_extension);
+
+
+void cx231xx_init_extension(struct cx231xx *dev)
+{
+       struct cx231xx_ops *ops = NULL;
+
+       mutex_lock(&cx231xx_extension_devlist_lock);
+       if (!list_empty(&cx231xx_extension_devlist)) {
+               list_for_each_entry(ops, &cx231xx_extension_devlist, next) {
+                       if (ops->init)
+                               ops->init(dev);
+               }
+       }
+       mutex_unlock(&cx231xx_extension_devlist_lock);
+}
+
+void cx231xx_close_extension(struct cx231xx *dev)
+{
+       struct cx231xx_ops *ops = NULL;
+
+       mutex_lock(&cx231xx_extension_devlist_lock);
+       if (!list_empty(&cx231xx_extension_devlist)) {
+               list_for_each_entry(ops, &cx231xx_extension_devlist, next) {
+                       if (ops->fini)
+                               ops->fini(dev);
+               }
+       }
+       mutex_unlock(&cx231xx_extension_devlist_lock);
+}
+
+/************************************************************************************
+*                              U S B related functions                              *
+*************************************************************************************/
+int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus,
+                   struct cx231xx_i2c_xfer_data *req_data)
+{
+    int status = 0;
+    struct cx231xx *dev = i2c_bus->dev;
+    VENDOR_REQUEST_IN ven_req;
+
+    u8 saddr_len    = 0;
+    u8 _i2c_period  = 0;
+    u8 _i2c_nostop  = 0;
+    u8 _i2c_reserve = 0;
+
+    /* Get the I2C period, nostop and reserve parameters */
+    _i2c_period  = i2c_bus->i2c_period;
+    _i2c_nostop  = i2c_bus->i2c_nostop;
+    _i2c_reserve = i2c_bus->i2c_reserve;
+
+    saddr_len = req_data->saddr_len;
+
+    /* Set wValue */
+    if(saddr_len == 1)                          /* need check saddr_len == 0  */
+        ven_req.wValue = req_data->dev_addr<<9|_i2c_period<<4|saddr_len<<2|
+                        _i2c_nostop<<1|I2C_SYNC|_i2c_reserve<<6;
+    else
+        ven_req.wValue = req_data->dev_addr<<9|_i2c_period<<4|saddr_len<<2|
+                        _i2c_nostop<<1|I2C_SYNC|_i2c_reserve<<6;
+
+    /* set channel number */
+    if(req_data->direction & I2C_M_RD)
+        ven_req.bRequest = i2c_bus->nr + 4;   /* channel number, for read,
+                                                 spec required channel_num +4 */
+    else
+        ven_req.bRequest = i2c_bus->nr;       /* channel number,  */
+
+    /* set index value */
+    switch(saddr_len){
+        case 0:
+            ven_req.wIndex = 0;               /* need check */
+            break;
+        case 1:
+            ven_req.wIndex = (req_data->saddr_dat & 0xff);
+            break;
+        case 2:
+            ven_req.wIndex = req_data->saddr_dat;
+            break;
+    }
+
+    /* set wLength value */
+    ven_req.wLength = req_data->buf_size;
+
+    /* set bData value */
+    ven_req.bData = 0;
+
+    /* set the direction */
+    if(req_data->direction){
+        ven_req.direction = USB_DIR_IN;
+        memset(req_data->p_buffer, 0x00, ven_req.wLength);
+    }
+    else
+        ven_req.direction = USB_DIR_OUT;
+
+    /* set the buffer for read / write */
+    ven_req.pBuff = req_data->p_buffer;
+
+
+
+    /* call common vendor command request */
+    status = cx231xx_send_vendor_cmd(dev, &ven_req);
+    if (status < 0) {
+        cx231xx_info("UsbInterface::sendCommand, output buffer failed with status -%d\n", status);
+    }
+
+    return status;
+}
+
+EXPORT_SYMBOL_GPL(cx231xx_send_usb_command);
+/*
+ * cx231xx_read_ctrl_reg()
+ * reads data from the usb device specifying bRequest and wValue
+ */
+int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg,
+                           char *buf, int len)
+{
+     u8 val = 0;
+       int ret;
+       int pipe = usb_rcvctrlpipe(dev->udev, 0);
+
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
+       if (len > URB_MAX_CTRL_SIZE)
+               return -EINVAL;
+
+    switch(len)
+    {
+        case 1:
+            val = ENABLE_ONE_BYTE;
+            break;
+        case 2:
+            val = ENABLE_TWE_BYTE;
+            break;
+        case 3:
+            val = ENABLE_THREE_BYTE;
+            break;
+        case 4:
+            val = ENABLE_FOUR_BYTE;
+            break;
+        default:
+            val = 0xFF; /* invalid option */
+    }
+
+    if(val == 0xFF)
+        return -EINVAL;
+
+       if (reg_debug) {
+               cx231xx_isocdbg("(pipe 0x%08x): "
+                       "IN:  %02x %02x %02x %02x %02x %02x %02x %02x ",
+                       pipe,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       req, 0, val,
+                       reg & 0xff, reg >> 8,
+                       len & 0xff, len >> 8);
+       }
+
+       /* mutex_lock(&dev->ctrl_urb_lock);  */
+       ret = usb_control_msg(dev->udev, pipe, req,
+                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             val, reg, dev->urb_buf, len, HZ);
+       if (ret < 0) {
+               cx231xx_isocdbg(" failed!\n");
+               /* mutex_unlock(&dev->ctrl_urb_lock); */
+               return ret;
+       }
+
+       if (len)
+               memcpy(buf, dev->urb_buf, len);
+
+       /* mutex_unlock(&dev->ctrl_urb_lock); */
+
+       if (reg_debug) {
+               int byte;
+
+               cx231xx_isocdbg("<<<");
+               for (byte = 0; byte < len; byte++)
+                       cx231xx_isocdbg(" %02x", (unsigned char)buf[byte]);
+               cx231xx_isocdbg("\n");
+       }
+
+       return ret;
+}
+
+
+int cx231xx_send_vendor_cmd(struct cx231xx *dev, VENDOR_REQUEST_IN *ven_req)
+{
+    int ret;
+       int pipe = 0;
+
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
+       if ((ven_req->wLength > URB_MAX_CTRL_SIZE))
+               return -EINVAL;
+
+    if(ven_req->direction)
+        pipe = usb_rcvctrlpipe(dev->udev, 0);
+    else
+        pipe = usb_sndctrlpipe(dev->udev, 0);
+
+
+       if (reg_debug) {
+               int byte;
+
+               cx231xx_isocdbg("(pipe 0x%08x): "
+                       "OUT: %02x %02x %02x %04x %04x %04x >>>",
+                       pipe,
+                       ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       ven_req->bRequest, 0, ven_req->wValue,
+                       ven_req->wIndex,
+                       ven_req->wLength);
+
+               for (byte = 0; byte < ven_req->wLength; byte++)
+                       cx231xx_isocdbg(" %02x", (unsigned char)ven_req->pBuff[byte]);
+               cx231xx_isocdbg("\n");
+       }
+
+       /* mutex_lock(&dev->ctrl_urb_lock); */
+       ret = usb_control_msg(dev->udev, pipe, ven_req->bRequest,
+                             ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             ven_req->wValue, ven_req->wIndex, ven_req->pBuff, ven_req->wLength, HZ);
+       /* mutex_unlock(&dev->ctrl_urb_lock); */
+
+       return ret;
+}
+
+/*
+ * cx231xx_write_ctrl_reg()
+ * sends data to the usb device, specifying bRequest
+ */
+int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf,
+                                int len)
+{
+    u8 val = 0;
+       int ret;
+       int pipe = usb_sndctrlpipe(dev->udev, 0);
+
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
+       if ((len < 1) || (len > URB_MAX_CTRL_SIZE))
+               return -EINVAL;
+
+    switch(len)
+    {
+        case 1:
+            val = ENABLE_ONE_BYTE;
+            break;
+        case 2:
+            val = ENABLE_TWE_BYTE;
+            break;
+        case 3:
+            val = ENABLE_THREE_BYTE;
+            break;
+        case 4:
+            val = ENABLE_FOUR_BYTE;
+            break;
+        default:
+            val = 0xFF; /* invalid option */
+    }
+
+    if(val == 0xFF)
+        return -EINVAL;
+
+       if (reg_debug) {
+               int byte;
+
+               cx231xx_isocdbg("(pipe 0x%08x): "
+                       "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>",
+                       pipe,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       req, 0, val,
+                       reg & 0xff, reg >> 8,
+                       len & 0xff, len >> 8);
+
+               for (byte = 0; byte < len; byte++)
+                       cx231xx_isocdbg(" %02x", (unsigned char)buf[byte]);
+               cx231xx_isocdbg("\n");
+       }
+
+       /* mutex_lock(&dev->ctrl_urb_lock); */
+       memcpy(dev->urb_buf, buf, len);
+       ret = usb_control_msg(dev->udev, pipe, req,
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             val, reg, dev->urb_buf, len, HZ);
+       /* mutex_unlock(&dev->ctrl_urb_lock); */
+
+       return ret;
+}
+
+
+/************************************************************************************
+*                         USB Alternate Setting functions                           *
+*************************************************************************************/
+
+int cx231xx_set_video_alternate(struct cx231xx *dev)
+{
+       int errCode, prev_alt = dev->video_mode.alt;
+       unsigned int min_pkt_size = dev->width * 2 + 4;
+    u32 usb_interface_index = 0;
+
+       /* When image size is bigger than a certain value,
+          the frame size should be increased, otherwise, only
+          green screen will be received.
+        */
+       if (dev->width * 2 * dev->height > 720 * 240 * 2)
+               min_pkt_size *= 2;
+
+    if(dev->width > 360) {
+        /* resolutions: 720,704,640 */
+        dev->video_mode.alt = 3;
+    } else if(dev->width > 180) {
+        /* resolutions: 360,352,320,240 */
+        dev->video_mode.alt = 2;
+    } else if(dev->width > 0) {
+        /* resolutions: 180,176,160,128,88 */
+        dev->video_mode.alt = 1;
+    } else {
+        /* Change to alt0 BULK to release USB bandwidth */
+        dev->video_mode.alt = 0;
+    }
+
+    /* Get the correct video interface Index */
+    usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.video_index+1;
+
+       if (dev->video_mode.alt != prev_alt) {
+               cx231xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
+                               min_pkt_size, dev->video_mode.alt);
+               dev->video_mode.max_pkt_size = dev->video_mode.alt_max_pkt_size[dev->video_mode.alt];
+               cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
+                              dev->video_mode.alt, dev->video_mode.max_pkt_size);
+        cx231xx_info(" setting alternate %d with wMaxPacketSize=%u , Interface = %d\n",
+                              dev->video_mode.alt, dev->video_mode.max_pkt_size, usb_interface_index);
+               errCode = usb_set_interface(dev->udev, usb_interface_index, dev->video_mode.alt);
+               if (errCode < 0) {
+                       cx231xx_errdev("cannot change alternate number to %d (error=%i)\n",
+                                       dev->video_mode.alt, errCode);
+                       return errCode;
+               }
+       }
+       return 0;
+}
+
+int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt)
+{
+    int status = 0;
+    u32 usb_interface_index = 0;
+    u32 max_pkt_size = 0;
+
+    switch(index) {
+        case INDEX_TS1:
+            usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index+1;
+            dev->video_mode.alt = alt;
+            if(dev->ts1_mode.alt_max_pkt_size != NULL)
+                max_pkt_size = dev->ts1_mode.max_pkt_size = dev->ts1_mode.alt_max_pkt_size[dev->ts1_mode.alt];
+            break;
+        case INDEX_TS2:
+            usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.ts2_index+1;
+            break;
+        case INDEX_AUDIO:
+            usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.audio_index+1;
+            dev->adev.alt = alt;
+            if( dev->adev.alt_max_pkt_size != NULL)
+                max_pkt_size = dev->adev.max_pkt_size = dev->adev.alt_max_pkt_size[dev->adev.alt];
+            break;
+        case INDEX_VIDEO:
+            usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.video_index+1;
+            dev->video_mode.alt = alt;
+            if(dev->video_mode.alt_max_pkt_size != NULL)
+                max_pkt_size = dev->video_mode.max_pkt_size = dev->video_mode.alt_max_pkt_size[dev->video_mode.alt];
+            break;
+        case INDEX_VANC:
+            usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index+1;
+            dev->vbi_mode.alt = alt;
+            if(dev->vbi_mode.alt_max_pkt_size != NULL)
+                max_pkt_size = dev->vbi_mode.max_pkt_size = dev->vbi_mode.alt_max_pkt_size[dev->vbi_mode.alt];
+            break;
+        case INDEX_HANC:
+            usb_interface_index = dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index+1;
+            dev->sliced_cc_mode.alt = alt;
+            if(dev->sliced_cc_mode.alt_max_pkt_size != NULL)
+                max_pkt_size = dev->sliced_cc_mode.max_pkt_size = dev->sliced_cc_mode.alt_max_pkt_size[dev->sliced_cc_mode.alt];
+            break;
+        default:
+            break;
+    }
+
+    if(alt > 0 && max_pkt_size == 0 ) {
+        cx231xx_errdev("cannot change interface %d alternate number to %d : Max. Pkt size is ZERO\n",
+                                       usb_interface_index, alt);
+        return -1;
+    }
+
+    cx231xx_info(" setting alternate %d with wMaxPacketSize=%u , Interface = %d\n",
+                              alt, max_pkt_size, usb_interface_index);
+
+    if(usb_interface_index > 0 ) {
+        status = usb_set_interface(dev->udev, usb_interface_index, alt);
+               if (status < 0) {
+                       cx231xx_errdev("cannot change interface %d alternate number to %d (error=%i)\n",
+                                       usb_interface_index, alt, status);
+                       return status;
+               }
+    }
+
+    return status;
+}
+EXPORT_SYMBOL_GPL(cx231xx_set_alt_setting);
+
+int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio)
+{
+       int rc = 0;
+
+       if (!gpio)
+               return rc;
+
+       /* Send GPIO reset sequences specified at board entry */
+       while (gpio->sleep >= 0) {
+        rc = cx231xx_set_gpio_value(dev, gpio->bit,
+                                                  gpio->val);
+                       if (rc < 0)
+                               return rc;
+
+               if (gpio->sleep > 0)
+                       msleep(gpio->sleep);
+
+               gpio++;
+       }
+       return rc;
+}
+
+int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode)
+{
+       if (dev->mode == set_mode)
+               return 0;
+
+       if (set_mode == CX231XX_SUSPEND) {
+        /* Set the chip in power saving mode */
+               dev->mode = set_mode;
+       }
+
+       /* Resource is locked */
+       if (dev->mode != CX231XX_SUSPEND)
+               return -EINVAL;
+
+       dev->mode = set_mode;
+
+    if (dev->mode == CX231XX_DIGITAL_MODE) {
+        /* Set Digital power mode */
+    } else {
+        /* Set Analog Power mode*/
+    }
+    return 0;
+}
+EXPORT_SYMBOL_GPL(cx231xx_set_mode);
+
+/************************************************************************************
+*                               URB Streaming functions                             *
+*************************************************************************************/
+
+/*
+ * IRQ callback, called by URB callback
+ */
+static void cx231xx_irq_callback(struct urb *urb)
+{
+       struct cx231xx_dmaqueue  *dma_q = urb->context;
+    struct cx231xx_video_mode *vmode = container_of(dma_q, struct cx231xx_video_mode, vidq);
+    struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode);
+       int rc, i;
+
+
+    switch (urb->status) {
+           case 0:             /* success */
+           case -ETIMEDOUT:    /* NAK */
+                   break;
+           case -ECONNRESET:   /* kill */
+           case -ENOENT:
+           case -ESHUTDOWN:
+                   return;
+           default:            /* error */
+                   cx231xx_isocdbg("urb completition error %d.\n", urb->status);
+                   break;
+       }
+
+       /* Copy data from URB */
+       spin_lock(&dev->video_mode.slock);
+       rc = dev->video_mode.isoc_ctl.isoc_copy(dev, urb);
+       spin_unlock(&dev->video_mode.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 = 0;
+
+       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (urb->status) {
+               cx231xx_isocdbg("urb resubmit failed (error=%i)\n",
+                              urb->status);
+       }
+}
+
+/*
+ * Stop and Deallocate URBs
+ */
+void cx231xx_uninit_isoc(struct cx231xx *dev)
+{
+       struct urb *urb;
+       int i;
+
+       cx231xx_isocdbg("cx231xx: called cx231xx_uninit_isoc\n");
+
+       dev->video_mode.isoc_ctl.nfields = -1;
+       for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {
+               urb = dev->video_mode.isoc_ctl.urb[i];
+               if (urb) {
+            if (!irqs_disabled())
+                           usb_kill_urb(urb);
+            else
+                           usb_unlink_urb(urb);
+
+                       if (dev->video_mode.isoc_ctl.transfer_buffer[i]) {
+                               usb_buffer_free(dev->udev,
+                                       urb->transfer_buffer_length,
+                                       dev->video_mode.isoc_ctl.transfer_buffer[i],
+                                       urb->transfer_dma);
+                       }
+                       usb_free_urb(urb);
+                       dev->video_mode.isoc_ctl.urb[i] = NULL;
+               }
+               dev->video_mode.isoc_ctl.transfer_buffer[i] = NULL;
+       }
+
+       kfree(dev->video_mode.isoc_ctl.urb);
+       kfree(dev->video_mode.isoc_ctl.transfer_buffer);
+
+       dev->video_mode.isoc_ctl.urb = NULL;
+       dev->video_mode.isoc_ctl.transfer_buffer = NULL;
+       dev->video_mode.isoc_ctl.num_bufs = 0;
+
+       cx231xx_capture_start(dev, 0, Raw_Video);
+}
+EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc);
+
+/*
+ * Allocate URBs and start IRQ
+ */
+int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
+                    int num_bufs, int max_pkt_size,
+                    int (*isoc_copy) (struct cx231xx *dev, struct urb *urb))
+{
+       struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq;
+       int i;
+       int sb_size, pipe;
+       struct urb *urb;
+       int j, k;
+       int rc;
+
+       cx231xx_isocdbg("cx231xx: called cx231xx_prepare_isoc\n");
+
+    dev->video_input = dev->video_input > 2?2:dev->video_input;
+
+    cx231xx_info("Setting Video mux to %d\n",dev->video_input);
+    video_mux(dev, dev->video_input);
+
+
+       /* De-allocates all pending stuff */
+       cx231xx_uninit_isoc(dev);
+
+       dev->video_mode.isoc_ctl.isoc_copy = isoc_copy;
+       dev->video_mode.isoc_ctl.num_bufs = num_bufs;
+    dma_q->pos = 0;
+    dma_q->is_partial_line = 0;
+    dma_q->last_sav = 0;
+    dma_q->current_field = -1;
+    dma_q->field1_done = 0;
+    dma_q->lines_per_field = dev->height/2;
+    dma_q->bytes_left_in_line = dev->width << 1;
+    dma_q->lines_completed = 0;
+    for(i = 0; i < 8 ; i++)
+        dma_q->partial_buf[i] = 0;
+
+       dev->video_mode.isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs,  GFP_KERNEL);
+       if (!dev->video_mode.isoc_ctl.urb) {
+               cx231xx_errdev("cannot alloc memory for usb buffers\n");
+               return -ENOMEM;
+       }
+
+       dev->video_mode.isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
+                                             GFP_KERNEL);
+       if (!dev->video_mode.isoc_ctl.transfer_buffer) {
+               cx231xx_errdev("cannot allocate memory for usbtransfer\n");
+               kfree(dev->video_mode.isoc_ctl.urb);
+               return -ENOMEM;
+       }
+
+       dev->video_mode.isoc_ctl.max_pkt_size = max_pkt_size;
+       dev->video_mode.isoc_ctl.buf = NULL;
+
+       sb_size = max_packets * dev->video_mode.isoc_ctl.max_pkt_size;
+
+       /* allocate urbs and transfer buffers */
+       for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {
+               urb = usb_alloc_urb(max_packets, GFP_KERNEL);
+               if (!urb) {
+                       cx231xx_err("cannot alloc isoc_ctl.urb %i\n", i);
+                       cx231xx_uninit_isoc(dev);
+                       return -ENOMEM;
+               }
+               dev->video_mode.isoc_ctl.urb[i] = urb;
+
+               dev->video_mode.isoc_ctl.transfer_buffer[i] = usb_buffer_alloc(dev->udev,
+                       sb_size, GFP_KERNEL, &urb->transfer_dma);
+               if (!dev->video_mode.isoc_ctl.transfer_buffer[i]) {
+                       cx231xx_err("unable to allocate %i bytes for transfer"
+                                       " buffer %i%s\n",
+                                       sb_size, i,
+                                       in_interrupt()?" while in int":"");
+                       cx231xx_uninit_isoc(dev);
+                       return -ENOMEM;
+               }
+               memset(dev->video_mode.isoc_ctl.transfer_buffer[i], 0, sb_size);
+
+               pipe = usb_rcvisocpipe(dev->udev, dev->video_mode.end_point_addr);
+
+               usb_fill_int_urb(urb, dev->udev, pipe,
+                                dev->video_mode.isoc_ctl.transfer_buffer[i], sb_size,
+                                cx231xx_irq_callback, dma_q, 1);
+
+               urb->number_of_packets = max_packets;
+               urb->transfer_flags = URB_ISO_ASAP;
+
+               k = 0;
+               for (j = 0; j < max_packets; j++) {
+                       urb->iso_frame_desc[j].offset = k;
+                       urb->iso_frame_desc[j].length =
+                                               dev->video_mode.isoc_ctl.max_pkt_size;
+                       k += dev->video_mode.isoc_ctl.max_pkt_size;
+               }
+       }
+
+       init_waitqueue_head(&dma_q->wq);
+
+
+       /* submit urbs and enables IRQ */
+       for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {
+               rc = usb_submit_urb(dev->video_mode.isoc_ctl.urb[i], GFP_ATOMIC);
+               if (rc) {
+                       cx231xx_err("submit of urb %i failed (error=%i)\n", i,
+                                  rc);
+                       cx231xx_uninit_isoc(dev);
+                       return rc;
+               }
+       }
+
+    cx231xx_capture_start(dev, 1, Raw_Video);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cx231xx_init_isoc);
+
+/************************************************************************************
+*                          Device Init/UnInit functions                             *
+*************************************************************************************/
+int cx231xx_dev_init(struct cx231xx *dev)
+{
+    int errCode = 0;
+
+    /* Initialize I2C bus */
+
+       /* External Master 1 Bus */
+       dev->i2c_bus[0].nr = 0;
+       dev->i2c_bus[0].dev = dev;
+       dev->i2c_bus[0].i2c_period = I2C_SPEED_1M;  /* 1MHz */
+    dev->i2c_bus[0].i2c_nostop = 0;
+    dev->i2c_bus[0].i2c_reserve = 0;
+
+       /* External Master 2 Bus */
+       dev->i2c_bus[1].nr = 1;
+       dev->i2c_bus[1].dev = dev;
+       dev->i2c_bus[1].i2c_period =  I2C_SPEED_1M;  /* 1MHz */
+    dev->i2c_bus[1].i2c_nostop = 0;
+    dev->i2c_bus[1].i2c_reserve = 0;
+
+       /* Internal Master 3 Bus */
+       dev->i2c_bus[2].nr = 2;
+       dev->i2c_bus[2].dev = dev;
+       dev->i2c_bus[2].i2c_period = I2C_SPEED_400K; /* 400kHz */
+    dev->i2c_bus[2].i2c_nostop = 0;
+    dev->i2c_bus[2].i2c_reserve = 0;
+
+    /* register I2C buses */
+       cx231xx_i2c_register(&dev->i2c_bus[0]);
+       cx231xx_i2c_register(&dev->i2c_bus[1]);
+       cx231xx_i2c_register(&dev->i2c_bus[2]);
+
+    /* init hardware */
+    /* Note : with out calling set power mode function, colibri can not be set up correctly */
+    errCode = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV);
+    if (errCode < 0) {
+        cx231xx_errdev("%s: cx231xx_set_power_mode : Failed to set Power - errCode [%d]!\n",
+                       __func__, errCode);
+               return errCode;
+       }
+
+    /* initialize Colibri block */
+    errCode = cx231xx_colibri_init_super_block(dev, 0x23c);
+       if (errCode < 0) {
+               cx231xx_errdev("%s: cx231xx_colibri init super block - errCode [%d]!\n",
+                       __func__, errCode);
+               return errCode;
+       }
+    errCode = cx231xx_colibri_init_channels(dev);
+    if (errCode < 0) {
+               cx231xx_errdev("%s: cx231xx_colibri init channels - errCode [%d]!\n",
+                       __func__, errCode);
+               return errCode;
+       }
+
+    /* Set DIF in By pass mode */
+    errCode = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
+    if (errCode < 0) {
+               cx231xx_errdev("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n",
+                       __func__, errCode);
+               return errCode;
+       }
+
+    /* flatiron related functions */
+    errCode = cx231xx_flatiron_initialize(dev);
+    if (errCode < 0) {
+               cx231xx_errdev("%s: cx231xx_flatiron initialize - errCode [%d]!\n",
+                       __func__, errCode);
+               return errCode;
+       }
+
+    /* init control pins */
+    errCode = cx231xx_init_ctrl_pin_status(dev);
+    if (errCode < 0) {
+               cx231xx_errdev("%s: cx231xx_init ctrl pins - errCode [%d]!\n",
+                       __func__, errCode);
+               return errCode;
+       }
+
+    /* set AGC mode to Analog */
+    errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1);
+    if (errCode < 0) {
+               cx231xx_errdev("%s: cx231xx_AGC mode to Analog - errCode [%d]!\n",
+                       __func__, errCode);
+               return errCode;
+       }
+
+    /* set all alternate settings to zero initially */
+    cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0);
+    cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
+    cx231xx_set_alt_setting(dev, INDEX_HANC, 0);
+    if(dev->board.has_dvb)
+        cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
+
+    /* set the I2C master port to 3 on channel 1 */
+    errCode = cx231xx_enable_i2c_for_tuner(dev, I2C_3);
+
+       return errCode;
+}
+EXPORT_SYMBOL_GPL(cx231xx_dev_init);
+
+void cx231xx_dev_uninit(struct cx231xx *dev)
+{
+    /* Un Initialize I2C bus */
+       cx231xx_i2c_unregister(&dev->i2c_bus[2]);
+       cx231xx_i2c_unregister(&dev->i2c_bus[1]);
+       cx231xx_i2c_unregister(&dev->i2c_bus[0]);
+}
+EXPORT_SYMBOL_GPL(cx231xx_dev_uninit);
+
+
+/************************************************************************************
+*                              G P I O related functions                            *
+*************************************************************************************/
+int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8* gpio_val,
+                          u8 len, u8 request, u8 direction)
+{
+    int status = 0;
+    VENDOR_REQUEST_IN ven_req;
+
+    /* Set wValue */
+    ven_req.wValue = (u16)(gpio_bit>>16 & 0xffff);
+
+    /* set request */
+    if(!request){
+        if(direction)
+            ven_req.bRequest = VRT_GET_GPIO; /* 0x8 gpio */
+        else
+            ven_req.bRequest = VRT_SET_GPIO; /* 0x9 gpio */
+    }
+    else {
+        if(direction)
+            ven_req.bRequest = VRT_GET_GPIE; /* 0xa gpie */
+        else
+            ven_req.bRequest = VRT_SET_GPIE; /* 0xb gpie */
+    }
+
+    /* set index value */
+    ven_req.wIndex = (u16)(gpio_bit & 0xffff);
+
+    /* set wLength value */
+    ven_req.wLength = len;
+
+    /* set bData value */
+    ven_req.bData = 0;
+
+       /* set the buffer for read / write */
+    ven_req.pBuff = gpio_val;
+
+    /* set the direction */
+    if(direction){
+        ven_req.direction = USB_DIR_IN;
+        memset(ven_req.pBuff, 0x00, ven_req.wLength);
+    }
+    else
+        ven_req.direction = USB_DIR_OUT;
+
+
+
+    /* call common vendor command request */
+    status = cx231xx_send_vendor_cmd(dev, &ven_req);
+    if (status < 0)
+    {
+        cx231xx_info("UsbInterface::sendCommand, output buffer failed with status -%d\n", status);
+    }
+
+    return status;
+}
+
+EXPORT_SYMBOL_GPL(cx231xx_send_gpio_cmd);
+
+/*************************************************************************************
+ *               C O N T R O L - Register R E A D / W R I T E functions              *
+ *************************************************************************************/
+int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode)
+{
+    u8  value[4] = {0x0, 0x0, 0x0, 0x0};
+    u32 tmp =0;
+    int status = 0;
+
+    status = cx231xx_read_ctrl_reg(dev,VRT_GET_REGISTER, address,value,4);
+    if(status < 0)
+        return status;
+
+    tmp = *((u32 *)value);
+    tmp |= mode;
+
+    value[0]=(u8) tmp;
+    value[1]=(u8)(tmp>>8);
+    value[2]=(u8)(tmp>>16);
+    value[3]=(u8)(tmp>>24);
+
+    status = cx231xx_write_ctrl_reg(dev,VRT_SET_REGISTER, address,value,4);
+
+    return status;
+}
+
+/*************************************************************************************
+ *                      I 2 C Internal C O N T R O L   functions                     *
+ *************************************************************************************/
+int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr,
+                           u8 saddr_len, u32 *data, u8 data_len)
+{
+    int status = 0;
+    struct cx231xx_i2c_xfer_data req_data;
+    u8 value[4] ={0,0,0,0};
+
+    if(saddr_len == 0)
+        saddr = 0;
+    else if(saddr_len == 0)
+        saddr &= 0xff;
+
+    /* prepare xfer_data struct */
+    req_data.dev_addr = dev_addr >> 1;
+    req_data.direction = I2C_M_RD;
+    req_data.saddr_len = saddr_len;
+    req_data.saddr_dat = saddr;
+    req_data.buf_size = data_len;
+    req_data.p_buffer = (u8*)value;
+
+    /* usb send command */
+    status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data);
+
+    if(status >= 0)
+    {
+        /* Copy the data read back to main buffer */
+        if(data_len == 1)
+            *data = value[0];
+        else
+            *data = value[0] | value[1] << 8 | value[2] << 16 | value[3] << 24;
+    }
+
+    return status;
+}
+
+int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr,
+                           u8 saddr_len, u32 data, u8 data_len)
+{
+    int status = 0;
+    u8 value[4] ={0,0,0,0};
+    struct cx231xx_i2c_xfer_data req_data;
+
+    value[0]=(u8)data;
+    value[1]=(u8)(data>>8);
+    value[2]=(u8)(data>>16);
+    value[3]=(u8)(data>>24);
+
+    if(saddr_len == 0)
+        saddr = 0;
+    else if(saddr_len == 0)
+        saddr &= 0xff;
+
+    /* prepare xfer_data struct */
+    req_data.dev_addr = dev_addr >> 1;
+    req_data.direction = 0;
+    req_data.saddr_len = saddr_len;
+    req_data.saddr_dat = saddr;
+    req_data.buf_size = data_len;
+    req_data.p_buffer = value;
+
+    /* usb send command */
+    status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data);
+
+    return status;
+}
+
+int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size, u16 register_address,
+                           u8 bit_start,u8 bit_end, u32 value)
+{
+    int status = 0;
+    u32 tmp;
+    u32 mask = 0;
+    int i;
+
+    if (bit_start>(size-1) || bit_end>(size-1)) {
+        return -1;
+    }
+
+    if (size==8){
+        status = cx231xx_read_i2c_data(dev, dev_addr, register_address, 2, &tmp, 1);
+    } else {
+        status = cx231xx_read_i2c_data(dev, dev_addr, register_address, 2, &tmp, 4);
+    }
+
+    if (status < 0) {
+        return status;
+    }
+
+    mask = 1<<bit_end;
+    for (i=bit_end; i>bit_start&&i>0; i--) {
+        mask = mask + (1<<(i-1));
+    }
+
+    value <<= bit_start;
+
+    if (size==8)
+    {
+        tmp &=  ~mask;
+        tmp |=  value;
+        tmp &= 0xff;
+        status = cx231xx_write_i2c_data(dev, dev_addr, register_address, 2, tmp, 1);
+    }
+    else
+    {
+        tmp &=  ~mask;
+        tmp |=  value;
+        status = cx231xx_write_i2c_data(dev, dev_addr, register_address, 2, tmp, 4);
+    }
+
+    return status;
+}
+
+
+
+int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr,
+                                       u16 saddr, u32 mask, u32 value)
+{
+    u32   temp;
+    int status = 0;
+
+    status = cx231xx_read_i2c_data(dev, dev_addr, saddr, 2, &temp, 4);
+
+    if(status < 0)
+        return status;
+
+    temp &= ~mask;
+    temp |= value;
+
+    status = cx231xx_write_i2c_data(dev, dev_addr, saddr, 2, temp, 4);
+
+    return status;
+}
+
+u32 cx231xx_set_field(u32 field_mask, u32 data)
+{
+   u32 temp;
+
+   for (temp = field_mask; (temp & 1) == 0; temp >>= 1) {
+      data <<= 1;
+   }
+
+   return data;
+}
diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c
new file mode 100644 (file)
index 0000000..46bdcec
--- /dev/null
@@ -0,0 +1,565 @@
+/*
+ DVB device driver for cx231xx
+
+ Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+        Based on em28xx driver
+
+ 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; either version 2 of the License, or
+   (at your option) any later version.
+
+   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/usb.h>
+
+#include "cx231xx.h"
+#include <media/v4l2-common.h>
+#include <media/videobuf-vmalloc.h>
+
+#include "xc5000.h"
+#include "dvb_dummy_fe.h"
+
+
+MODULE_DESCRIPTION("driver for cx231xx based DVB cards");
+MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define dprintk(level, fmt, arg...) do {                       \
+if (debug >= level)                                            \
+       printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \
+} while (0)
+
+#define CX231XX_DVB_NUM_BUFS 5
+#define CX231XX_DVB_MAX_PACKETSIZE 564
+#define CX231XX_DVB_MAX_PACKETS 64
+
+struct cx231xx_dvb {
+       struct dvb_frontend        *frontend;
+
+       /* feed count management */
+       struct mutex               lock;
+       int                        nfeeds;
+
+       /* general boilerplate stuff */
+       struct dvb_adapter         adapter;
+       struct dvb_demux           demux;
+       struct dmxdev              dmxdev;
+       struct dmx_frontend        fe_hw;
+       struct dmx_frontend        fe_mem;
+       struct dvb_net             net;
+};
+
+
+static inline void print_err_status(struct cx231xx *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(1, "URB status %d [%s].\n", status, errmsg);
+       } else {
+               dprintk(1, "URB packet %d, status %d [%s].\n",
+                       packet, status, errmsg);
+       }
+}
+
+static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb)
+{
+       int i;
+
+       if (!dev)
+               return 0;
+
+       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+               return 0;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               if (urb->status == -ENOENT)
+                       return 0;
+       }
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               int status = urb->iso_frame_desc[i].status;
+
+               if (status < 0) {
+                       print_err_status(dev, i, status);
+                       if (urb->iso_frame_desc[i].status != -EPROTO)
+                               continue;
+               }
+
+               dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer +
+                                urb->iso_frame_desc[i].offset,
+                                urb->iso_frame_desc[i].actual_length);
+       }
+
+       return 0;
+}
+
+static int start_streaming(struct cx231xx_dvb *dvb)
+{
+       int rc;
+       struct cx231xx *dev = dvb->adapter.priv;
+
+       usb_set_interface(dev->udev, 0, 1);
+       rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
+       if (rc < 0)
+               return rc;
+
+       return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS,
+                               CX231XX_DVB_NUM_BUFS, CX231XX_DVB_MAX_PACKETSIZE,
+                               dvb_isoc_copy);
+}
+
+static int stop_streaming(struct cx231xx_dvb *dvb)
+{
+       struct cx231xx *dev = dvb->adapter.priv;
+
+       cx231xx_uninit_isoc(dev);
+
+       cx231xx_set_mode(dev, CX231XX_SUSPEND);
+
+       return 0;
+}
+
+static int start_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux  = feed->demux;
+       struct cx231xx_dvb *dvb = demux->priv;
+       int rc, ret;
+
+       if (!demux->dmx.frontend)
+               return -EINVAL;
+
+       mutex_lock(&dvb->lock);
+       dvb->nfeeds++;
+       rc = dvb->nfeeds;
+
+       if (dvb->nfeeds == 1) {
+               ret = start_streaming(dvb);
+               if (ret < 0)
+                       rc = ret;
+       }
+
+       mutex_unlock(&dvb->lock);
+       return rc;
+}
+
+static int stop_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux  = feed->demux;
+       struct cx231xx_dvb *dvb = demux->priv;
+       int err = 0;
+
+       mutex_lock(&dvb->lock);
+       dvb->nfeeds--;
+
+       if (0 == dvb->nfeeds)
+               err = stop_streaming(dvb);
+
+       mutex_unlock(&dvb->lock);
+       return err;
+}
+
+
+
+/* ------------------------------------------------------------------ */
+static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+       struct cx231xx *dev = fe->dvb->priv;
+
+       if (acquire)
+               return cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
+       else
+               return cx231xx_set_mode(dev, CX231XX_SUSPEND);
+}
+
+/* ------------------------------------------------------------------ */
+
+
+static struct xc5000_config cnxt_rde250_tunerconfig = {
+       .i2c_address      = 0x61,
+       .if_khz           = 5380,
+};
+
+
+/* ------------------------------------------------------------------ */
+#if 0
+static int attach_xc5000(u8 addr, struct cx231xx *dev)
+{
+
+       struct dvb_frontend *fe;
+       struct xc5000_config cfg;
+
+       memset(&cfg, 0, sizeof(cfg));
+       cfg.i2c_adap  = &dev->i2c_bus[1].i2c_adap;
+       cfg.i2c_addr  = addr;
+
+       if (!dev->dvb->frontend) {
+               printk(KERN_ERR "%s/2: dvb frontend not attached. "
+                               "Can't attach xc5000\n",
+                      dev->name);
+               return -EINVAL;
+       }
+
+       fe = dvb_attach(xc5000_attach, dev->dvb->frontend, &cfg);
+       if (!fe) {
+               printk(KERN_ERR "%s/2: xc5000 attach failed\n", dev->name);
+               dvb_frontend_detach(dev->dvb->frontend);
+               dev->dvb->frontend = NULL;
+               return -EINVAL;
+       }
+
+       printk(KERN_INFO "%s/2: xc5000 attached\n", dev->name);
+
+       return 0;
+}
+#endif
+
+int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq )
+{
+       int status = 0;
+
+       if( (dev->dvb != NULL) && (dev->dvb->frontend != NULL) ){
+
+                       struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops;
+
+                   if(dops->set_analog_params != NULL) {
+                                struct analog_parameters params;
+
+                                params.frequency = freq;
+                                params.std = dev->norm;
+                                params.mode = 0 ; /* 0- Air; 1 - cable */
+                                /*params.audmode = ;       */
+
+                                /* Set the analog parameters to set the frequency */
+                                cx231xx_info("Setting Frequency for XC5000\n");
+                                dops->set_analog_params(dev->dvb->frontend, &params);
+                       }
+
+               }
+
+       return status;
+}
+
+int cx231xx_reset_analog_tuner(struct cx231xx *dev)
+{
+    int status = 0;
+
+       if( (dev->dvb != NULL) && (dev->dvb->frontend != NULL) ){
+
+                       struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops;
+
+                   if(dops->init != NULL && !dev->xc_fw_load_done) {
+
+                                cx231xx_info("Reloading firmware for XC5000\n");
+                                status = dops->init(dev->dvb->frontend);
+                 if(status == 0 ) {
+                    dev->xc_fw_load_done = 1;
+                    cx231xx_info("XC5000 firmware download completed\n");
+                 } else {
+                     dev->xc_fw_load_done = 0;
+                     cx231xx_info("XC5000 firmware download failed !!!\n");
+                 }
+                       }
+
+               }
+
+       return status;
+}
+
+
+/* ------------------------------------------------------------------ */
+
+static int register_dvb(struct cx231xx_dvb *dvb,
+                struct module *module,
+                struct cx231xx *dev,
+                struct device *device)
+{
+       int result;
+
+       mutex_init(&dvb->lock);
+
+       /* register adapter */
+       result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
+                                     adapter_nr);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_adapter;
+       }
+
+       /* Ensure all frontends negotiate bus access */
+       dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl;
+
+       dvb->adapter.priv = dev;
+
+       /* register frontend */
+       result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_frontend;
+       }
+
+       /* register demux stuff */
+       dvb->demux.dmx.capabilities =
+               DMX_TS_FILTERING | DMX_SECTION_FILTERING |
+               DMX_MEMORY_BASED_FILTERING;
+       dvb->demux.priv       = dvb;
+       dvb->demux.filternum  = 256;
+       dvb->demux.feednum    = 256;
+       dvb->demux.start_feed = start_feed;
+       dvb->demux.stop_feed  = stop_feed;
+
+       result = dvb_dmx_init(&dvb->demux);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_dmx;
+       }
+
+       dvb->dmxdev.filternum    = 256;
+       dvb->dmxdev.demux        = &dvb->demux.dmx;
+       dvb->dmxdev.capabilities = 0;
+       result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_dmxdev;
+       }
+
+       dvb->fe_hw.source = DMX_FRONTEND_0;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
+                      dev->name, result);
+               goto fail_fe_hw;
+       }
+
+       dvb->fe_mem.source = DMX_MEMORY_FE;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
+                      dev->name, result);
+               goto fail_fe_mem;
+       }
+
+       result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_fe_conn;
+       }
+
+       /* register network adapter */
+       dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
+       return 0;
+
+fail_fe_conn:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+fail_fe_mem:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+fail_fe_hw:
+       dvb_dmxdev_release(&dvb->dmxdev);
+fail_dmxdev:
+       dvb_dmx_release(&dvb->demux);
+fail_dmx:
+       dvb_unregister_frontend(dvb->frontend);
+fail_frontend:
+       dvb_frontend_detach(dvb->frontend);
+       dvb_unregister_adapter(&dvb->adapter);
+fail_adapter:
+       return result;
+}
+
+static void unregister_dvb(struct cx231xx_dvb *dvb)
+{
+       dvb_net_release(&dvb->net);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       dvb_dmxdev_release(&dvb->dmxdev);
+       dvb_dmx_release(&dvb->demux);
+       dvb_unregister_frontend(dvb->frontend);
+       dvb_frontend_detach(dvb->frontend);
+       dvb_unregister_adapter(&dvb->adapter);
+}
+
+
+static int dvb_init(struct cx231xx *dev)
+{
+       int result = 0;
+       struct cx231xx_dvb *dvb;
+
+       if (!dev->board.has_dvb) {
+               /* This device does not support the extension */
+               return 0;
+       }
+
+       dvb = kzalloc(sizeof(struct cx231xx_dvb), GFP_KERNEL);
+
+       if (dvb == NULL) {
+               printk(KERN_INFO "cx231xx_dvb: memory allocation failed\n");
+               return -ENOMEM;
+       }
+       dev->dvb = dvb;
+       dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq;
+    dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner;
+
+       cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
+       /* init frontend */
+       switch (dev->model) {
+        case CX231XX_BOARD_CNXT_RDE_250:
+
+           /* dev->dvb->frontend = dvb_attach(s5h1411_attach,
+                                                       &dvico_s5h1411_config,
+                                                       &dev->i2c_bus[1].i2c_adap);*/
+            dev->dvb->frontend = dvb_attach(dvb_dummy_fe_ofdm_attach);
+
+            if(dev->dvb->frontend == NULL) {
+                printk(DRIVER_NAME ": Failed to attach dummy front end\n");
+                result = -EINVAL;
+                           goto out_free;
+            }
+
+            /* define general-purpose callback pointer */
+               dvb->frontend->callback = cx231xx_tuner_callback;
+
+            if(dvb_attach(xc5000_attach, dev->dvb->frontend,
+                                  &dev->i2c_bus[1].i2c_adap,
+                                  &cnxt_rde250_tunerconfig) < 0) {
+                           result = -EINVAL;
+                           goto out_free;
+                   }
+
+            break;
+       case CX231XX_BOARD_CNXT_RDU_250:
+
+           dev->dvb->frontend = dvb_attach(dvb_dummy_fe_ofdm_attach);
+
+            if(dev->dvb->frontend == NULL) {
+                printk(DRIVER_NAME ": Failed to attach dummy front end\n");
+                result = -EINVAL;
+                           goto out_free;
+            }
+
+            /* define general-purpose callback pointer */
+               dvb->frontend->callback = cx231xx_tuner_callback;
+
+           if(dvb_attach(xc5000_attach, dev->dvb->frontend,
+                                  &dev->i2c_bus[1].i2c_adap,
+                                  &cnxt_rde250_tunerconfig) < 0) {
+                           result = -EINVAL;
+                           goto out_free;
+                   }
+           break;
+
+       default:
+               printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
+                               " isn't supported yet\n",
+                      dev->name);
+               break;
+       }
+       if (NULL == dvb->frontend) {
+               printk(KERN_ERR
+                      "%s/2: frontend initialization failed\n",
+                      dev->name);
+               result = -EINVAL;
+               goto out_free;
+       }
+
+
+       /* register everything */
+       result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
+
+       if (result < 0)
+               goto out_free;
+
+       cx231xx_set_mode(dev, CX231XX_SUSPEND);
+       printk(KERN_INFO "Successfully loaded cx231xx-dvb\n");
+       return 0;
+
+out_free:
+       cx231xx_set_mode(dev, CX231XX_SUSPEND);
+       kfree(dvb);
+       dev->dvb = NULL;
+       return result;
+}
+
+static int dvb_fini(struct cx231xx *dev)
+{
+       if (!dev->board.has_dvb) {
+               /* This device does not support the extension */
+               return 0;
+       }
+
+       if (dev->dvb) {
+               unregister_dvb(dev->dvb);
+               dev->dvb = NULL;
+       }
+
+       return 0;
+}
+
+static struct cx231xx_ops dvb_ops = {
+       .id   = CX231XX_DVB,
+       .name = "Cx231xx dvb Extension",
+       .init = dvb_init,
+       .fini = dvb_fini,
+};
+
+static int __init cx231xx_dvb_register(void)
+{
+       return cx231xx_register_extension(&dvb_ops);
+}
+
+static void __exit cx231xx_dvb_unregister(void)
+{
+       cx231xx_unregister_extension(&dvb_ops);
+}
+
+module_init(cx231xx_dvb_register);
+module_exit(cx231xx_dvb_unregister);
+
diff --git a/drivers/media/video/cx231xx/cx231xx-i2c.c b/drivers/media/video/cx231xx/cx231xx-i2c.c
new file mode 100644 (file)
index 0000000..d75ed6c
--- /dev/null
@@ -0,0 +1,577 @@
+/*
+   cx231xx-i2c.c - driver for Conexant Cx23100/101/102 USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+        Based on em28xx driver
+        Based on Cx23885 driver
+
+   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; either version 2 of the License, or
+   (at your option) any later version.
+
+   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 <media/v4l2-common.h>
+#include <media/tuner.h>
+
+#include "cx231xx.h"
+
+
+/* ----------------------------------------------------------- */
+
+static unsigned int i2c_scan;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+static unsigned int i2c_debug;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+
+#define dprintk1(lvl, fmt, args...)                    \
+do {                                                   \
+       if (i2c_debug >= lvl) {                         \
+       printk(fmt, ##args);                            \
+      }                                                        \
+} while (0)
+
+#define dprintk2(lvl, fmt, args...)                    \
+do {                                                   \
+       if (i2c_debug >= lvl) {                         \
+               printk(KERN_DEBUG "%s at %s: " fmt,     \
+                      dev->name, __func__ , ##args);   \
+      }                                                \
+} while (0)
+
+
+/*
+ * cx231xx_i2c_send_bytes()
+ */
+int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap,
+                        const struct i2c_msg *msg)
+{
+       struct cx231xx_i2c *bus = i2c_adap->algo_data;
+       struct cx231xx *dev = bus->dev;
+    struct cx231xx_i2c_xfer_data req_data;
+    int status = 0;
+    u16 size = 0;
+    u8 loop = 0;
+    u8 saddr_len = 1;
+    u8 *buf_ptr = NULL;
+    u16 saddr = 0;
+    u8 need_gpio = 0;
+
+
+    if( (bus->nr ==1) && (msg->addr == 0x61) && (dev->tuner_type == TUNER_XC5000) ) {
+
+        size = msg->len;
+
+        if( size == 2 ) { /* register write sub addr*/
+
+            /* Just writing sub address will cause problem to XC5000
+               So ignore the request */
+            return 0;
+
+        } else if( size == 4 ) { /* register write with sub addr*/
+
+            if(msg->len >= 2 )
+                saddr = msg->buf[0] << 8 | msg->buf[1];
+            else if ( msg->len == 1 )
+                saddr = msg->buf[0];
+
+            switch(saddr) {
+                case 0x0000:    /* start tuner calibration mode */
+                    need_gpio = 1;
+                    dev->xc_fw_load_done = 1; /* FW Loading is done */
+                    break;
+                case 0x000D:    /* Set signal source */
+                case 0x0001:    /* Set TV standard - Video */
+                case 0x0002:    /* Set TV standard - Audio */
+                case 0x0003:    /* Set RF Frequency */
+                    need_gpio = 1;
+                    break;
+                default:
+                    if(dev->xc_fw_load_done)
+                        need_gpio = 1;
+                    break;
+            }
+
+            if(need_gpio ) {
+                dprintk1(1, " GPIO W R I T E : addr 0x%x, len %d, saddr 0x%x\n",
+                    msg->addr, msg->len,  saddr);
+
+                return dev->cx231xx_gpio_i2c_write(dev, msg->addr, msg->buf, msg->len);
+            }
+
+        }
+
+        /* special case for Xc5000 tuner case */
+        saddr_len = 1;
+
+        /* adjust the length to correct length */
+        size -= saddr_len;
+        buf_ptr = (u8*) (msg->buf + 1 );
+
+        do {
+            /* prepare xfer_data struct */
+            req_data.dev_addr = msg->addr;
+            req_data.direction = msg->flags;
+            req_data.saddr_len = saddr_len;
+            req_data.saddr_dat = msg->buf[0];
+            req_data.buf_size =  size > 16 ? 16: size;
+            req_data.p_buffer = (u8*)(buf_ptr + loop * 16);
+
+            bus->i2c_nostop =  (size > 16) ? 1: 0;
+            bus->i2c_reserve = (loop == 0) ? 0: 1;
+
+            /* usb send command */
+            status = dev->cx231xx_send_usb_command(bus, &req_data);
+            loop++;
+
+            if( size >= 16 )
+                size -=  16;
+            else
+                size = 0;
+
+        }while( size > 0 );
+
+        bus->i2c_nostop =  0;
+        bus->i2c_reserve = 0;
+
+    } else { /* regular case */
+
+        /* prepare xfer_data struct */
+        req_data.dev_addr = msg->addr;
+        req_data.direction = msg->flags;
+        req_data.saddr_len = 0;
+        req_data.saddr_dat = 0;
+        req_data.buf_size = msg->len;
+        req_data.p_buffer = msg->buf;
+
+        /* usb send command */
+        status = dev->cx231xx_send_usb_command(bus, &req_data);
+    }
+
+    return status < 0 ? status: 0;
+}
+
+/*
+ * cx231xx_i2c_recv_bytes()
+ * read a byte from the i2c device
+ */
+static int cx231xx_i2c_recv_bytes(struct i2c_adapter *i2c_adap,
+                        const struct i2c_msg *msg)
+{
+    struct cx231xx_i2c *bus = i2c_adap->algo_data;
+       struct cx231xx *dev = bus->dev;
+    struct cx231xx_i2c_xfer_data req_data;
+    int status = 0;
+    u16 saddr = 0;
+    u8 need_gpio = 0;
+
+    if((bus->nr ==1) && (msg->addr == 0x61) && dev->tuner_type == TUNER_XC5000) {
+
+        if(msg->len == 2 )
+            saddr = msg->buf[0] << 8 | msg->buf[1];
+        else if ( msg->len == 1 )
+            saddr = msg->buf[0];
+
+        if( dev->xc_fw_load_done) {
+
+            switch(saddr) {
+                case 0x0009:    /* BUSY check */
+                    dprintk1(1, " GPIO R E A D : Special case BUSY check \n");
+                    /* Try to read BUSY register, just set it to zero */
+                    msg->buf[0] = 0;
+                    if(msg->len == 2 )
+                        msg->buf[1] = 0;
+                    return 0;
+                case 0x0004:    /* read Lock status */
+                    need_gpio = 1;
+                    break;
+
+            }
+
+            if(need_gpio) {
+                /* this is a special case to handle Xceive tuner clock stretch issue
+                   with gpio based I2C interface */
+                dprintk1(1, " GPIO R E A D : addr 0x%x, len %d, saddr 0x%x\n",
+                    msg->addr, msg->len, msg->buf[0] << 8| msg->buf[1]);
+                status = dev->cx231xx_gpio_i2c_write(dev, msg->addr, msg->buf, msg->len);
+                status = dev->cx231xx_gpio_i2c_read(dev, msg->addr, msg->buf, msg->len);
+                return status;
+            }
+        }
+
+         /* prepare xfer_data struct */
+        req_data.dev_addr = msg->addr;
+        req_data.direction = msg->flags;
+        req_data.saddr_len = msg->len;
+        req_data.saddr_dat = msg->buf[0] << 8 | msg->buf[1];
+        req_data.buf_size = msg->len;
+        req_data.p_buffer = msg->buf;
+
+        /* usb send command */
+        status = dev->cx231xx_send_usb_command(bus, &req_data);
+
+    } else {
+
+        /* prepare xfer_data struct */
+        req_data.dev_addr = msg->addr;
+        req_data.direction = msg->flags;
+        req_data.saddr_len = 0;
+        req_data.saddr_dat = 0;
+        req_data.buf_size = msg->len;
+        req_data.p_buffer = msg->buf;
+
+        /* usb send command */
+        status = dev->cx231xx_send_usb_command(bus, &req_data);
+    }
+
+    return status < 0 ? status: 0;
+}
+
+/*
+ * cx231xx_i2c_recv_bytes_with_saddr()
+ * read a byte from the i2c device
+ */
+static int cx231xx_i2c_recv_bytes_with_saddr(struct i2c_adapter *i2c_adap,
+                        const struct i2c_msg *msg1, const struct i2c_msg *msg2)
+{
+    struct cx231xx_i2c *bus = i2c_adap->algo_data;
+       struct cx231xx *dev = bus->dev;
+    struct cx231xx_i2c_xfer_data req_data;
+    int status = 0;
+    u16 saddr = 0;
+    u8 need_gpio = 0;
+
+    if(msg1->len == 2 )
+        saddr = msg1->buf[0] << 8 | msg1->buf[1];
+    else if ( msg1->len == 1 )
+        saddr = msg1->buf[0];
+
+    if ( (bus->nr ==1) && (msg2->addr == 0x61) &&  dev->tuner_type == TUNER_XC5000) {
+
+        if( (msg2->len < 16) ) {
+
+            dprintk1(1, " i2c_read : addr 0x%x, len %d, subaddr 0x%x, leng %d\n",
+                msg2->addr, msg2->len, saddr, msg1->len);
+
+            switch(saddr) {
+                case 0x0008:    /* read FW load status */
+                    need_gpio = 1;
+                    break;
+                case 0x0004:    /* read Lock status */
+                    need_gpio = 1;
+                    break;
+            }
+
+            if(need_gpio ) {
+                status = dev->cx231xx_gpio_i2c_write(dev, msg1->addr, msg1->buf, msg1->len);
+                status = dev->cx231xx_gpio_i2c_read(dev, msg2->addr, msg2->buf, msg2->len);
+                return status;
+            }
+        }
+    }
+
+    /* prepare xfer_data struct */
+    req_data.dev_addr = msg2->addr;
+    req_data.direction = msg2->flags;
+    req_data.saddr_len = msg1->len;
+    req_data.saddr_dat = saddr;
+    req_data.buf_size = msg2->len;
+    req_data.p_buffer = msg2->buf;
+
+    /* usb send command */
+    status = dev->cx231xx_send_usb_command(bus, &req_data);
+
+    return status < 0 ? status: 0;
+}
+
+/*
+ * cx231xx_i2c_check_for_device()
+ * check if there is a i2c_device at the supplied address
+ */
+static int cx231xx_i2c_check_for_device(struct i2c_adapter *i2c_adap,
+                        const struct i2c_msg *msg)
+{
+    struct cx231xx_i2c *bus = i2c_adap->algo_data;
+       struct cx231xx *dev = bus->dev;
+    struct cx231xx_i2c_xfer_data req_data;
+    int status = 0;
+
+    /* prepare xfer_data struct */
+    req_data.dev_addr = msg->addr;
+    req_data.direction = msg->flags;
+    req_data.saddr_len = 0;
+    req_data.saddr_dat = 0;
+    req_data.buf_size = 0;
+    req_data.p_buffer = NULL;
+
+    /* usb send command */
+    status = dev->cx231xx_send_usb_command(bus, &req_data);
+
+    return status < 0 ? status: 0;
+}
+
+/*
+ * cx231xx_i2c_xfer()
+ * the main i2c transfer function
+ */
+static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap,
+                          struct i2c_msg msgs[], int num)
+{
+       struct cx231xx_i2c *bus = i2c_adap->algo_data;
+       struct cx231xx *dev = bus->dev;
+       int addr, rc, i, byte;
+
+       if (num <= 0)
+               return 0;
+
+       for (i = 0; i < num; i++) {
+
+               addr = msgs[i].addr >> 1;
+
+               dprintk2(2, "%s %s addr=%x len=%d:",
+                        (msgs[i].flags & I2C_M_RD) ? "read" : "write",
+                        i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
+               if (!msgs[i].len) { /* no len: check only for device presence */
+                       rc = cx231xx_i2c_check_for_device(i2c_adap, &msgs[i]);
+                       if (rc < 0) {
+                               dprintk2(2, " no device\n");
+                               return rc;
+                       }
+
+               } else if (msgs[i].flags & I2C_M_RD) {
+                       /* read bytes */
+                       rc = cx231xx_i2c_recv_bytes(i2c_adap, &msgs[i]);
+                       if (i2c_debug >= 2) {
+                               for (byte = 0; byte < msgs[i].len; byte++)
+                                       printk(" %02x", msgs[i].buf[byte]);
+                       }
+               } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
+                          msgs[i].addr == msgs[i + 1].addr  && (msgs[i].len <= 2) && (bus->nr < 2)) {
+                       /* read bytes */
+                       rc = cx231xx_i2c_recv_bytes_with_saddr(i2c_adap, &msgs[i], &msgs[i+1]);
+                       if (i2c_debug >= 2) {
+                               for (byte = 0; byte < msgs[i].len; byte++)
+                                       printk(" %02x", msgs[i].buf[byte]);
+                       }
+            i++;
+               } else {
+                       /* write bytes */
+                       if (i2c_debug >= 2) {
+                               for (byte = 0; byte < msgs[i].len; byte++)
+                                       printk(" %02x", msgs[i].buf[byte]);
+                       }
+                       rc = cx231xx_i2c_send_bytes(i2c_adap,&msgs[i]);
+               }
+               if (rc < 0)
+                       goto err;
+               if (i2c_debug >= 2)
+                       printk("\n");
+       }
+
+       return num;
+err:
+       dprintk2(2, " ERROR: %i\n", rc);
+       return rc;
+}
+
+/* ----------------------------------------------------------- */
+
+/*
+ * functionality()
+ */
+static u32 functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
+}
+
+/*
+ * attach_inform()
+ * gets called when a device attaches to the i2c bus
+ * does some basic configuration
+ */
+static int attach_inform(struct i2c_client *client)
+{
+    struct cx231xx_i2c *bus = i2c_get_adapdata(client->adapter);
+       struct cx231xx *dev = bus->dev;
+
+       switch (client->addr << 1) {
+       case 0x32:
+               dprintk1(1, "attach_inform: Geminit III detected.\n");
+               break;
+       case 0x02:
+               dprintk1(1, "attach_inform: Acquarius detected.\n");
+               break;
+       case 0xa0:
+               dprintk1(1, "attach_inform: eeprom detected.\n");
+               break;
+       case 0x60:
+        dprintk1(1, "attach_inform: Colibri detected.\n");
+        break;
+       case 0x8e:
+       {
+               struct IR_i2c *ir = i2c_get_clientdata(client);
+               dprintk1(1, "attach_inform: IR detected (%s).\n",
+                       ir->phys);
+               cx231xx_set_ir(dev, ir);
+               break;
+       }
+       case 0x80:
+       case 0x88:
+               dprintk1(1, "attach_inform: Hammerhead detected.\n");
+               break;
+
+       default:
+               if (!dev->tuner_addr)
+                       dev->tuner_addr = client->addr;
+
+               dprintk1(1, "attach inform: detected I2C address %x\n",
+                               client->addr << 1);
+       }
+
+       return 0;
+}
+
+static int detach_inform(struct i2c_client *client)
+{
+       dprintk1(1, "i2c detach [client=%s]\n", client->name);
+       return 0;
+}
+
+
+static struct i2c_algorithm cx231xx_algo = {
+       .master_xfer   = cx231xx_i2c_xfer,
+       .functionality = functionality,
+};
+
+static struct i2c_adapter cx231xx_adap_template = {
+       .owner = THIS_MODULE,
+       .class = I2C_CLASS_TV_ANALOG,
+       .name = "cx231xx",
+       .id = I2C_HW_B_CX231XX,
+       .algo = &cx231xx_algo,
+       .client_register   = attach_inform,
+       .client_unregister = detach_inform,
+};
+
+static struct i2c_client cx231xx_client_template = {
+       .name = "cx231xx internal",
+};
+
+/* ----------------------------------------------------------- */
+
+/*
+ * i2c_devs
+ * incomplete list of known devices
+ */
+static char *i2c_devs[128] = {
+       [0x60 >> 1] = "colibri",
+       [0x88 >> 1] = "hammerhead",
+    [0x8e >> 1] = "CIR",
+       [0x32 >> 1] = "GeminiIII",
+    [0x02 >> 1] = "Aquarius",
+       [0xa0 >> 1] = "eeprom",
+       [0xc0 >> 1] = "tuner/XC3028",
+       [0xc2 >> 1] = "tuner/XC5000",
+};
+
+/*
+ * cx231xx_do_i2c_scan()
+ * check i2c address range for devices
+ */
+void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c)
+{
+       unsigned char buf;
+       int i, rc;
+
+    cx231xx_info(": Checking for I2C devices ..\n");
+       for (i = 0; i < 128; i++) {
+               c->addr = i;
+               rc = i2c_master_recv(c, &buf, 0);
+               if (rc < 0)
+                       continue;
+               cx231xx_info("%s: i2c scan: found device @ 0x%x  [%s]\n",
+                      dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+       }
+    cx231xx_info(": Completed Checking for I2C devices.\n");
+}
+
+/*
+ * cx231xx_i2c_call_clients()
+ * send commands to all attached i2c devices
+ */
+void cx231xx_i2c_call_clients(struct cx231xx_i2c *bus, unsigned int cmd, void *arg)
+{
+       /* struct cx231xx *dev = bus->dev; */
+
+       BUG_ON(NULL == bus->i2c_adap.algo_data);
+       i2c_clients_command(&bus->i2c_adap, cmd, arg);
+}
+
+/*
+ * cx231xx_i2c_register()
+ * register i2c bus
+ */
+int cx231xx_i2c_register(struct cx231xx_i2c *bus)
+{
+    struct cx231xx *dev = bus->dev;
+
+    BUG_ON(!dev->cx231xx_send_usb_command);
+
+    cx231xx_info("%s(bus = %d)\n", __func__, bus->nr);
+
+       memcpy(&bus->i2c_adap, &cx231xx_adap_template,
+              sizeof(bus->i2c_adap));
+       memcpy(&bus->i2c_algo, &cx231xx_algo,
+              sizeof(bus->i2c_algo));
+       memcpy(&bus->i2c_client, &cx231xx_client_template,
+              sizeof(bus->i2c_client));
+
+       bus->i2c_adap.dev.parent = &dev->udev->dev;
+
+       strlcpy(bus->i2c_adap.name, bus->dev->name,
+               sizeof(bus->i2c_adap.name));
+
+       bus->i2c_algo.data = bus;
+       bus->i2c_adap.algo_data = bus;
+       i2c_set_adapdata(&bus->i2c_adap, bus);
+       i2c_add_adapter(&bus->i2c_adap);
+
+       bus->i2c_client.adapter = &bus->i2c_adap;
+
+       if (0 == bus->i2c_rc) {
+               cx231xx_info("%s: i2c bus %d registered\n", dev->name, bus->nr);
+               if (i2c_scan)
+                       cx231xx_do_i2c_scan(dev, &bus->i2c_client);
+       } else
+               cx231xx_warn("%s: i2c bus %d register FAILED\n",
+                       dev->name, bus->nr);
+
+       return bus->i2c_rc;
+}
+
+/*
+ * cx231xx_i2c_unregister()
+ * unregister i2c_bus
+ */
+int cx231xx_i2c_unregister(struct cx231xx_i2c *bus)
+{
+       i2c_del_adapter(&bus->i2c_adap);
+       return 0;
+}
diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c
new file mode 100644 (file)
index 0000000..fdc37a8
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+  handle cx231xx IR remotes via linux kernel input layer.
+
+  Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+        Based on em28xx driver
+
+        < This is a place holder for IR now.>
+
+  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; either version 2 of the License, or
+  (at your option) any later version.
+
+  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+
+#include "cx231xx.h"
+
+
+static unsigned int ir_debug;
+module_param(ir_debug, int, 0644);
+MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
+
+#define i2cdprintk(fmt, arg...) \
+       if (ir_debug) { \
+               printk(KERN_DEBUG "%s/ir: " fmt, ir->c.name , ## arg); \
+       }
+
+#define dprintk(fmt, arg...) \
+       if (ir_debug) { \
+               printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
+       }
+
+/**********************************************************
+ Polling structure used by cx231xx IR's
+ **********************************************************/
+
+struct cx231xx_ir_poll_result {
+       unsigned int toggle_bit:1;
+       unsigned int read_count:7;
+       u8 rc_address;
+       u8 rc_data[4];
+};
+
+struct cx231xx_IR {
+       struct cx231xx *dev;
+       struct input_dev *input;
+       struct ir_input_state ir;
+       char name[32];
+       char phys[32];
+
+       /* poll external decoder */
+       int polling;
+       struct work_struct work;
+       struct timer_list timer;
+       unsigned int last_toggle:1;
+       unsigned int last_readcount;
+       unsigned int repeat_interval;
+
+       int  (*get_key)(struct cx231xx_IR *, struct cx231xx_ir_poll_result *);
+};
+
+
+
+/**********************************************************
+ Polling code for cx231xx
+ **********************************************************/
+
+static void cx231xx_ir_handle_key(struct cx231xx_IR *ir)
+{
+       int result;
+       int do_sendkey = 0;
+       struct cx231xx_ir_poll_result poll_result;
+
+       /* read the registers containing the IR status */
+       result = ir->get_key(ir, &poll_result);
+       if (result < 0) {
+               dprintk("ir->get_key() failed %d\n", result);
+               return;
+       }
+
+       dprintk("ir->get_key result tb=%02x rc=%02x lr=%02x data=%02x\n",
+               poll_result.toggle_bit, poll_result.read_count,
+               ir->last_readcount, poll_result.rc_data[0]);
+
+       if (ir->dev->chip_id == CHIP_ID_EM2874) {
+               /* The em2874 clears the readcount field every time the
+                  register is read.  The em2860/2880 datasheet says that it
+                  is supposed to clear the readcount, but it doesn't.  So with
+                  the em2874, we are looking for a non-zero read count as
+                  opposed to a readcount that is incrementing */
+               ir->last_readcount = 0;
+       }
+
+       if (poll_result.read_count == 0) {
+               /* The button has not been pressed since the last read */
+       } else if (ir->last_toggle != poll_result.toggle_bit) {
+               /* A button has been pressed */
+               dprintk("button has been pressed\n");
+               ir->last_toggle = poll_result.toggle_bit;
+               ir->repeat_interval = 0;
+               do_sendkey = 1;
+       } else if (poll_result.toggle_bit == ir->last_toggle &&
+                  poll_result.read_count > 0 &&
+                  poll_result.read_count != ir->last_readcount) {
+               /* The button is still being held down */
+               dprintk("button being held down\n");
+
+               /* Debouncer for first keypress */
+               if (ir->repeat_interval++ > 9) {
+                       /* Start repeating after 1 second */
+                       do_sendkey = 1;
+               }
+       }
+
+       if (do_sendkey) {
+               dprintk("sending keypress\n");
+               ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0],
+                                poll_result.rc_data[0]);
+               ir_input_nokey(ir->input, &ir->ir);
+       }
+
+       ir->last_readcount = poll_result.read_count;
+       return;
+}
+
+static void ir_timer(unsigned long data)
+{
+       struct cx231xx_IR *ir = (struct cx231xx_IR *)data;
+
+       schedule_work(&ir->work);
+}
+
+static void cx231xx_ir_work(struct work_struct *work)
+{
+       struct cx231xx_IR *ir = container_of(work, struct cx231xx_IR, work);
+
+       cx231xx_ir_handle_key(ir);
+       mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
+}
+
+void cx231xx_ir_start(struct cx231xx_IR *ir)
+{
+       setup_timer(&ir->timer, ir_timer, (unsigned long)ir);
+       INIT_WORK(&ir->work, cx231xx_ir_work);
+       schedule_work(&ir->work);
+}
+
+static void cx231xx_ir_stop(struct cx231xx_IR *ir)
+{
+       del_timer_sync(&ir->timer);
+       flush_scheduled_work();
+}
+
+int cx231xx_ir_init(struct cx231xx *dev)
+{
+       struct cx231xx_IR *ir;
+       struct input_dev *input_dev;
+       u8 ir_config;
+       int err = -ENOMEM;
+
+       if (dev->board.ir_codes == NULL) {
+               /* No remote control support */
+               return 0;
+       }
+
+       ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!ir || !input_dev)
+               goto err_out_free;
+
+       ir->input = input_dev;
+
+       /* Setup the proper handler based on the chip */
+       switch (dev->chip_id) {
+           default:
+                   printk("Unrecognized cx231xx chip id: IR not supported\n");
+                   goto err_out_free;
+       }
+
+       /* This is how often we ask the chip for IR information */
+       ir->polling = 100; /* ms */
+
+       /* init input device */
+       snprintf(ir->name, sizeof(ir->name), "cx231xx IR (%s)",
+                                               dev->name);
+
+       usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
+       strlcat(ir->phys, "/input0", sizeof(ir->phys));
+
+       ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER, dev->board.ir_codes);
+       input_dev->name = ir->name;
+       input_dev->phys = ir->phys;
+       input_dev->id.bustype = BUS_USB;
+       input_dev->id.version = 1;
+       input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
+       input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
+
+       input_dev->dev.parent = &dev->udev->dev;
+       /* record handles to ourself */
+       ir->dev = dev;
+       dev->ir = ir;
+
+       cx231xx_ir_start(ir);
+
+       /* all done */
+       err = input_register_device(ir->input);
+       if (err)
+               goto err_out_stop;
+
+       return 0;
+ err_out_stop:
+       cx231xx_ir_stop(ir);
+       dev->ir = NULL;
+ err_out_free:
+       input_free_device(input_dev);
+       kfree(ir);
+       return err;
+}
+
+int cx231xx_ir_fini(struct cx231xx *dev)
+{
+       struct cx231xx_IR *ir = dev->ir;
+
+       /* skip detach on non attached boards */
+       if (!ir)
+               return 0;
+
+       cx231xx_ir_stop(ir);
+       input_unregister_device(ir->input);
+       kfree(ir);
+
+       /* done */
+       dev->ir = NULL;
+       return 0;
+}
diff --git a/drivers/media/video/cx231xx/cx231xx-reg.h b/drivers/media/video/cx231xx/cx231xx-reg.h
new file mode 100644 (file)
index 0000000..ef24781
--- /dev/null
@@ -0,0 +1,1574 @@
+/*
+   cx231xx-reg.h - driver for Conexant Cx23100/101/102 USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot 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; either version 2 of the License, or
+   (at your option) any later version.
+
+   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.
+ */
+
+#ifndef _CX231XX_REG_H
+#define _CX231XX_REG_H
+
+/*****************************************************************************
+                    * VBI codes *
+*****************************************************************************/
+
+#define SAV_ACTIVE_VIDEO_FIELD1              0x80
+#define EAV_ACTIVE_VIDEO_FIELD1                  0x90
+
+#define SAV_ACTIVE_VIDEO_FIELD2                  0xC0
+#define EAV_ACTIVE_VIDEO_FIELD2                  0xD0
+
+#define SAV_VBLANK_FIELD1                    0xA0
+#define EAV_VBLANK_FIELD1                    0xB0
+
+#define SAV_VBLANK_FIELD2                    0xE0
+#define EAV_VBLANK_FIELD2                    0xF0
+
+#define SAV_VBI_FIELD1               0x20
+#define EAV_VBI_FIELD1               0x30
+
+#define SAV_VBI_FIELD2               0x60
+#define EAV_VBI_FIELD2               0x70
+
+/*****************************************************************************/
+/* Audio ADC Registers */
+#define CH_PWR_CTRL1                 0x0000000E
+#define CH_PWR_CTRL2                 0x0000000F
+/*****************************************************************************/
+
+#define      HOST_REG1                0x000
+#define      FLD_FORCE_CHIP_SEL       0x80
+#define      FLD_AUTO_INC_DIS         0x20
+#define      FLD_PREFETCH_EN          0x10
+/* Reserved [2:3] */
+#define      FLD_DIGITAL_PWR_DN       0x02
+#define      FLD_SLEEP                0x01
+
+/*****************************************************************************/
+#define      HOST_REG2                0x001
+
+
+/*****************************************************************************/
+#define      HOST_REG3                0x002
+
+/*****************************************************************************/
+/* added for polaris */
+#define      GPIO_PIN_CTL0            0x3
+#define      GPIO_PIN_CTL1            0x4
+#define      GPIO_PIN_CTL2            0x5
+#define      GPIO_PIN_CTL3            0x6
+#define      TS1_PIN_CTL0             0x7
+#define      TS1_PIN_CTL1             0x8
+/*****************************************************************************/
+
+#define      FLD_CLK_IN_EN           0x80
+#define      FLD_XTAL_CTRL           0x70
+#define      FLD_BB_CLK_MODE         0x0C
+#define      FLD_REF_DIV_PLL         0x02
+#define      FLD_REF_SEL_PLL1        0x01
+
+/*****************************************************************************/
+#define      CHIP_CTRL                0x100
+/* Reserved [27] */
+/* Reserved [31:21] */
+#define      FLD_CHIP_ACFG_DIS        0x00100000
+/* Reserved [19] */
+#define      FLD_DUAL_MODE_ADC2       0x00040000
+#define      FLD_SIF_EN               0x00020000
+#define      FLD_SOFT_RST             0x00010000
+#define      FLD_DEVICE_ID            0x0000FFFF
+
+/*****************************************************************************/
+#define      AFE_CTRL                 0x104
+#define      AFE_CTRL_C2HH_SRC_CTRL   0x104
+#define      FLD_DIF_OUT_SEL          0xC0000000
+#define      FLD_AUX_PLL_CLK_ALT_SEL  0x3C000000
+#define      FLD_UV_ORDER_MODE        0x02000000
+#define      FLD_FUNC_MODE            0x01800000
+#define      FLD_ROT1_PHASE_CTL       0x007F8000
+#define      FLD_AUD_IN_SEL           0x00004000
+#define      FLD_LUMA_IN_SEL          0x00002000
+#define      FLD_CHROMA_IN_SEL        0x00001000
+/* reserve [11:10] */
+#define      FLD_INV_SPEC_DIS         0x00000200
+#define      FLD_VGA_SEL_CH3          0x00000100
+#define      FLD_VGA_SEL_CH2          0x00000080
+#define      FLD_VGA_SEL_CH1          0x00000040
+#define      FLD_DCR_BYP_CH1          0x00000020
+#define      FLD_DCR_BYP_CH2          0x00000010
+#define      FLD_DCR_BYP_CH3          0x00000008
+#define      FLD_EN_12DB_CH3          0x00000004
+#define      FLD_EN_12DB_CH2          0x00000002
+#define      FLD_EN_12DB_CH1          0x00000001
+
+/* redefine in Cx231xx */
+/*****************************************************************************/
+#define      DC_CTRL1                 0x108
+/* reserve [31:30] */
+#define      FLD_CLAMP_LVL_CH1        0x3FFF8000
+#define      FLD_CLAMP_LVL_CH2        0x00007FFF
+/*****************************************************************************/
+
+/*****************************************************************************/
+#define      DC_CTRL2                 0x10c
+/* reserve [31:28] */
+#define      FLD_CLAMP_LVL_CH3        0x00FFFE00
+#define      FLD_CLAMP_WIND_LENTH     0x000001E0
+#define      FLD_C2HH_SAT_MIN         0x0000001E
+#define      FLD_FLT_BYP_SEL          0x00000001
+/*****************************************************************************/
+
+/*****************************************************************************/
+#define      DC_CTRL3                 0x110
+/* reserve [31:16] */
+#define      FLD_ERR_GAIN_CTL         0x00070000
+#define      FLD_LPF_MIN              0x0000FFFF
+/*****************************************************************************/
+
+/*****************************************************************************/
+#define      DC_CTRL4                 0x114
+/* reserve [31:31] */
+#define      FLD_INTG_CH1             0x7FFFFFFF
+/*****************************************************************************/
+
+/*****************************************************************************/
+#define      DC_CTRL5                 0x118
+/* reserve [31:31] */
+#define      FLD_INTG_CH2             0x7FFFFFFF
+/*****************************************************************************/
+
+/*****************************************************************************/
+#define      DC_CTRL6                 0x11c
+/* reserve [31:31] */
+#define      FLD_INTG_CH3             0x7FFFFFFF
+/*****************************************************************************/
+
+/*****************************************************************************/
+#define      PIN_CTRL                 0x120
+#define      FLD_OEF_AGC_RF           0x00000001
+#define      FLD_OEF_AGC_IFVGA        0x00000002
+#define      FLD_OEF_AGC_IF           0x00000004
+#define      FLD_REG_BO_PUD           0x80000000
+#define      FLD_IR_IRQ_STAT          0x40000000
+#define      FLD_AUD_IRQ_STAT         0x20000000
+#define      FLD_VID_IRQ_STAT         0x10000000
+/* Reserved [27:26] */
+#define      FLD_IRQ_N_OUT_EN         0x02000000
+#define      FLD_IRQ_N_POLAR          0x01000000
+/* Reserved [23:6] */
+#define      FLD_OE_AUX_PLL_CLK       0x00000020
+#define      FLD_OE_I2S_BCLK          0x00000010
+#define      FLD_OE_I2S_WCLK          0x00000008
+#define      FLD_OE_AGC_IF            0x00000004
+#define      FLD_OE_AGC_IFVGA         0x00000002
+#define      FLD_OE_AGC_RF            0x00000001
+
+/*****************************************************************************/
+#define      AUD_IO_CTRL              0x124
+/* Reserved [31:8] */
+#define      FLD_I2S_PORT_DIR         0x00000080
+#define      FLD_I2S_OUT_SRC          0x00000040
+#define      FLD_AUD_CHAN3_SRC        0x00000030
+#define      FLD_AUD_CHAN2_SRC        0x0000000C
+#define      FLD_AUD_CHAN1_SRC        0x00000003
+
+/*****************************************************************************/
+#define      AUD_LOCK1                0x128
+#define      FLD_AUD_LOCK_KI_SHIFT    0xC0000000
+#define      FLD_AUD_LOCK_KD_SHIFT    0x30000000
+/* Reserved [27:25] */
+#define      FLD_EN_AV_LOCK           0x01000000
+#define      FLD_VID_COUNT            0x00FFFFFF
+
+/*****************************************************************************/
+#define      AUD_LOCK2                0x12C
+#define      FLD_AUD_LOCK_KI_MULT     0xF0000000
+#define      FLD_AUD_LOCK_KD_MULT     0x0F000000
+/* Reserved [23:22] */
+#define      FLD_AUD_LOCK_FREQ_SHIFT  0x00300000
+#define      FLD_AUD_COUNT            0x000FFFFF
+
+/*****************************************************************************/
+#define      AFE_DIAG_CTRL1           0x134
+/* Reserved [31:16] */
+#define      FLD_CUV_DLY_LENGTH       0x0000FF00
+#define      FLD_YC_DLY_LENGTH        0x000000FF
+
+/*****************************************************************************/
+/* Poalris redefine */
+#define      AFE_DIAG_CTRL3           0x138
+/* Reserved [31:26] */
+#define      FLD_AUD_DUAL_FLAG_POL    0x02000000
+#define      FLD_VID_DUAL_FLAG_POL    0x01000000
+/* Reserved [23:23] */
+#define      FLD_COL_CLAMP_DIS_CH1    0x00400000
+#define      FLD_COL_CLAMP_DIS_CH2    0x00200000
+#define      FLD_COL_CLAMP_DIS_CH3    0x00100000
+
+#define      TEST_CTRL1                 0x144
+/* Reserved [31:29] */
+#define      FLD_LBIST_EN               0x10000000
+/* Reserved [27:10] */
+#define      FLD_FI_BIST_INTR_R         0x0000200
+#define      FLD_FI_BIST_INTR_L         0x0000100
+#define      FLD_BIST_FAIL_AUD_PLL      0x0000080
+#define      FLD_BIST_INTR_AUD_PLL      0x0000040
+#define      FLD_BIST_FAIL_VID_PLL      0x0000020
+#define      FLD_BIST_INTR_VID_PLL      0x0000010
+/* Reserved [3:1] */
+#define      FLD_CIR_TEST_DIS           0x00000001
+
+
+/*****************************************************************************/
+#define      TEST_CTRL2               0x148
+#define      FLD_TSXCLK_POL_CTL       0x80000000
+#define      FLD_ISO_CTL_SEL          0x40000000
+#define      FLD_ISO_CTL_EN           0x20000000
+#define      FLD_BIST_DEBUGZ          0x10000000
+#define      FLD_AUD_BIST_TEST_H      0x0F000000
+/* Reserved [23:22] */
+#define      FLD_FLTRN_BIST_TEST_H    0x00020000
+#define      FLD_VID_BIST_TEST_H      0x00010000
+/* Reserved [19:17] */
+#define      FLD_BIST_TEST_H          0x00010000
+/* Reserved [15:13] */
+#define      FLD_TAB_EN               0x00001000
+/* Reserved [11:0] */
+
+/*****************************************************************************/
+#define      BIST_STAT                0x14C
+#define      FLD_AUD_BIST_FAIL_H      0xFFF00000
+#define      FLD_FLTRN_BIST_FAIL_H    0x00180000
+#define      FLD_VID_BIST_FAIL_H      0x00070000
+#define      FLD_AUD_BIST_TST_DONE    0x0000FFF0
+#define      FLD_FLTRN_BIST_TST_DONE  0x00000008
+#define      FLD_VID_BIST_TST_DONE    0x00000007
+
+
+/*****************************************************************************/
+/* DirectIF registers definition have been moved to DIF_reg.h                */
+/*****************************************************************************/
+#define      MODE_CTRL                0x400
+#define      FLD_AFD_PAL60_DIS        0x20000000
+#define      FLD_AFD_FORCE_SECAM      0x10000000
+#define      FLD_AFD_FORCE_PALNC      0x08000000
+#define      FLD_AFD_FORCE_PAL        0x04000000
+#define      FLD_AFD_PALM_SEL         0x03000000
+#define      FLD_CKILL_MODE           0x00300000
+#define      FLD_COMB_NOTCH_MODE      0x00c00000       /* bit[19:18] */
+#define      FLD_CLR_LOCK_STAT        0x00020000
+#define      FLD_FAST_LOCK_MD         0x00010000
+#define      FLD_WCEN                 0x00008000
+#define      FLD_CAGCEN               0x00004000
+#define      FLD_CKILLEN              0x00002000
+#define      FLD_AUTO_SC_LOCK         0x00001000
+#define      FLD_MAN_SC_FAST_LOCK     0x00000800
+#define      FLD_INPUT_MODE           0x00000600
+#define      FLD_AFD_ACQUIRE          0x00000100
+#define      FLD_AFD_NTSC_SEL         0x00000080
+#define      FLD_AFD_PAL_SEL          0x00000040
+#define      FLD_ACFG_DIS             0x00000020
+#define      FLD_SQ_PIXEL             0x00000010
+#define      FLD_VID_FMT_SEL          0x0000000F
+
+/*****************************************************************************/
+#define      OUT_CTRL1                0x404
+#define      FLD_POLAR                0x7F000000
+/* Reserved [23] */
+#define      FLD_RND_MODE             0x00600000
+#define      FLD_VIPCLAMP_EN          0x00100000
+#define      FLD_VIPBLANK_EN          0x00080000
+#define      FLD_VIP_OPT_AL           0x00040000
+#define      FLD_IDID0_SOURCE         0x00020000
+#define      FLD_DCMODE               0x00010000
+#define      FLD_CLK_GATING           0x0000C000
+#define      FLD_CLK_INVERT           0x00002000
+#define      FLD_HSFMT                0x00001000
+#define      FLD_VALIDFMT             0x00000800
+#define      FLD_ACTFMT               0x00000400
+#define      FLD_SWAPRAW              0x00000200
+#define      FLD_CLAMPRAW_EN          0x00000100
+#define      FLD_BLUE_FIELD_EN        0x00000080
+#define      FLD_BLUE_FIELD_ACT       0x00000040
+#define      FLD_TASKBIT_VAL          0x00000020
+#define      FLD_ANC_DATA_EN          0x00000010
+#define      FLD_VBIHACTRAW_EN        0x00000008
+#define      FLD_MODE10B              0x00000004
+#define      FLD_OUT_MODE             0x00000003
+
+/*****************************************************************************/
+#define      OUT_CTRL2                0x408
+#define      FLD_AUD_GRP              0xC0000000
+#define      FLD_SAMPLE_RATE          0x30000000
+#define      FLD_AUD_ANC_EN           0x08000000
+#define      FLD_EN_C                 0x04000000
+#define      FLD_EN_B                 0x02000000
+#define      FLD_EN_A                 0x01000000
+/* Reserved [23:20] */
+#define      FLD_IDID1_LSB            0x000C0000
+#define      FLD_IDID0_LSB            0x00030000
+#define      FLD_IDID1_MSB            0x0000FF00
+#define      FLD_IDID0_MSB            0x000000FF
+
+/*****************************************************************************/
+#define      GEN_STAT                 0x40C
+#define      FLD_VCR_DETECT           0x00800000
+#define      FLD_SPECIAL_PLAY_N       0x00400000
+#define      FLD_VPRES                0x00200000
+#define      FLD_AGC_LOCK             0x00100000
+#define      FLD_CSC_LOCK             0x00080000
+#define      FLD_VLOCK                0x00040000
+#define      FLD_SRC_LOCK             0x00020000
+#define      FLD_HLOCK                0x00010000
+#define      FLD_VSYNC_N              0x00008000
+#define      FLD_SRC_FIFO_UFLOW       0x00004000
+#define      FLD_SRC_FIFO_OFLOW       0x00002000
+#define      FLD_FIELD                0x00001000
+#define      FLD_AFD_FMT_STAT         0x00000F00
+#define      FLD_MV_TYPE2_PAIR        0x00000080
+#define      FLD_MV_T3CS              0x00000040
+#define      FLD_MV_CS                0x00000020
+#define      FLD_MV_PSP               0x00000010
+/* Reserved [3] */
+#define      FLD_MV_CDAT              0x00000003
+
+/*****************************************************************************/
+#define      INT_STAT_MASK            0x410
+#define      FLD_COMB_3D_FIFO_MSK     0x80000000
+#define      FLD_WSS_DAT_AVAIL_MSK    0x40000000
+#define      FLD_GS2_DAT_AVAIL_MSK    0x20000000
+#define      FLD_GS1_DAT_AVAIL_MSK    0x10000000
+#define      FLD_CC_DAT_AVAIL_MSK     0x08000000
+#define      FLD_VPRES_CHANGE_MSK     0x04000000
+#define      FLD_MV_CHANGE_MSK        0x02000000
+#define      FLD_END_VBI_EVEN_MSK     0x01000000
+#define      FLD_END_VBI_ODD_MSK      0x00800000
+#define      FLD_FMT_CHANGE_MSK       0x00400000
+#define      FLD_VSYNC_TRAIL_MSK      0x00200000
+#define      FLD_HLOCK_CHANGE_MSK     0x00100000
+#define      FLD_VLOCK_CHANGE_MSK     0x00080000
+#define      FLD_CSC_LOCK_CHANGE_MSK  0x00040000
+#define      FLD_SRC_FIFO_UFLOW_MSK   0x00020000
+#define      FLD_SRC_FIFO_OFLOW_MSK   0x00010000
+#define      FLD_COMB_3D_FIFO_STAT    0x00008000
+#define      FLD_WSS_DAT_AVAIL_STAT   0x00004000
+#define      FLD_GS2_DAT_AVAIL_STAT   0x00002000
+#define      FLD_GS1_DAT_AVAIL_STAT   0x00001000
+#define      FLD_CC_DAT_AVAIL_STAT    0x00000800
+#define      FLD_VPRES_CHANGE_STAT    0x00000400
+#define      FLD_MV_CHANGE_STAT       0x00000200
+#define      FLD_END_VBI_EVEN_STAT    0x00000100
+#define      FLD_END_VBI_ODD_STAT     0x00000080
+#define      FLD_FMT_CHANGE_STAT      0x00000040
+#define      FLD_VSYNC_TRAIL_STAT     0x00000020
+#define      FLD_HLOCK_CHANGE_STAT    0x00000010
+#define      FLD_VLOCK_CHANGE_STAT    0x00000008
+#define      FLD_CSC_LOCK_CHANGE_STAT 0x00000004
+#define      FLD_SRC_FIFO_UFLOW_STAT  0x00000002
+#define      FLD_SRC_FIFO_OFLOW_STAT  0x00000001
+
+/*****************************************************************************/
+#define      LUMA_CTRL                0x414
+#define      BRIGHTNESS_CTRL_BYTE     0x414
+#define      CONTRAST_CTRL_BYTE       0x415
+#define      LUMA_CTRL_BYTE_3         0x416
+#define      FLD_LUMA_CORE_SEL        0x00C00000
+#define      FLD_RANGE                0x00300000
+/* Reserved [19] */
+#define      FLD_PEAK_EN              0x00040000
+#define      FLD_PEAK_SEL             0x00030000
+#define      FLD_CNTRST               0x0000FF00
+#define      FLD_BRITE                0x000000FF
+
+/*****************************************************************************/
+#define      HSCALE_CTRL              0x418
+#define      FLD_HFILT                0x03000000
+#define      FLD_HSCALE               0x00FFFFFF
+
+/*****************************************************************************/
+#define      VSCALE_CTRL              0x41C
+#define      FLD_LINE_AVG_DIS         0x01000000
+/* Reserved [23:20] */
+#define      FLD_VS_INTRLACE          0x00080000
+#define      FLD_VFILT                0x00070000
+/* Reserved [15:13] */
+#define      FLD_VSCALE               0x00001FFF
+
+/*****************************************************************************/
+#define      CHROMA_CTRL              0x420
+#define      USAT_CTRL_BYTE           0x420
+#define      VSAT_CTRL_BYTE           0x421
+#define      HUE_CTRL_BYTE            0x422
+#define      FLD_C_LPF_EN             0x20000000
+#define      FLD_CHR_DELAY            0x1C000000
+#define      FLD_C_CORE_SEL           0x03000000
+#define      FLD_HUE                  0x00FF0000
+#define      FLD_VSAT                 0x0000FF00
+#define      FLD_USAT                 0x000000FF
+
+/*****************************************************************************/
+#define      VBI_LINE_CTRL1           0x424
+#define      FLD_VBI_MD_LINE4         0xFF000000
+#define      FLD_VBI_MD_LINE3         0x00FF0000
+#define      FLD_VBI_MD_LINE2         0x0000FF00
+#define      FLD_VBI_MD_LINE1         0x000000FF
+
+/*****************************************************************************/
+#define      VBI_LINE_CTRL2           0x428
+#define      FLD_VBI_MD_LINE8         0xFF000000
+#define      FLD_VBI_MD_LINE7         0x00FF0000
+#define      FLD_VBI_MD_LINE6         0x0000FF00
+#define      FLD_VBI_MD_LINE5         0x000000FF
+
+/*****************************************************************************/
+#define      VBI_LINE_CTRL3           0x42C
+#define      FLD_VBI_MD_LINE12        0xFF000000
+#define      FLD_VBI_MD_LINE11        0x00FF0000
+#define      FLD_VBI_MD_LINE10        0x0000FF00
+#define      FLD_VBI_MD_LINE9         0x000000FF
+
+/*****************************************************************************/
+#define      VBI_LINE_CTRL4           0x430
+#define      FLD_VBI_MD_LINE16        0xFF000000
+#define      FLD_VBI_MD_LINE15        0x00FF0000
+#define      FLD_VBI_MD_LINE14        0x0000FF00
+#define      FLD_VBI_MD_LINE13        0x000000FF
+
+/*****************************************************************************/
+#define      VBI_LINE_CTRL5           0x434
+#define      FLD_VBI_MD_LINE17        0x000000FF
+
+/*****************************************************************************/
+#define      VBI_FC_CFG               0x438
+#define      FLD_FC_ALT2              0xFF000000
+#define      FLD_FC_ALT1              0x00FF0000
+#define      FLD_FC_ALT2_TYPE         0x0000F000
+#define      FLD_FC_ALT1_TYPE         0x00000F00
+/* Reserved [7:1] */
+#define      FLD_FC_SEARCH_MODE       0x00000001
+
+/*****************************************************************************/
+#define      VBI_MISC_CFG1            0x43C
+#define      FLD_TTX_PKTADRU          0xFFF00000
+#define      FLD_TTX_PKTADRL          0x000FFF00
+/* Reserved [7:6] */
+#define      FLD_MOJI_PACK_DIS        0x00000020
+#define      FLD_VPS_DEC_DIS          0x00000010
+#define      FLD_CRI_MARG_SCALE       0x0000000C
+#define      FLD_EDGE_RESYNC_EN       0x00000002
+#define      FLD_ADAPT_SLICE_DIS      0x00000001
+
+/*****************************************************************************/
+#define      VBI_MISC_CFG2            0x440
+#define      FLD_HAMMING_TYPE         0x0F000000
+/* Reserved [23:20] */
+#define      FLD_WSS_FIFO_RST         0x00080000
+#define      FLD_GS2_FIFO_RST         0x00040000
+#define      FLD_GS1_FIFO_RST         0x00020000
+#define      FLD_CC_FIFO_RST          0x00010000
+/* Reserved [15:12] */
+#define      FLD_VBI3_SDID            0x00000F00
+#define      FLD_VBI2_SDID            0x000000F0
+#define      FLD_VBI1_SDID            0x0000000F
+
+/*****************************************************************************/
+#define      VBI_PAY1                 0x444
+#define      FLD_GS1_FIFO_DAT         0xFF000000
+#define      FLD_GS1_STAT             0x00FF0000
+#define      FLD_CC_FIFO_DAT          0x0000FF00
+#define      FLD_CC_STAT              0x000000FF
+
+/*****************************************************************************/
+#define      VBI_PAY2                 0x448
+#define      FLD_WSS_FIFO_DAT         0xFF000000
+#define      FLD_WSS_STAT             0x00FF0000
+#define      FLD_GS2_FIFO_DAT         0x0000FF00
+#define      FLD_GS2_STAT             0x000000FF
+
+/*****************************************************************************/
+#define      VBI_CUST1_CFG1           0x44C
+/* Reserved [31] */
+#define      FLD_VBI1_CRIWIN          0x7F000000
+#define      FLD_VBI1_SLICE_DIST      0x00F00000
+#define      FLD_VBI1_BITINC          0x000FFF00
+#define      FLD_VBI1_HDELAY          0x000000FF
+
+/*****************************************************************************/
+#define      VBI_CUST1_CFG2           0x450
+#define      FLD_VBI1_FC_LENGTH       0x1F000000
+#define      FLD_VBI1_FRAME_CODE      0x00FFFFFF
+
+/*****************************************************************************/
+#define      VBI_CUST1_CFG3           0x454
+#define      FLD_VBI1_HAM_EN          0x80000000
+#define      FLD_VBI1_FIFO_MODE       0x70000000
+#define      FLD_VBI1_FORMAT_TYPE     0x0F000000
+#define      FLD_VBI1_PAYLD_LENGTH    0x00FF0000
+#define      FLD_VBI1_CRI_LENGTH      0x0000F000
+#define      FLD_VBI1_CRI_MARGIN      0x00000F00
+#define      FLD_VBI1_CRI_TIME        0x000000FF
+
+/*****************************************************************************/
+#define      VBI_CUST2_CFG1           0x458
+/* Reserved [31] */
+#define      FLD_VBI2_CRIWIN          0x7F000000
+#define      FLD_VBI2_SLICE_DIST      0x00F00000
+#define      FLD_VBI2_BITINC          0x000FFF00
+#define      FLD_VBI2_HDELAY          0x000000FF
+
+/*****************************************************************************/
+#define      VBI_CUST2_CFG2           0x45C
+#define      FLD_VBI2_FC_LENGTH       0x1F000000
+#define      FLD_VBI2_FRAME_CODE      0x00FFFFFF
+
+/*****************************************************************************/
+#define      VBI_CUST2_CFG3           0x460
+#define      FLD_VBI2_HAM_EN          0x80000000
+#define      FLD_VBI2_FIFO_MODE       0x70000000
+#define      FLD_VBI2_FORMAT_TYPE     0x0F000000
+#define      FLD_VBI2_PAYLD_LENGTH    0x00FF0000
+#define      FLD_VBI2_CRI_LENGTH      0x0000F000
+#define      FLD_VBI2_CRI_MARGIN      0x00000F00
+#define      FLD_VBI2_CRI_TIME        0x000000FF
+
+/*****************************************************************************/
+#define      VBI_CUST3_CFG1           0x464
+/* Reserved [31] */
+#define      FLD_VBI3_CRIWIN          0x7F000000
+#define      FLD_VBI3_SLICE_DIST      0x00F00000
+#define      FLD_VBI3_BITINC          0x000FFF00
+#define      FLD_VBI3_HDELAY          0x000000FF
+
+/*****************************************************************************/
+#define      VBI_CUST3_CFG2           0x468
+#define      FLD_VBI3_FC_LENGTH       0x1F000000
+#define      FLD_VBI3_FRAME_CODE      0x00FFFFFF
+
+/*****************************************************************************/
+#define      VBI_CUST3_CFG3           0x46C
+#define      FLD_VBI3_HAM_EN          0x80000000
+#define      FLD_VBI3_FIFO_MODE       0x70000000
+#define      FLD_VBI3_FORMAT_TYPE     0x0F000000
+#define      FLD_VBI3_PAYLD_LENGTH    0x00FF0000
+#define      FLD_VBI3_CRI_LENGTH      0x0000F000
+#define      FLD_VBI3_CRI_MARGIN      0x00000F00
+#define      FLD_VBI3_CRI_TIME        0x000000FF
+
+/*****************************************************************************/
+#define      HORIZ_TIM_CTRL           0x470
+#define      FLD_BGDEL_CNT            0xFF000000
+/* Reserved [23:22] */
+#define      FLD_HACTIVE_CNT          0x003FF000
+/* Reserved [11:10] */
+#define      FLD_HBLANK_CNT           0x000003FF
+
+/*****************************************************************************/
+#define      VERT_TIM_CTRL            0x474
+#define      FLD_V656BLANK_CNT        0xFF000000
+/* Reserved [23:22] */
+#define      FLD_VACTIVE_CNT          0x003FF000
+/* Reserved [11:10] */
+#define      FLD_VBLANK_CNT           0x000003FF
+
+/*****************************************************************************/
+#define      SRC_COMB_CFG             0x478
+#define      FLD_CCOMB_2LN_CHECK      0x80000000
+#define      FLD_CCOMB_3LN_EN         0x40000000
+#define      FLD_CCOMB_2LN_EN         0x20000000
+#define      FLD_CCOMB_3D_EN          0x10000000
+/* Reserved [27] */
+#define      FLD_LCOMB_3LN_EN         0x04000000
+#define      FLD_LCOMB_2LN_EN         0x02000000
+#define      FLD_LCOMB_3D_EN          0x01000000
+#define      FLD_LUMA_LPF_SEL         0x00C00000
+#define      FLD_UV_LPF_SEL           0x00300000
+#define      FLD_BLEND_SLOPE          0x000F0000
+#define      FLD_CCOMB_REDUCE_EN      0x00008000
+/* Reserved [14:10] */
+#define      FLD_SRC_DECIM_RATIO      0x000003FF
+
+/*****************************************************************************/
+#define      CHROMA_VBIOFF_CFG        0x47C
+#define      FLD_VBI_VOFFSET          0x1F000000
+/* Reserved [23:20] */
+#define      FLD_SC_STEP              0x000FFFFF
+
+/*****************************************************************************/
+#define      FIELD_COUNT              0x480
+#define      FLD_FIELD_COUNT_FLD      0x000003FF
+
+/*****************************************************************************/
+#define      MISC_TIM_CTRL            0x484
+#define      FLD_DEBOUNCE_COUNT       0xC0000000
+#define      FLD_VT_LINE_CNT_HYST     0x30000000
+/* Reserved [27] */
+#define      FLD_AFD_STAT             0x07FF0000
+#define      FLD_VPRES_VERT_EN        0x00008000
+/* Reserved [14:12] */
+#define      FLD_HR32                 0x00000800
+#define      FLD_TDALGN               0x00000400
+#define      FLD_TDFIELD              0x00000200
+/* Reserved [8:6] */
+#define      FLD_TEMPDEC              0x0000003F
+
+/*****************************************************************************/
+#define      DFE_CTRL1                0x488
+#define      FLD_CLAMP_AUTO_EN        0x80000000
+#define      FLD_AGC_AUTO_EN          0x40000000
+#define      FLD_VGA_CRUSH_EN         0x20000000
+#define      FLD_VGA_AUTO_EN          0x10000000
+#define      FLD_VBI_GATE_EN          0x08000000
+#define      FLD_CLAMP_LEVEL          0x07000000
+/* Reserved [23:22] */
+#define      FLD_CLAMP_SKIP_CNT       0x00300000
+#define      FLD_AGC_GAIN             0x000FFF00
+/* Reserved [7:6] */
+#define      FLD_VGA_GAIN             0x0000003F
+
+/*****************************************************************************/
+#define      DFE_CTRL2                0x48C
+#define      FLD_VGA_ACQUIRE_RANGE    0x00FF0000
+#define      FLD_VGA_TRACK_RANGE      0x0000FF00
+#define      FLD_VGA_SYNC             0x000000FF
+
+/*****************************************************************************/
+#define      DFE_CTRL3                0x490
+#define      FLD_BP_PERCENT           0xFF000000
+#define      FLD_DFT_THRESHOLD        0x00FF0000
+/* Reserved [15:12] */
+#define      FLD_SYNC_WIDTH_SEL       0x00000600
+#define      FLD_BP_LOOP_GAIN         0x00000300
+#define      FLD_SYNC_LOOP_GAIN       0x000000C0
+/* Reserved [5:4] */
+#define      FLD_AGC_LOOP_GAIN        0x0000000C
+#define      FLD_DCC_LOOP_GAIN        0x00000003
+
+/*****************************************************************************/
+#define      PLL_CTRL                 0x494
+#define      FLD_PLL_KD               0xFF000000
+#define      FLD_PLL_KI               0x00FF0000
+#define      FLD_PLL_MAX_OFFSET       0x0000FFFF
+
+
+/*****************************************************************************/
+#define      HTL_CTRL                 0x498
+/* Reserved [31:24] */
+#define      FLD_AUTO_LOCK_SPD        0x00080000
+#define      FLD_MAN_FAST_LOCK        0x00040000
+#define      FLD_HTL_15K_EN           0x00020000
+#define      FLD_HTL_500K_EN          0x00010000
+#define      FLD_HTL_KD               0x0000FF00
+#define      FLD_HTL_KI               0x000000FF
+
+/*****************************************************************************/
+#define      COMB_CTRL                0x49C
+#define      FLD_COMB_PHASE_LIMIT     0xFF000000
+#define      FLD_CCOMB_ERR_LIMIT      0x00FF0000
+#define      FLD_LUMA_THRESHOLD       0x0000FF00
+#define      FLD_LCOMB_ERR_LIMIT      0x000000FF
+
+/*****************************************************************************/
+#define      CRUSH_CTRL               0x4A0
+#define      FLD_WTW_EN               0x00400000
+#define      FLD_CRUSH_FREQ           0x00200000
+#define      FLD_MAJ_SEL_EN           0x00100000
+#define      FLD_MAJ_SEL              0x000C0000
+/* Reserved [17:15] */
+#define      FLD_SYNC_TIP_REDUCE      0x00007E00
+/* Reserved [8:6] */
+#define      FLD_SYNC_TIP_INC         0x0000003F
+
+/*****************************************************************************/
+#define      SOFT_RST_CTRL            0x4A4
+#define      FLD_VD_SOFT_RST          0x00008000
+/* Reserved [14:12] */
+#define      FLD_REG_RST_MSK          0x00000800
+#define      FLD_VOF_RST_MSK          0x00000400
+#define      FLD_MVDET_RST_MSK        0x00000200
+#define      FLD_VBI_RST_MSK          0x00000100
+#define      FLD_SCALE_RST_MSK        0x00000080
+#define      FLD_CHROMA_RST_MSK       0x00000040
+#define      FLD_LUMA_RST_MSK         0x00000020
+#define      FLD_VTG_RST_MSK          0x00000010
+#define      FLD_YCSEP_RST_MSK        0x00000008
+#define      FLD_SRC_RST_MSK          0x00000004
+#define      FLD_DFE_RST_MSK          0x00000002
+/* Reserved [0] */
+
+/*****************************************************************************/
+#define      MV_DT_CTRL1              0x4A8
+/* Reserved [31:29] */
+#define      FLD_PSP_STOP_LINE        0x1F000000
+/* Reserved [23:21] */
+#define      FLD_PSP_STRT_LINE        0x001F0000
+/* Reserved [15] */
+#define      FLD_PSP_LLIMW            0x00007F00
+/* Reserved [7] */
+#define      FLD_PSP_ULIMW            0x0000007F
+
+/*****************************************************************************/
+#define      MV_DT_CTRL2              0x4AC
+#define      FLD_CS_STOPWIN           0xFF000000
+#define      FLD_CS_STRTWIN           0x00FF0000
+#define      FLD_CS_WIDTH             0x0000FF00
+#define      FLD_PSP_SPEC_VAL         0x000000FF
+
+/*****************************************************************************/
+#define      MV_DT_CTRL3              0x4B0
+#define      FLD_AUTO_RATE_DIS        0x80000000
+#define      FLD_HLOCK_DIS            0x40000000
+#define      FLD_SEL_FIELD_CNT        0x20000000
+#define      FLD_CS_TYPE2_SEL         0x10000000
+#define      FLD_CS_LINE_THRSH_SEL    0x08000000
+#define      FLD_CS_ATHRESH_SEL       0x04000000
+#define      FLD_PSP_SPEC_SEL         0x02000000
+#define      FLD_PSP_LINES_SEL        0x01000000
+#define      FLD_FIELD_CNT            0x00F00000
+#define      FLD_CS_TYPE2_CNT         0x000FC000
+#define      FLD_CS_LINE_CNT          0x00003F00
+#define      FLD_CS_ATHRESH_LEV       0x000000FF
+
+/*****************************************************************************/
+#define      CHIP_VERSION             0x4B4
+/* Cx231xx redefine  */
+#define      VERSION                  0x4B4
+#define      FLD_REV_ID               0x000000FF
+
+/*****************************************************************************/
+#define      MISC_DIAG_CTRL           0x4B8
+/* Reserved [31:24] */
+#define      FLD_SC_CONVERGE_THRESH   0x00FF0000
+#define      FLD_CCOMB_ERR_LIMIT_3D   0x0000FF00
+#define      FLD_LCOMB_ERR_LIMIT_3D   0x000000FF
+
+/*****************************************************************************/
+#define      VBI_PASS_CTRL            0x4BC
+#define      FLD_VBI_PASS_MD          0x00200000
+#define      FLD_VBI_SETUP_DIS        0x00100000
+#define      FLD_PASS_LINE_CTRL       0x000FFFFF
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      VCR_DET_CTRL             0x4c0
+#define      FLD_EN_FIELD_PHASE_DET   0x80000000
+#define      FLD_EN_HEAD_SW_DET       0x40000000
+#define      FLD_FIELD_PHASE_LENGTH   0x01FF0000
+/* Reserved [29:25] */
+#define      FLD_FIELD_PHASE_DELAY    0x0000FF00
+#define      FLD_FIELD_PHASE_LIMIT    0x000000F0
+#define      FLD_HEAD_SW_DET_LIMIT    0x0000000F
+
+
+/*****************************************************************************/
+#define      DL_CTL                   0x800
+#define      DL_CTL_ADDRESS_LOW       0x800    /* Byte 1 in DL_CTL */
+#define      DL_CTL_ADDRESS_HIGH      0x801    /* Byte 2 in DL_CTL */
+#define      DL_CTL_DATA              0x802    /* Byte 3 in DL_CTL */
+#define      DL_CTL_CONTROL           0x803    /* Byte 4 in DL_CTL */
+/* Reserved [31:5] */
+#define      FLD_START_8051           0x10000000
+#define      FLD_DL_ENABLE            0x08000000
+#define      FLD_DL_AUTO_INC          0x04000000
+#define      FLD_DL_MAP               0x03000000
+
+/*****************************************************************************/
+#define      STD_DET_STATUS           0x804
+#define      FLD_SPARE_STATUS1        0xFF000000
+#define      FLD_SPARE_STATUS0        0x00FF0000
+#define      FLD_MOD_DET_STATUS1      0x0000FF00
+#define      FLD_MOD_DET_STATUS0      0x000000FF
+
+/*****************************************************************************/
+#define      AUD_BUILD_NUM            0x806
+#define      AUD_VER_NUM              0x807
+#define      STD_DET_CTL              0x808
+#define      STD_DET_CTL_AUD_CTL      0x808  /* Byte 1 in STD_DET_CTL */
+#define      STD_DET_CTL_PREF_MODE    0x809  /* Byte 2 in STD_DET_CTL */
+#define      FLD_SPARE_CTL0           0xFF000000
+#define      FLD_DIS_DBX              0x00800000
+#define      FLD_DIS_BTSC             0x00400000
+#define      FLD_DIS_NICAM_A2         0x00200000
+#define      FLD_VIDEO_PRESENT        0x00100000
+#define      FLD_DW8051_VIDEO_FORMAT  0x000F0000
+#define      FLD_PREF_DEC_MODE        0x0000FF00
+#define      FLD_AUD_CONFIG           0x000000FF
+
+/*****************************************************************************/
+#define      DW8051_INT               0x80C
+#define      FLD_VIDEO_PRESENT_CHANGE 0x80000000
+#define      FLD_VIDEO_CHANGE         0x40000000
+#define      FLD_RDS_READY            0x20000000
+#define      FLD_AC97_INT             0x10000000
+#define      FLD_NICAM_BIT_ERROR_TOO_HIGH         0x08000000
+#define      FLD_NICAM_LOCK           0x04000000
+#define      FLD_NICAM_UNLOCK         0x02000000
+#define      FLD_DFT4_TH_CMP          0x01000000
+/* Reserved [23:22] */
+#define      FLD_LOCK_IND_INT         0x00200000
+#define      FLD_DFT3_TH_CMP          0x00100000
+#define      FLD_DFT2_TH_CMP          0x00080000
+#define      FLD_DFT1_TH_CMP          0x00040000
+#define      FLD_FM2_DFT_TH_CMP       0x00020000
+#define      FLD_FM1_DFT_TH_CMP       0x00010000
+#define      FLD_VIDEO_PRESENT_EN     0x00008000
+#define      FLD_VIDEO_CHANGE_EN      0x00004000
+#define      FLD_RDS_READY_EN         0x00002000
+#define      FLD_AC97_INT_EN          0x00001000
+#define      FLD_NICAM_BIT_ERROR_TOO_HIGH_EN      0x00000800
+#define      FLD_NICAM_LOCK_EN        0x00000400
+#define      FLD_NICAM_UNLOCK_EN      0x00000200
+#define      FLD_DFT4_TH_CMP_EN       0x00000100
+/* Reserved [7] */
+#define      FLD_DW8051_INT6_CTL1     0x00000040
+#define      FLD_DW8051_INT5_CTL1     0x00000020
+#define      FLD_DW8051_INT4_CTL1     0x00000010
+#define      FLD_DW8051_INT3_CTL1     0x00000008
+#define      FLD_DW8051_INT2_CTL1     0x00000004
+#define      FLD_DW8051_INT1_CTL1     0x00000002
+#define      FLD_DW8051_INT0_CTL1     0x00000001
+
+/*****************************************************************************/
+#define      GENERAL_CTL              0x810
+#define      FLD_RDS_INT              0x80000000
+#define      FLD_NBER_INT             0x40000000
+#define      FLD_NLL_INT              0x20000000
+#define      FLD_IFL_INT              0x10000000
+#define      FLD_FDL_INT              0x08000000
+#define      FLD_AFC_INT              0x04000000
+#define      FLD_AMC_INT              0x02000000
+#define      FLD_AC97_INT_CTL         0x01000000
+#define      FLD_RDS_INT_DIS          0x00800000
+#define      FLD_NBER_INT_DIS         0x00400000
+#define      FLD_NLL_INT_DIS          0x00200000
+#define      FLD_IFL_INT_DIS          0x00100000
+#define      FLD_FDL_INT_DIS          0x00080000
+#define      FLD_FC_INT_DIS           0x00040000
+#define      FLD_AMC_INT_DIS          0x00020000
+#define      FLD_AC97_INT_DIS         0x00010000
+#define      FLD_REV_NUM              0x0000FF00
+/* Reserved [7:5] */
+#define      FLD_DBX_SOFT_RESET_REG   0x00000010
+#define      FLD_AD_SOFT_RESET_REG    0x00000008
+#define      FLD_SRC_SOFT_RESET_REG   0x00000004
+#define      FLD_CDMOD_SOFT_RESET     0x00000002
+#define      FLD_8051_SOFT_RESET      0x00000001
+
+/*****************************************************************************/
+#define      AAGC_CTL                 0x814
+#define      FLD_AFE_12DB_EN          0x80000000
+#define      FLD_AAGC_DEFAULT_EN      0x40000000
+#define      FLD_AAGC_DEFAULT         0x3F000000
+/* Reserved [23] */
+#define      FLD_AAGC_GAIN            0x00600000
+#define      FLD_AAGC_TH              0x001F0000
+/* Reserved [15:14] */
+#define      FLD_AAGC_HYST2           0x00003F00
+/* Reserved [7:6] */
+#define      FLD_AAGC_HYST1           0x0000003F
+
+/*****************************************************************************/
+#define      IF_SRC_CTL               0x818
+#define      FLD_DBX_BYPASS           0x80000000
+/* Reserved [30:25] */
+#define      FLD_IF_SRC_MODE          0x01000000
+/* Reserved [23:18] */
+#define      FLD_IF_SRC_PHASE_INC     0x0001FFFF
+
+/*****************************************************************************/
+#define      ANALOG_DEMOD_CTL         0x81C
+#define      FLD_ROT1_PHACC_PROG      0xFFFF0000
+/* Reserved [15] */
+#define      FLD_FM1_DELAY_FIX        0x00007000
+#define      FLD_PDF4_SHIFT           0x00000C00
+#define      FLD_PDF3_SHIFT           0x00000300
+#define      FLD_PDF2_SHIFT           0x000000C0
+#define      FLD_PDF1_SHIFT           0x00000030
+#define      FLD_FMBYPASS_MODE2       0x00000008
+#define      FLD_FMBYPASS_MODE1       0x00000004
+#define      FLD_NICAM_MODE           0x00000002
+#define      FLD_BTSC_FMRADIO_MODE    0x00000001
+
+/*****************************************************************************/
+#define      ROT_FREQ_CTL             0x820
+#define      FLD_ROT3_PHACC_PROG      0xFFFF0000
+#define      FLD_ROT2_PHACC_PROG      0x0000FFFF
+
+/*****************************************************************************/
+#define      FM_CTL                   0x824
+#define      FLD_FM2_DC_FB_SHIFT      0xF0000000
+#define      FLD_FM2_DC_INT_SHIFT     0x0F000000
+#define      FLD_FM2_AFC_RESET        0x00800000
+#define      FLD_FM2_DC_PASS_IN       0x00400000
+#define      FLD_FM2_DAGC_SHIFT       0x00380000
+#define      FLD_FM2_CORDIC_SHIFT     0x00070000
+#define      FLD_FM1_DC_FB_SHIFT      0x0000F000
+#define      FLD_FM1_DC_INT_SHIFT     0x00000F00
+#define      FLD_FM1_AFC_RESET        0x00000080
+#define      FLD_FM1_DC_PASS_IN       0x00000040
+#define      FLD_FM1_DAGC_SHIFT       0x00000038
+#define      FLD_FM1_CORDIC_SHIFT     0x00000007
+
+/*****************************************************************************/
+#define      LPF_PDF_CTL              0x828
+/* Reserved [31:30] */
+#define      FLD_LPF32_SHIFT1         0x30000000
+#define      FLD_LPF32_SHIFT2         0x0C000000
+#define      FLD_LPF160_SHIFTA        0x03000000
+#define      FLD_LPF160_SHIFTB        0x00C00000
+#define      FLD_LPF160_SHIFTC        0x00300000
+#define      FLD_LPF32_COEF_SEL2      0x000C0000
+#define      FLD_LPF32_COEF_SEL1      0x00030000
+#define      FLD_LPF160_COEF_SELC     0x0000C000
+#define      FLD_LPF160_COEF_SELB     0x00003000
+#define      FLD_LPF160_COEF_SELA     0x00000C00
+#define      FLD_LPF160_IN_EN_REG     0x00000300
+#define      FLD_PDF4_PDF_SEL         0x000000C0
+#define      FLD_PDF3_PDF_SEL         0x00000030
+#define      FLD_PDF2_PDF_SEL         0x0000000C
+#define      FLD_PDF1_PDF_SEL         0x00000003
+
+/*****************************************************************************/
+#define      DFT1_CTL1                0x82C
+#define      FLD_DFT1_DWELL           0xFFFF0000
+#define      FLD_DFT1_FREQ            0x0000FFFF
+
+/*****************************************************************************/
+#define      DFT1_CTL2                0x830
+#define      FLD_DFT1_THRESHOLD       0xFFFFFF00
+#define      FLD_DFT1_CMP_CTL         0x00000080
+#define      FLD_DFT1_AVG             0x00000070
+/* Reserved [3:1] */
+#define      FLD_DFT1_START           0x00000001
+
+/*****************************************************************************/
+#define      DFT1_STATUS              0x834
+#define      FLD_DFT1_DONE            0x80000000
+#define      FLD_DFT1_TH_CMP_STAT     0x40000000
+#define      FLD_DFT1_RESULT          0x3FFFFFFF
+
+/*****************************************************************************/
+#define      DFT2_CTL1                0x838
+#define      FLD_DFT2_DWELL           0xFFFF0000
+#define      FLD_DFT2_FREQ            0x0000FFFF
+
+/*****************************************************************************/
+#define      DFT2_CTL2                0x83C
+#define      FLD_DFT2_THRESHOLD       0xFFFFFF00
+#define      FLD_DFT2_CMP_CTL         0x00000080
+#define      FLD_DFT2_AVG             0x00000070
+/* Reserved [3:1] */
+#define      FLD_DFT2_START           0x00000001
+
+/*****************************************************************************/
+#define      DFT2_STATUS              0x840
+#define      FLD_DFT2_DONE            0x80000000
+#define      FLD_DFT2_TH_CMP_STAT     0x40000000
+#define      FLD_DFT2_RESULT          0x3FFFFFFF
+
+/*****************************************************************************/
+#define      DFT3_CTL1                0x844
+#define      FLD_DFT3_DWELL           0xFFFF0000
+#define      FLD_DFT3_FREQ            0x0000FFFF
+
+/*****************************************************************************/
+#define      DFT3_CTL2                0x848
+#define      FLD_DFT3_THRESHOLD       0xFFFFFF00
+#define      FLD_DFT3_CMP_CTL         0x00000080
+#define      FLD_DFT3_AVG             0x00000070
+/* Reserved [3:1] */
+#define      FLD_DFT3_START           0x00000001
+
+/*****************************************************************************/
+#define      DFT3_STATUS              0x84C
+#define      FLD_DFT3_DONE            0x80000000
+#define      FLD_DFT3_TH_CMP_STAT     0x40000000
+#define      FLD_DFT3_RESULT          0x3FFFFFFF
+
+/*****************************************************************************/
+#define      DFT4_CTL1                0x850
+#define      FLD_DFT4_DWELL           0xFFFF0000
+#define      FLD_DFT4_FREQ            0x0000FFFF
+
+/*****************************************************************************/
+#define      DFT4_CTL2                0x854
+#define      FLD_DFT4_THRESHOLD       0xFFFFFF00
+#define      FLD_DFT4_CMP_CTL         0x00000080
+#define      FLD_DFT4_AVG             0x00000070
+/* Reserved [3:1] */
+#define      FLD_DFT4_START           0x00000001
+
+/*****************************************************************************/
+#define      DFT4_STATUS              0x858
+#define      FLD_DFT4_DONE            0x80000000
+#define      FLD_DFT4_TH_CMP_STAT     0x40000000
+#define      FLD_DFT4_RESULT          0x3FFFFFFF
+
+/*****************************************************************************/
+#define      AM_MTS_DET               0x85C
+#define      FLD_AM_MTS_MODE          0x80000000
+/* Reserved [30:26] */
+#define      FLD_AM_SUB               0x02000000
+#define      FLD_AM_GAIN_EN           0x01000000
+/* Reserved [23:16] */
+#define      FLD_AMMTS_GAIN_SCALE     0x0000E000
+#define      FLD_MTS_PDF_SHIFT        0x00001800
+#define      FLD_AM_REG_GAIN          0x00000700
+#define      FLD_AGC_REF              0x000000FF
+
+/*****************************************************************************/
+#define      ANALOG_MUX_CTL           0x860
+/* Reserved [31:29] */
+#define      FLD_MUX21_SEL            0x10000000
+#define      FLD_MUX20_SEL            0x08000000
+#define      FLD_MUX19_SEL            0x04000000
+#define      FLD_MUX18_SEL            0x02000000
+#define      FLD_MUX17_SEL            0x01000000
+#define      FLD_MUX16_SEL            0x00800000
+#define      FLD_MUX15_SEL            0x00400000
+#define      FLD_MUX14_SEL            0x00300000
+#define      FLD_MUX13_SEL            0x000C0000
+#define      FLD_MUX12_SEL            0x00020000
+#define      FLD_MUX11_SEL            0x00018000
+#define      FLD_MUX10_SEL            0x00004000
+#define      FLD_MUX9_SEL             0x00002000
+#define      FLD_MUX8_SEL             0x00001000
+#define      FLD_MUX7_SEL             0x00000800
+#define      FLD_MUX6_SEL             0x00000600
+#define      FLD_MUX5_SEL             0x00000100
+#define      FLD_MUX4_SEL             0x000000C0
+#define      FLD_MUX3_SEL             0x00000030
+#define      FLD_MUX2_SEL             0x0000000C
+#define      FLD_MUX1_SEL             0x00000003
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DPLL_CTRL1               0x864
+#define      DIG_PLL_CTL1             0x864
+
+#define      FLD_PLL_STATUS           0x07000000
+#define      FLD_BANDWIDTH_SELECT     0x00030000
+#define      FLD_PLL_SHIFT_REG        0x00007000
+#define      FLD_PHASE_SHIFT          0x000007FF
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DPLL_CTRL2               0x868
+#define      DIG_PLL_CTL2             0x868
+#define      FLD_PLL_UNLOCK_THR       0xFF000000
+#define      FLD_PLL_LOCK_THR         0x00FF0000
+/* Reserved [15:8] */
+#define      FLD_AM_PDF_SEL2          0x000000C0
+#define      FLD_AM_PDF_SEL1          0x00000030
+#define      FLD_DPLL_FSM_CTRL        0x0000000C
+/* Reserved [1] */
+#define      FLD_PLL_PILOT_DET        0x00000001
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DPLL_CTRL3               0x86C
+#define      DIG_PLL_CTL3             0x86C
+#define      FLD_DISABLE_LOOP         0x01000000
+#define      FLD_A1_DS1_SEL           0x000C0000
+#define      FLD_A1_DS2_SEL           0x00030000
+#define      FLD_A1_KI                0x0000FF00
+#define      FLD_A1_KD                0x000000FF
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DPLL_CTRL4               0x870
+#define      DIG_PLL_CTL4             0x870
+#define      FLD_A2_DS1_SEL           0x000C0000
+#define      FLD_A2_DS2_SEL           0x00030000
+#define      FLD_A2_KI                0x0000FF00
+#define      FLD_A2_KD                0x000000FF
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DPLL_CTRL5               0x874
+#define      DIG_PLL_CTL5             0x874
+#define      FLD_TRK_DS1_SEL          0x000C0000
+#define      FLD_TRK_DS2_SEL          0x00030000
+#define      FLD_TRK_KI               0x0000FF00
+#define      FLD_TRK_KD               0x000000FF
+
+/*****************************************************************************/
+#define      DEEMPH_GAIN_CTL          0x878
+#define      FLD_DEEMPH2_GAIN         0xFFFF0000
+#define      FLD_DEEMPH1_GAIN         0x0000FFFF
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DEEMPH_COEFF1            0x87C
+#define      DEEMPH_COEF1             0x87C
+#define      FLD_DEEMPH_B0            0xFFFF0000
+#define      FLD_DEEMPH_A0            0x0000FFFF
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DEEMPH_COEFF2            0x880
+#define      DEEMPH_COEF2             0x880
+#define      FLD_DEEMPH_B1            0xFFFF0000
+#define      FLD_DEEMPH_A1            0x0000FFFF
+
+/*****************************************************************************/
+#define      DBX1_CTL1                0x884
+#define      FLD_DBX1_WBE_GAIN        0xFFFF0000
+#define      FLD_DBX1_IN_GAIN         0x0000FFFF
+
+/*****************************************************************************/
+#define      DBX1_CTL2                0x888
+#define      FLD_DBX1_SE_BYPASS       0xFFFF0000
+#define      FLD_DBX1_SE_GAIN         0x0000FFFF
+
+/*****************************************************************************/
+#define      DBX1_RMS_SE              0x88C
+#define      FLD_DBX1_RMS_WBE         0xFFFF0000
+#define      FLD_DBX1_RMS_SE_FLD      0x0000FFFF
+
+/*****************************************************************************/
+#define      DBX2_CTL1                0x890
+#define      FLD_DBX2_WBE_GAIN        0xFFFF0000
+#define      FLD_DBX2_IN_GAIN         0x0000FFFF
+
+/*****************************************************************************/
+#define      DBX2_CTL2                0x894
+#define      FLD_DBX2_SE_BYPASS       0xFFFF0000
+#define      FLD_DBX2_SE_GAIN         0x0000FFFF
+
+/*****************************************************************************/
+#define      DBX2_RMS_SE              0x898
+#define      FLD_DBX2_RMS_WBE         0xFFFF0000
+#define      FLD_DBX2_RMS_SE_FLD      0x0000FFFF
+
+/*****************************************************************************/
+#define      AM_FM_DIFF               0x89C
+/* Reserved [31] */
+#define      FLD_FM_DIFF_OUT          0x7FFF0000
+/* Reserved [15] */
+#define      FLD_AM_DIFF_OUT          0x00007FFF
+
+/*****************************************************************************/
+#define      NICAM_FAW                0x8A0
+#define      FLD_FAWDETWINEND         0xFC000000
+#define      FLD_FAWDETWINSTR         0x03FF0000
+/* Reserved [15:12] */
+#define      FLD_FAWDETTHRSHLD3       0x00000F00
+#define      FLD_FAWDETTHRSHLD2       0x000000F0
+#define      FLD_FAWDETTHRSHLD1       0x0000000F
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DEEMPH_GAIN              0x8A4
+#define      NICAM_DEEMPHGAIN         0x8A4
+/* Reserved [31:18] */
+#define      FLD_DEEMPHGAIN           0x0003FFFF
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DEEMPH_NUMER1            0x8A8
+#define      NICAM_DEEMPHNUMER1       0x8A8
+/* Reserved [31:18] */
+#define      FLD_DEEMPHNUMER1         0x0003FFFF
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DEEMPH_NUMER2            0x8AC
+#define      NICAM_DEEMPHNUMER2       0x8AC
+/* Reserved [31:18] */
+#define      FLD_DEEMPHNUMER2         0x0003FFFF
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DEEMPH_DENOM1            0x8B0
+#define      NICAM_DEEMPHDENOM1       0x8B0
+/* Reserved [31:18] */
+#define      FLD_DEEMPHDENOM1         0x0003FFFF
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DEEMPH_DENOM2            0x8B4
+#define      NICAM_DEEMPHDENOM2       0x8B4
+/* Reserved [31:18] */
+#define      FLD_DEEMPHDENOM2         0x0003FFFF
+
+/*****************************************************************************/
+#define      NICAM_ERRLOG_CTL1        0x8B8
+/* Reserved [31:28] */
+#define      FLD_ERRINTRPTTHSHLD1     0x0FFF0000
+/* Reserved [15:12] */
+#define      FLD_ERRLOGPERIOD         0x00000FFF
+
+/*****************************************************************************/
+#define      NICAM_ERRLOG_CTL2        0x8BC
+/* Reserved [31:28] */
+#define      FLD_ERRINTRPTTHSHLD3     0x0FFF0000
+/* Reserved [15:12] */
+#define      FLD_ERRINTRPTTHSHLD2     0x00000FFF
+
+/*****************************************************************************/
+#define      NICAM_ERRLOG_STS1        0x8C0
+/* Reserved [31:28] */
+#define      FLD_ERRLOG2              0x0FFF0000
+/* Reserved [15:12] */
+#define      FLD_ERRLOG1              0x00000FFF
+
+/*****************************************************************************/
+#define      NICAM_ERRLOG_STS2        0x8C4
+/* Reserved [31:12] */
+#define      FLD_ERRLOG3              0x00000FFF
+
+/*****************************************************************************/
+#define      NICAM_STATUS             0x8C8
+/* Reserved [31:20] */
+#define      FLD_NICAM_CIB            0x000C0000
+#define      FLD_NICAM_LOCK_STAT      0x00020000
+#define      FLD_NICAM_MUTE           0x00010000
+#define      FLD_NICAMADDIT_DATA      0x0000FFE0
+#define      FLD_NICAMCNTRL           0x0000001F
+
+/*****************************************************************************/
+#define      DEMATRIX_CTL             0x8CC
+#define      FLD_AC97_IN_SHIFT        0xF0000000
+#define      FLD_I2S_IN_SHIFT         0x0F000000
+#define      FLD_DEMATRIX_SEL_CTL     0x00FF0000
+/* Reserved [15:11] */
+#define      FLD_DMTRX_BYPASS         0x00000400
+#define      FLD_DEMATRIX_MODE        0x00000300
+/* Reserved [7:6] */
+#define      FLD_PH_DBX_SEL           0x00000020
+#define      FLD_PH_CH_SEL            0x00000010
+#define      FLD_PHASE_FIX            0x0000000F
+
+/*****************************************************************************/
+#define      PATH1_CTL1               0x8D0
+/* Reserved [31:29] */
+#define      FLD_PATH1_MUTE_CTL       0x1F000000
+/* Reserved [23:22] */
+#define      FLD_PATH1_AVC_CG         0x00300000
+#define      FLD_PATH1_AVC_RT         0x000F0000
+#define      FLD_PATH1_AVC_AT         0x0000F000
+#define      FLD_PATH1_AVC_STEREO     0x00000800
+#define      FLD_PATH1_AVC_CR         0x00000700
+#define      FLD_PATH1_AVC_RMS_CON    0x000000F0
+#define      FLD_PATH1_SEL_CTL        0x0000000F
+
+/*****************************************************************************/
+#define      PATH1_VOL_CTL            0x8D4
+#define      FLD_PATH1_AVC_THRESHOLD  0x7FFF0000
+#define      FLD_PATH1_BAL_LEFT       0x00008000
+#define      FLD_PATH1_BAL_LEVEL      0x00007F00
+#define      FLD_PATH1_VOLUME         0x000000FF
+
+/*****************************************************************************/
+#define      PATH1_EQ_CTL             0x8D8
+/* Reserved [31:30] */
+#define      FLD_PATH1_EQ_TREBLE_VOL  0x3F000000
+/* Reserved [23:22] */
+#define      FLD_PATH1_EQ_MID_VOL     0x003F0000
+/* Reserved [15:14] */
+#define      FLD_PATH1_EQ_BASS_VOL    0x00003F00
+/* Reserved [7:1] */
+#define      FLD_PATH1_EQ_BAND_SEL    0x00000001
+
+/*****************************************************************************/
+#define      PATH1_SC_CTL             0x8DC
+#define      FLD_PATH1_SC_THRESHOLD   0x7FFF0000
+#define      FLD_PATH1_SC_RT          0x0000F000
+#define      FLD_PATH1_SC_AT          0x00000F00
+#define      FLD_PATH1_SC_STEREO      0x00000080
+#define      FLD_PATH1_SC_CR