Blob Blame History Raw
Hans Verkuil (2):
      V4L/DVB (10982): cx231xx: fix compile warning
      V4L/DVB (10989): cx25840: cx23885 detection was broken

Mauro Carvalho Chehab (12):
      V4L/DVB (10953): cx25840: Fix CodingStyle errors introduced by the last patch
      V4L/DVB (10955): cx231xx: CodingStyle automatic fixes with Lindent
      V4L/DVB (10956): cx231xx: First series of manual CodingStyle fixes
      V4L/DVB (10957a): cx231xx: Fix compilation breakage
      V4L/DVB (11130): cx231xx: fix an inverted logic at vidioc_streamoff
      V4L/DVB (11131): cx231xx: avoid trying to access unfilled dev struct
      V4L/DVB (11132): cx231xx: usb probe cleanups
      V4L/DVB (11133): cx231xx: don't print pcb config debug messages by default
      V4L/DVB (11134): cx231xx: dmesg cleanup
      V4L/DVB (11135): cx231xx: use usb_make_path() for bus_info
      V4L/DVB (11250): cx231xx: Fix Kconfig help items
      Merge branch 'next' of ../pending into Fedora

Sri Deevi (7):
      V4L/DVB (10952): cx25840: prepare it to be used by cx231xx module
      V4L/DVB (10954): Add cx231xx USB driver
      V4L/DVB (10957): cx231xx: Fix CodingStyle
      V4L/DVB (10958): cx231xx: some additional CodingStyle and minor fixes
      V4L/DVB (11038): Fix the issue with audio module & correction of Names
      V4L/DVB (11128): cx231xx: convert the calls to subdev format
      V4L/DVB (11129): cx231xx: Use generic names for each device block

Uri Shkolnik (2):
      V4L/DVB (11239): sdio: add cards ids for sms (Siano Mobile Silicon) MDTV receivers
      V4L/DVB (11240): siano: add high level SDIO interface driver for SMS based cards

diff --git a/drivers/media/dvb/siano/smssdio.c b/drivers/media/dvb/siano/smssdio.c
new file mode 100644
index 0000000..31ba8c5
--- /dev/null
+++ b/drivers/media/dvb/siano/smssdio.c
@@ -0,0 +1,356 @@
+/*
+ *  smssdio.c - Siano 1xxx SDIO interface driver
+ *
+ *  Copyright 2008 Pierre Ossman
+ *
+ * Based on code by Siano Mobile Silicon, Inc.,
+ * Copyright (C) 2006-2008, Uri Shkolnik
+ *
+ * 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 hardware is a bit odd in that all transfers should be done
+ * to/from the SMSSDIO_DATA register, yet the "increase address" bit
+ * always needs to be set.
+ *
+ * Also, buffers from the card are always aligned to 128 byte
+ * boundaries.
+ */
+
+/*
+ * General cleanup notes:
+ *
+ * - only typedefs should be name *_t
+ *
+ * - use ERR_PTR and friends for smscore_register_device()
+ *
+ * - smscore_getbuffer should zero fields
+ *
+ * Fix stop command
+ */
+
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+
+#include "smscoreapi.h"
+#include "sms-cards.h"
+
+/* Registers */
+
+#define SMSSDIO_DATA		0x00
+#define SMSSDIO_INT		0x04
+
+static const struct sdio_device_id smssdio_ids[] = {
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR),
+	 .driver_data = SMS1XXX_BOARD_SIANO_STELLAR},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0),
+	 .driver_data = SMS1XXX_BOARD_SIANO_NOVA_A},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_B0),
+	 .driver_data = SMS1XXX_BOARD_SIANO_NOVA_B},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VEGA_A0),
+	 .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VENICE),
+	 .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
+	{ /* end: all zeroes */ },
+};
+
+MODULE_DEVICE_TABLE(sdio, smssdio_ids);
+
+struct smssdio_device {
+	struct sdio_func *func;
+
+	struct smscore_device_t *coredev;
+
+	struct smscore_buffer_t *split_cb;
+};
+
+/*******************************************************************/
+/* Siano core callbacks                                            */
+/*******************************************************************/
+
+static int smssdio_sendrequest(void *context, void *buffer, size_t size)
+{
+	int ret;
+	struct smssdio_device *smsdev;
+
+	smsdev = context;
+
+	sdio_claim_host(smsdev->func);
+
+	while (size >= smsdev->func->cur_blksize) {
+		ret = sdio_write_blocks(smsdev->func, SMSSDIO_DATA, buffer, 1);
+		if (ret)
+			goto out;
+
+		buffer += smsdev->func->cur_blksize;
+		size -= smsdev->func->cur_blksize;
+	}
+
+	if (size) {
+		ret = sdio_write_bytes(smsdev->func, SMSSDIO_DATA,
+				       buffer, size);
+		if (ret)
+			goto out;
+	}
+
+out:
+	sdio_release_host(smsdev->func);
+
+	return ret;
+}
+
+/*******************************************************************/
+/* SDIO callbacks                                                  */
+/*******************************************************************/
+
+static void smssdio_interrupt(struct sdio_func *func)
+{
+	int ret, isr;
+
+	struct smssdio_device *smsdev;
+	struct smscore_buffer_t *cb;
+	struct SmsMsgHdr_ST *hdr;
+	size_t size;
+
+	smsdev = sdio_get_drvdata(func);
+
+	/*
+	 * The interrupt register has no defined meaning. It is just
+	 * a way of turning of the level triggered interrupt.
+	 */
+	isr = sdio_readb(func, SMSSDIO_INT, &ret);
+	if (ret) {
+		dev_err(&smsdev->func->dev,
+			"Unable to read interrupt register!\n");
+		return;
+	}
+
+	if (smsdev->split_cb == NULL) {
+		cb = smscore_getbuffer(smsdev->coredev);
+		if (!cb) {
+			dev_err(&smsdev->func->dev,
+				"Unable to allocate data buffer!\n");
+			return;
+		}
+
+		ret = sdio_read_blocks(smsdev->func, cb->p, SMSSDIO_DATA, 1);
+		if (ret) {
+			dev_err(&smsdev->func->dev,
+				"Error %d reading initial block!\n", ret);
+			return;
+		}
+
+		hdr = cb->p;
+
+		if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) {
+			smsdev->split_cb = cb;
+			return;
+		}
+
+		size = hdr->msgLength - smsdev->func->cur_blksize;
+	} else {
+		cb = smsdev->split_cb;
+		hdr = cb->p;
+
+		size = hdr->msgLength - sizeof(struct SmsMsgHdr_ST);
+
+		smsdev->split_cb = NULL;
+	}
+
+	if (hdr->msgLength > smsdev->func->cur_blksize) {
+		void *buffer;
+
+		size = ALIGN(size, 128);
+		buffer = cb->p + hdr->msgLength;
+
+		BUG_ON(smsdev->func->cur_blksize != 128);
+
+		/*
+		 * First attempt to transfer all of it in one go...
+		 */
+		ret = sdio_read_blocks(smsdev->func, buffer,
+				       SMSSDIO_DATA, size / 128);
+		if (ret && ret != -EINVAL) {
+			smscore_putbuffer(smsdev->coredev, cb);
+			dev_err(&smsdev->func->dev,
+				"Error %d reading data from card!\n", ret);
+			return;
+		}
+
+		/*
+		 * ..then fall back to one block at a time if that is
+		 * not possible...
+		 *
+		 * (we have to do this manually because of the
+		 * problem with the "increase address" bit)
+		 */
+		if (ret == -EINVAL) {
+			while (size) {
+				ret = sdio_read_blocks(smsdev->func,
+						       buffer, SMSSDIO_DATA, 1);
+				if (ret) {
+					smscore_putbuffer(smsdev->coredev, cb);
+					dev_err(&smsdev->func->dev,
+						"Error %d reading "
+						"data from card!\n", ret);
+					return;
+				}
+
+				buffer += smsdev->func->cur_blksize;
+				if (size > smsdev->func->cur_blksize)
+					size -= smsdev->func->cur_blksize;
+				else
+					size = 0;
+			}
+		}
+	}
+
+	cb->size = hdr->msgLength;
+	cb->offset = 0;
+
+	smscore_onresponse(smsdev->coredev, cb);
+}
+
+static int smssdio_probe(struct sdio_func *func,
+			 const struct sdio_device_id *id)
+{
+	int ret;
+
+	int board_id;
+	struct smssdio_device *smsdev;
+	struct smsdevice_params_t params;
+
+	board_id = id->driver_data;
+
+	smsdev = kzalloc(sizeof(struct smssdio_device), GFP_KERNEL);
+	if (!smsdev)
+		return -ENOMEM;
+
+	smsdev->func = func;
+
+	memset(&params, 0, sizeof(struct smsdevice_params_t));
+
+	params.device = &func->dev;
+	params.buffer_size = 0x5000;	/* ?? */
+	params.num_buffers = 22;	/* ?? */
+	params.context = smsdev;
+
+	snprintf(params.devpath, sizeof(params.devpath),
+		 "sdio\\%s", sdio_func_id(func));
+
+	params.sendrequest_handler = smssdio_sendrequest;
+
+	params.device_type = sms_get_board(board_id)->type;
+
+	if (params.device_type != SMS_STELLAR)
+		params.flags |= SMS_DEVICE_FAMILY2;
+	else {
+		/*
+		 * FIXME: Stellar needs special handling...
+		 */
+		ret = -ENODEV;
+		goto free;
+	}
+
+	ret = smscore_register_device(&params, &smsdev->coredev);
+	if (ret < 0)
+		goto free;
+
+	smscore_set_board_id(smsdev->coredev, board_id);
+
+	sdio_claim_host(func);
+
+	ret = sdio_enable_func(func);
+	if (ret)
+		goto release;
+
+	ret = sdio_set_block_size(func, 128);
+	if (ret)
+		goto disable;
+
+	ret = sdio_claim_irq(func, smssdio_interrupt);
+	if (ret)
+		goto disable;
+
+	sdio_set_drvdata(func, smsdev);
+
+	sdio_release_host(func);
+
+	ret = smscore_start_device(smsdev->coredev);
+	if (ret < 0)
+		goto reclaim;
+
+	return 0;
+
+reclaim:
+	sdio_claim_host(func);
+	sdio_release_irq(func);
+disable:
+	sdio_disable_func(func);
+release:
+	sdio_release_host(func);
+	smscore_unregister_device(smsdev->coredev);
+free:
+	kfree(smsdev);
+
+	return ret;
+}
+
+static void smssdio_remove(struct sdio_func *func)
+{
+	struct smssdio_device *smsdev;
+
+	smsdev = sdio_get_drvdata(func);
+
+	/* FIXME: racy! */
+	if (smsdev->split_cb)
+		smscore_putbuffer(smsdev->coredev, smsdev->split_cb);
+
+	smscore_unregister_device(smsdev->coredev);
+
+	sdio_claim_host(func);
+	sdio_release_irq(func);
+	sdio_disable_func(func);
+	sdio_release_host(func);
+
+	kfree(smsdev);
+}
+
+static struct sdio_driver smssdio_driver = {
+	.name = "smssdio",
+	.id_table = smssdio_ids,
+	.probe = smssdio_probe,
+	.remove = smssdio_remove,
+};
+
+/*******************************************************************/
+/* Module functions                                                */
+/*******************************************************************/
+
+int smssdio_register(void)
+{
+	int ret = 0;
+
+	printk(KERN_INFO "smssdio: Siano SMS1xxx SDIO driver\n");
+	printk(KERN_INFO "smssdio: Copyright Pierre Ossman\n");
+
+	ret = sdio_register_driver(&smssdio_driver);
+
+	return ret;
+}
+
+void smssdio_unregister(void)
+{
+	sdio_unregister_driver(&smssdio_driver);
+}
+
+MODULE_DESCRIPTION("Siano SMS1xxx SDIO driver");
+MODULE_AUTHOR("Pierre Ossman");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 76bad58..58abbe3 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -795,6 +795,8 @@ source "drivers/media/video/hdpvr/Kconfig"
 
 source "drivers/media/video/em28xx/Kconfig"
 
+source "drivers/media/video/cx231xx/Kconfig"
+
 source "drivers/media/video/usbvision/Kconfig"
 
 source "drivers/media/video/usbvideo/Kconfig"
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index b904674..08765d8 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -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
index 0000000..9115654
--- /dev/null
+++ b/drivers/media/video/cx231xx/Kconfig
@@ -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_CUSTOMISE
+       ---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
index 0000000..755dd0c
--- /dev/null
+++ b/drivers/media/video/cx231xx/Makefile
@@ -0,0 +1,14 @@
+cx231xx-objs     := cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o \
+		    cx231xx-avcore.o cx231xx-pcb-cfg.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
index 0000000..9ab0628
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx-audio.c
@@ -0,0 +1,585 @@
+/*
+ *  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"
+
+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;
+
+				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 */
+	/* 1 - 48000 samples per sec */
+	ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1);
+	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 */
+	/* 1 - 48000 samples per sec */
+	ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0);
+	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
index 0000000..1be3881
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx-avcore.c
@@ -0,0 +1,2581 @@
+/*
+   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"
+
+/******************************************************************************
+			-: BLOCK ARRANGEMENT :-
+	I2S block ----------------------|
+	[I2S audio]			|
+					|
+	Analog Front End --> Direct IF -|-> Cx25840 --> Audio
+	[video & audio]			|   [Audio]
+					|
+					|-> Cx25840 --> Video
+					    [Video]
+
+*******************************************************************************/
+
+/******************************************************************************
+ *                    A F E - B L O C K    C O N T R O L   functions          *
+ * 				[ANALOG FRONT END]			      *
+ ******************************************************************************/
+static int afe_write_byte(struct cx231xx *dev, u16 saddr, u8 data)
+{
+	return cx231xx_write_i2c_data(dev, AFE_DEVICE_ADDRESS,
+					saddr, 2, data, 1);
+}
+
+static int afe_read_byte(struct cx231xx *dev, u16 saddr, u8 *data)
+{
+	int status;
+	u32 temp = 0;
+
+	status = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS,
+					saddr, 2, &temp, 1);
+	*data = (u8) temp;
+	return status;
+}
+
+int cx231xx_afe_init_super_block(struct cx231xx *dev, u32 ref_count)
+{
+	int status = 0;
+	u8 temp = 0;
+	u8 afe_power_status = 0;
+	int i = 0;
+
+	/* super block initialize */
+	temp = (u8) (ref_count & 0xff);
+	status = afe_write_byte(dev, SUP_BLK_TUNE2, temp);
+	if (status < 0)
+		return status;
+
+	status = afe_read_byte(dev, SUP_BLK_TUNE2, &afe_power_status);
+	if (status < 0)
+		return status;
+
+	temp = (u8) ((ref_count & 0x300) >> 8);
+	temp |= 0x40;
+	status = afe_write_byte(dev, SUP_BLK_TUNE1, temp);
+	if (status < 0)
+		return status;
+
+	status = afe_write_byte(dev, SUP_BLK_PLL2, 0x0f);
+	if (status < 0)
+		return status;
+
+	/* enable pll     */
+	while (afe_power_status != 0x18) {
+		status = afe_write_byte(dev, SUP_BLK_PWRDN, 0x18);
+		if (status < 0) {
+			cx231xx_info(
+			": Init Super Block failed in send cmd\n");
+			break;
+		}
+
+		status = afe_read_byte(dev, SUP_BLK_PWRDN, &afe_power_status);
+		afe_power_status &= 0xff;
+		if (status < 0) {
+			cx231xx_info(
+			": Init Super Block failed in receive cmd\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 = afe_write_byte(dev, SUP_BLK_TUNE3, 0x40);
+	if (status < 0)
+		return status;
+
+	msleep(5);
+
+	/* exit tuning */
+	status = afe_write_byte(dev, SUP_BLK_TUNE3, 0x00);
+
+	return status;
+}
+
+int cx231xx_afe_init_channels(struct cx231xx *dev)
+{
+	int status = 0;
+
+	/* power up all 3 channels, clear pd_buffer */
+	status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, 0x00);
+	status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, 0x00);
+	status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, 0x00);
+
+	/* Enable quantizer calibration */
+	status = afe_write_byte(dev, ADC_COM_QUANT, 0x02);
+
+	/* channel initialize, force modulator (fb) reset */
+	status = afe_write_byte(dev, ADC_FB_FRCRST_CH1, 0x17);
+	status = afe_write_byte(dev, ADC_FB_FRCRST_CH2, 0x17);
+	status = afe_write_byte(dev, ADC_FB_FRCRST_CH3, 0x17);
+
+	/* start quantilizer calibration  */
+	status = afe_write_byte(dev, ADC_CAL_ATEST_CH1, 0x10);
+	status = afe_write_byte(dev, ADC_CAL_ATEST_CH2, 0x10);
+	status = afe_write_byte(dev, ADC_CAL_ATEST_CH3, 0x10);
+	msleep(5);
+
+	/* exit modulator (fb) reset */
+	status = afe_write_byte(dev, ADC_FB_FRCRST_CH1, 0x07);
+	status = afe_write_byte(dev, ADC_FB_FRCRST_CH2, 0x07);
+	status = afe_write_byte(dev, ADC_FB_FRCRST_CH3, 0x07);
+
+	/* enable the pre_clamp in each channel for single-ended input */
+	status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH1, 0xf0);
+	status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH2, 0xf0);
+	status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH3, 0xf0);
+
+	/* use diode instead of resistor, so set term_en to 0, res_en to 0  */
+	status = cx231xx_reg_mask_write(dev, AFE_DEVICE_ADDRESS, 8,
+				   ADC_QGAIN_RES_TRM_CH1, 3, 7, 0x00);
+	status = cx231xx_reg_mask_write(dev, AFE_DEVICE_ADDRESS, 8,
+				   ADC_QGAIN_RES_TRM_CH2, 3, 7, 0x00);
+	status = cx231xx_reg_mask_write(dev, AFE_DEVICE_ADDRESS, 8,
+				   ADC_QGAIN_RES_TRM_CH3, 3, 7, 0x00);
+
+	/* dynamic element matching off */
+	status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH1, 0x03);
+	status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH2, 0x03);
+	status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH3, 0x03);
+
+	return status;
+}
+
+int cx231xx_afe_setup_AFE_for_baseband(struct cx231xx *dev)
+{
+	u8 c_value = 0;
+	int status = 0;
+
+	status = afe_read_byte(dev, ADC_PWRDN_CLAMP_CH2, &c_value);
+	c_value &= (~(0x50));
+	status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, c_value);
+
+	return status;
+}
+
+/*
+	The Analog Front End in Cx231xx has 3 channels. These
+	channels are used to share between different inputs
+	like tuner, s-video and composite inputs.
+
+	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_afe_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;
+	u8 value = 0;
+
+	if (ch1_setting != 0) {
+		status = afe_read_byte(dev, ADC_INPUT_CH1, &value);
+		value &= (!INPUT_SEL_MASK);
+		value |= (ch1_setting - 1) << 4;
+		value &= 0xff;
+		status = afe_write_byte(dev, ADC_INPUT_CH1, value);
+	}
+
+	if (ch2_setting != 0) {
+		status = afe_read_byte(dev, ADC_INPUT_CH2, &value);
+		value &= (!INPUT_SEL_MASK);
+		value |= (ch2_setting - 1) << 4;
+		value &= 0xff;
+		status = afe_write_byte(dev, ADC_INPUT_CH2, value);
+	}
+
+	/* For ch3_setting, the value to put in the register is
+	   7 less than the input number */
+	if (ch3_setting != 0) {
+		status = afe_read_byte(dev, ADC_INPUT_CH3, &value);
+		value &= (!INPUT_SEL_MASK);
+		value |= (ch3_setting - 1) << 4;
+		value &= 0xff;
+		status = afe_write_byte(dev, ADC_INPUT_CH3, value);
+	}
+
+	return status;
+}
+
+int cx231xx_afe_set_mode(struct cx231xx *dev, enum AFE_MODE mode)
+{
+	int status = 0;
+
+	/*
+	* FIXME: We need to implement the AFE code for LOW IF and for HI IF.
+	* Currently, only baseband works.
+	*/
+
+	switch (mode) {
+	case AFE_MODE_LOW_IF:
+		/* SetupAFEforLowIF();  */
+		break;
+	case AFE_MODE_BASEBAND:
+		status = cx231xx_afe_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->afe_mode) &&
+		(dev->video_input == CX231XX_VMUX_TELEVISION))
+		status = cx231xx_afe_adjust_ref_count(dev,
+						     CX231XX_VMUX_TELEVISION);
+
+	dev->afe_mode = mode;
+
+	return status;
+}
+
+int cx231xx_afe_update_power_control(struct cx231xx *dev,
+					enum AV_MODE avmode)
+{
+	u8 afe_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 (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
+						FLD_PWRDN_ENABLE_PLL)) {
+				status = afe_write_byte(dev, SUP_BLK_PWRDN,
+							FLD_PWRDN_TUNING_BIAS |
+							FLD_PWRDN_ENABLE_PLL);
+				status |= afe_read_byte(dev, SUP_BLK_PWRDN,
+							&afe_power_status);
+				if (status < 0)
+					break;
+			}
+
+			status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
+							0x00);
+			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
+							0x00);
+			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
+							0x00);
+		} else if (avmode == POLARIS_AVMODE_DIGITAL) {
+			status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
+							0x70);
+			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
+							0x70);
+			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
+							0x70);
+
+			status |= afe_read_byte(dev, SUP_BLK_PWRDN,
+						  &afe_power_status);
+			afe_power_status |= FLD_PWRDN_PD_BANDGAP |
+						FLD_PWRDN_PD_BIAS |
+						FLD_PWRDN_PD_TUNECK;
+			status |= afe_write_byte(dev, SUP_BLK_PWRDN,
+						   afe_power_status);
+		} else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) {
+			while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
+						FLD_PWRDN_ENABLE_PLL)) {
+				status = afe_write_byte(dev, SUP_BLK_PWRDN,
+							FLD_PWRDN_TUNING_BIAS |
+							FLD_PWRDN_ENABLE_PLL);
+				status |= afe_read_byte(dev, SUP_BLK_PWRDN,
+							&afe_power_status);
+				if (status < 0)
+					break;
+			}
+
+			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
+						0x00);
+			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
+						0x00);
+			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
+						0x00);
+		} else {
+			cx231xx_info("Invalid AV mode input\n");
+			status = -1;
+		}
+		break;
+	default:
+		if (avmode == POLARIS_AVMODE_ANALOGT_TV) {
+			while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
+						FLD_PWRDN_ENABLE_PLL)) {
+				status = afe_write_byte(dev, SUP_BLK_PWRDN,
+							FLD_PWRDN_TUNING_BIAS |
+							FLD_PWRDN_ENABLE_PLL);
+				status |= afe_read_byte(dev, SUP_BLK_PWRDN,
+							&afe_power_status);
+				if (status < 0)
+					break;
+			}
+
+			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
+							0x40);
+			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
+							0x40);
+			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
+							0x00);
+		} else if (avmode == POLARIS_AVMODE_DIGITAL) {
+			status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
+							0x70);
+			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
+							0x70);
+			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
+							0x70);
+
+			status |= afe_read_byte(dev, SUP_BLK_PWRDN,
+						       &afe_power_status);
+			afe_power_status |= FLD_PWRDN_PD_BANDGAP |
+						FLD_PWRDN_PD_BIAS |
+						FLD_PWRDN_PD_TUNECK;
+			status |= afe_write_byte(dev, SUP_BLK_PWRDN,
+							afe_power_status);
+		} else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) {
+			while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
+						FLD_PWRDN_ENABLE_PLL)) {
+				status = afe_write_byte(dev, SUP_BLK_PWRDN,
+							FLD_PWRDN_TUNING_BIAS |
+							FLD_PWRDN_ENABLE_PLL);
+				status |= afe_read_byte(dev, SUP_BLK_PWRDN,
+							&afe_power_status);
+				if (status < 0)
+					break;
+			}
+
+			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
+							0x00);
+			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
+							0x00);
+			status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
+							0x40);
+		} else {
+			cx231xx_info("Invalid AV mode input\n");
+			status = -1;
+		}
+	}			/* switch  */
+
+	return status;
+}
+
+int cx231xx_afe_adjust_ref_count(struct cx231xx *dev, u32 video_input)
+{
+	u8 input_mode = 0;
+	u8 ntf_mode = 0;
+	int status = 0;
+
+	dev->video_input = video_input;
+
+	if (video_input == CX231XX_VMUX_TELEVISION) {
+		status = afe_read_byte(dev, ADC_INPUT_CH3, &input_mode);
+		status = afe_read_byte(dev, ADC_NTF_PRECLMP_EN_CH3,
+					&ntf_mode);
+	} else {
+		status = afe_read_byte(dev, ADC_INPUT_CH1, &input_mode);
+		status = afe_read_byte(dev, ADC_NTF_PRECLMP_EN_CH1,
+					&ntf_mode);
+	}
+
+	input_mode = (ntf_mode & 0x3) | ((input_mode & 0x6) << 1);
+
+	switch (input_mode) {
+	case SINGLE_ENDED:
+		dev->afe_ref_count = 0x23C;
+		break;
+	case LOW_IF:
+		dev->afe_ref_count = 0x24C;
+		break;
+	case EU_IF:
+		dev->afe_ref_count = 0x258;
+		break;
+	case US_IF:
+		dev->afe_ref_count = 0x260;
+		break;
+	default:
+		break;
+	}
+
+	status = cx231xx_afe_init_super_block(dev, dev->afe_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    *
+ ******************************************************************************/
+static int vid_blk_write_byte(struct cx231xx *dev, u16 saddr, u8 data)
+{
+	return cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS,
+					saddr, 2, data, 1);
+}
+
+static int vid_blk_read_byte(struct cx231xx *dev, u16 saddr, u8 *data)
+{
+	int status;
+	u32 temp = 0;
+
+	status = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
+					saddr, 2, &temp, 1);
+	*data = (u8) temp;
+	return status;
+}
+
+static int vid_blk_write_word(struct cx231xx *dev, u16 saddr, u32 data)
+{
+	return cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS,
+					saddr, 2, data, 4);
+}
+
+static int vid_blk_read_word(struct cx231xx *dev, u16 saddr, u32 *data)
+{
+	return cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
+					saddr, 2, data, 4);
+}
+
+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)) {
+			/* External AV */
+			status = cx231xx_set_power_mode(dev,
+					POLARIS_AVMODE_ENXTERNAL_AV);
+			if (status < 0) {
+				cx231xx_errdev("%s: 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)) {
+			/* Tuner */
+			status = cx231xx_set_power_mode(dev,
+						POLARIS_AVMODE_ANALOGT_TV);
+			if (status < 0) {
+				cx231xx_errdev("%s: 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: 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_afe_adjust_ref_count(dev, pin_type);
+		if (status < 0) {
+			cx231xx_errdev("%s: adjust_ref_count :Failed to set"
+				"AFE input mux - errCode [%d]!\n",
+				__func__, status);
+			return status;
+		}
+	}
+
+	/* call afe block to set video inputs */
+	status = cx231xx_afe_set_input_mux(dev, input);
+	if (status < 0) {
+		cx231xx_errdev("%s: set_input_mux :Failed to set"
+				" AFE input mux - errCode [%d]!\n",
+				__func__, status);
+		return status;
+	}
+
+	switch (pin_type) {
+	case CX231XX_VMUX_COMPOSITE1:
+		status = vid_blk_read_word(dev, AFE_CTRL, &value);
+		value |= (0 << 13) | (1 << 4);
+		value &= ~(1 << 5);
+
+		/* set [24:23] [22:15] to 0  */
+		value &= (~(0x1ff8000));
+		/* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0  */
+		value |= 0x1000000;
+		status = vid_blk_write_word(dev, AFE_CTRL, value);
+
+		status = vid_blk_read_word(dev, OUT_CTRL1, &value);
+		value |= (1 << 7);
+		status = vid_blk_write_word(dev, OUT_CTRL1, value);
+
+		/* Set vip 1.1 output mode */
+		status = cx231xx_read_modify_write_i2c_dword(dev,
+							VID_BLK_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 = vid_blk_read_word(dev, DFE_CTRL1, &value);
+
+		/* enable the VBI_GATE_EN */
+		value |= FLD_VBI_GATE_EN;
+
+		/* Enable the auto-VGA enable */
+		value |= FLD_VGA_AUTO_EN;
+
+		/* Write it back */
+		status = vid_blk_write_word(dev, DFE_CTRL1, value);
+
+		/* Disable auto config of registers */
+		status = cx231xx_read_modify_write_i2c_dword(dev,
+					VID_BLK_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,
+			VID_BLK_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 = vid_blk_read_word(dev, AFE_CTRL, &value);
+
+		/* set [24:23] [22:15] to 0 */
+		value &= (~(0x1ff8000));
+		/* set FUNC_MODE[24:23] = 2
+		IF_MOD[22:15] = 0 DCR_BYP_CH2[4:4] = 1; */
+		value |= 0x1000010;
+		status = vid_blk_write_word(dev, AFE_CTRL, value);
+
+		/* 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 = vid_blk_read_word(dev, DFE_CTRL1, &value);
+
+		/* enable the VBI_GATE_EN */
+		value |= FLD_VBI_GATE_EN;
+
+		/* Enable the auto-VGA enable */
+		value |= FLD_VGA_AUTO_EN;
+
+		/* Write it back */
+		status = vid_blk_write_word(dev, DFE_CTRL1, value);
+
+		/* Disable auto config of registers  */
+		status =  cx231xx_read_modify_write_i2c_dword(dev,
+					VID_BLK_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,
+			VID_BLK_I2C_ADDRESS,
+			MODE_CTRL,
+			FLD_INPUT_MODE,
+			cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_YC_1));
+
+		/* Chroma to ADC2 */
+		status = vid_blk_read_word(dev, AFE_CTRL, &value);
+		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 = vid_blk_write_word(dev, AFE_CTRL, value);
+
+		status = cx231xx_afe_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 = vid_blk_read_word(dev, AFE_CTRL, &value);
+			value |= (0 << 13) | (1 << 4);
+			value &= ~(1 << 5);
+
+			/* set [24:23] [22:15] to 0 */
+			value &= (~(0x1FF8000));
+			/* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */
+			value |= 0x1000000;
+			status = vid_blk_write_word(dev, AFE_CTRL, value);
+
+			status = vid_blk_read_word(dev, OUT_CTRL1, &value);
+			value |= (1 << 7);
+			status = vid_blk_write_word(dev, OUT_CTRL1, value);
+
+			/* Set vip 1.1 output mode */
+			status = cx231xx_read_modify_write_i2c_dword(dev,
+							VID_BLK_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 = vid_blk_read_word(dev, DFE_CTRL1, &value);
+
+			/* enable the VBI_GATE_EN */
+			value |= FLD_VBI_GATE_EN;
+
+			/* Enable the auto-VGA enable */
+			value |= FLD_VGA_AUTO_EN;
+
+			/* Write it back */
+			status = vid_blk_write_word(dev, DFE_CTRL1, value);
+
+			/* Disable auto config of registers */
+			status = cx231xx_read_modify_write_i2c_dword(dev,
+					VID_BLK_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,
+				VID_BLK_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 = vid_blk_read_word(dev, DIF_MISC_CTRL, &value);
+
+			/* Clear the bypass bit */
+			value &= ~FLD_DIF_DIF_BYPASS;
+
+			/* Enable the use of the DIF block */
+			status = vid_blk_write_word(dev, DIF_MISC_CTRL, value);
+
+			/* Read the DFE_CTRL1 register */
+			status = vid_blk_read_word(dev, DFE_CTRL1, &value);
+
+			/* 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 = vid_blk_write_word(dev, DFE_CTRL1, value);
+
+			/* Wait until AGC locks up */
+			msleep(1);
+
+			/* Disable the auto-VGA enable AGC */
+			value &= ~(FLD_VGA_AUTO_EN);
+
+			/* Write it back */
+			status = vid_blk_write_word(dev, DFE_CTRL1, value);
+
+			/* Enable Polaris B0 AGC output */
+			status = vid_blk_read_word(dev, PIN_CTRL, &value);
+			value |= (FLD_OEF_AGC_RF) |
+				 (FLD_OEF_AGC_IFVGA) |
+				 (FLD_OEF_AGC_IF);
+			status = vid_blk_write_word(dev, PIN_CTRL, value);
+
+			/* Set vip 1.1 output mode */
+			status = cx231xx_read_modify_write_i2c_dword(dev,
+						VID_BLK_I2C_ADDRESS,
+						OUT_CTRL1, FLD_OUT_MODE,
+						OUT_MODE_VIP11);
+
+			/* Disable auto config of registers */
+			status = cx231xx_read_modify_write_i2c_dword(dev,
+					VID_BLK_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,
+				VID_BLK_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 = vid_blk_read_word(dev, AFE_CTRL, &value);
+
+			value |= FLD_VGA_SEL_CH3 | FLD_VGA_SEL_CH2;
+
+			status = vid_blk_write_word(dev, AFE_CTRL, value);
+			break;
+
+		}
+		break;
+	}
+
+	/* Set raw VBI mode */
+	status = cx231xx_read_modify_write_i2c_dword(dev,
+				VID_BLK_I2C_ADDRESS,
+				OUT_CTRL1, FLD_VBIHACTRAW_EN,
+				cx231xx_set_field(FLD_VBIHACTRAW_EN, 1));
+
+	status = vid_blk_read_word(dev, OUT_CTRL1, &value);
+	if (value & 0x02) {
+		value |= (1 << 19);
+		status = vid_blk_write_word(dev, OUT_CTRL1, value);
+	}
+
+	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 = vid_blk_write_word(dev, DFE_CTRL3, 0xCD3F0280);
+
+	if (dev->norm & (V4L2_STD_NTSC | 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,
+							VID_BLK_I2C_ADDRESS,
+							VERT_TIM_CTRL,
+							FLD_VBLANK_CNT, 0x18);
+		status = cx231xx_read_modify_write_i2c_dword(dev,
+							VID_BLK_I2C_ADDRESS,
+							VERT_TIM_CTRL,
+							FLD_VACTIVE_CNT,
+							0x1E6000);
+		status = cx231xx_read_modify_write_i2c_dword(dev,
+							VID_BLK_I2C_ADDRESS,
+							VERT_TIM_CTRL,
+							FLD_V656BLANK_CNT,
+							0x1E000000);
+
+		status = cx231xx_read_modify_write_i2c_dword(dev,
+							VID_BLK_I2C_ADDRESS,
+							HORIZ_TIM_CTRL,
+							FLD_HBLANK_CNT,
+							cx231xx_set_field
+							(FLD_HBLANK_CNT, 0x79));
+	} else if (dev->norm & V4L2_STD_SECAM) {
+		cx231xx_info("do_mode_ctrl_overrides SECAM\n");
+		status =  cx231xx_read_modify_write_i2c_dword(dev,
+							VID_BLK_I2C_ADDRESS,
+							VERT_TIM_CTRL,
+							FLD_VBLANK_CNT, 0x24);
+		/* Adjust the active video horizontal start point */
+		status = cx231xx_read_modify_write_i2c_dword(dev,
+							VID_BLK_I2C_ADDRESS,
+							HORIZ_TIM_CTRL,
+							FLD_HBLANK_CNT,
+							cx231xx_set_field
+							(FLD_HBLANK_CNT, 0x85));
+	} else {
+		cx231xx_info("do_mode_ctrl_overrides PAL\n");
+		status = cx231xx_read_modify_write_i2c_dword(dev,
+							VID_BLK_I2C_ADDRESS,
+							VERT_TIM_CTRL,
+							FLD_VBLANK_CNT, 0x24);
+		/* Adjust the active video horizontal start point */
+		status = cx231xx_read_modify_write_i2c_dword(dev,
+							VID_BLK_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_i2s_blk_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;
+	u8 gen_ctrl;
+	u32 value = 0;
+
+	/* Put it in soft reset   */
+	status = vid_blk_read_byte(dev, GENERAL_CTL, &gen_ctrl);
+	gen_ctrl |= 1;
+	status = vid_blk_write_byte(dev, GENERAL_CTL, gen_ctrl);
+
+	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 = vid_blk_write_word(dev, AUD_IO_CTRL, value);
+
+		/* setup input to Merlin, SRC2 connect to AC97
+		   bypass upsample-by-2, slave mode, sony mode, left justify
+		   adr 091c, dat 01000000 */
+		status = vid_blk_read_word(dev, AC97_CTL, &dwval);
+
+		status = vid_blk_write_word(dev, AC97_CTL,
+					   (dwval | FLD_AC97_UP2X_BYPASS));
+
+		/* select the parallel1 and SRC3 */
+		status = vid_blk_write_word(dev, BAND_OUT_SEL,
+				cx231xx_set_field(FLD_SRC3_IN_SEL, 0x0) |
+				cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x0) |
+				cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x0));
+
+		/* unmute all, AC97 in, independence mode
+		   adr 08d0, data 0x00063073 */
+		status = vid_blk_write_word(dev, PATH1_CTL1, 0x00063073);
+
+		/* set AVC maximum threshold, adr 08d4, dat ffff0024 */
+		status = vid_blk_read_word(dev, PATH1_VOL_CTL, &dwval);
+		status = vid_blk_write_word(dev, PATH1_VOL_CTL,
+					   (dwval | FLD_PATH1_AVC_THRESHOLD));
+
+		/* set SC maximum threshold, adr 08ec, dat ffffb3a3 */
+		status = vid_blk_read_word(dev, PATH1_SC_CTL, &dwval);
+		status = vid_blk_write_word(dev, PATH1_SC_CTL,
+					   (dwval | FLD_PATH1_SC_THRESHOLD));
+		break;
+
+	case AUDIO_INPUT_TUNER_TV:
+	default:
+
+		/* Setup SRC sources and clocks */
+		status = vid_blk_write_word(dev, BAND_OUT_SEL,
+			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));
+
+		/* Setup the AUD_IO control */
+		status = vid_blk_write_word(dev, AUD_IO_CTRL,
+			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));
+
+		status = vid_blk_write_word(dev, PATH1_CTL1, 0x1F063870);
+
+		/* setAudioStandard(_audio_standard); */
+
+		status = vid_blk_write_word(dev, PATH1_CTL1, 0x00063870);
+		switch (dev->model) {
+		case CX231XX_BOARD_CNXT_RDE_250:
+		case CX231XX_BOARD_CNXT_RDU_250:
+			status = cx231xx_read_modify_write_i2c_dword(dev,
+					VID_BLK_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 = vid_blk_write_word(dev, PATH1_CTL1, 0x1F011012);
+		break;
+	}
+
+	/* Take it out of soft reset */
+	status = vid_blk_read_byte(dev, GENERAL_CTL, &gen_ctrl);
+	gen_ctrl &= ~1;
+	status = vid_blk_write_byte(dev, GENERAL_CTL, gen_ctrl);
+
+	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 = vid_blk_write_word(dev, HSCALE_CTRL, hscale);
+
+	/* set vertical scale */
+	status = vid_blk_write_word(dev, VSCALE_CTRL, vscale);
+
+	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 = vid_blk_read_word(dev, PIN_CTRL, &value);
+	value |= (~dev->board.ctl_pin_status_mask);
+	status = vid_blk_write_word(dev, PIN_CTRL, value);
+
+	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 */
+		/* lo if big signal */
+		status = cx231xx_reg_mask_write(dev,
+				VID_BLK_I2C_ADDRESS, 32,
+				AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);
+		/* FUNC_MODE = DIF */
+		status = cx231xx_reg_mask_write(dev,
+				VID_BLK_I2C_ADDRESS, 32,
+				AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode);
+		/* IF_MODE */
+		status = cx231xx_reg_mask_write(dev,
+				VID_BLK_I2C_ADDRESS, 32,
+				AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xFF);
+		/* no inv */
+		status = cx231xx_reg_mask_write(dev,
+				VID_BLK_I2C_ADDRESS, 32,
+				AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);
+	} else if (standard != DIF_USE_BASEBAND) {
+		if (standard & V4L2_STD_MN) {
+			/* lo if big signal */
+			status = cx231xx_reg_mask_write(dev,
+					VID_BLK_I2C_ADDRESS, 32,
+					AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);
+			/* FUNC_MODE = DIF */
+			status = cx231xx_reg_mask_write(dev,
+					VID_BLK_I2C_ADDRESS, 32,
+					AFE_CTRL_C2HH_SRC_CTRL, 23, 24,
+					function_mode);
+			/* IF_MODE */
+			status = cx231xx_reg_mask_write(dev,
+					VID_BLK_I2C_ADDRESS, 32,
+					AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xb);
+			/* no inv */
+			status = cx231xx_reg_mask_write(dev,
+					VID_BLK_I2C_ADDRESS, 32,
+					AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);
+			/* 0x124, AUD_CHAN1_SRC = 0x3 */
+			status = cx231xx_reg_mask_write(dev,
+					VID_BLK_I2C_ADDRESS, 32,
+					AUD_IO_CTRL, 0, 31, 0x00000003);
+		} else if ((standard == V4L2_STD_PAL_I) |
+			(standard & V4L2_STD_SECAM)) {
+			/* C2HH setup */
+			/* lo if big signal */
+			status = cx231xx_reg_mask_write(dev,
+					VID_BLK_I2C_ADDRESS, 32,
+					AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);
+			/* FUNC_MODE = DIF */
+			status = cx231xx_reg_mask_write(dev,
+					VID_BLK_I2C_ADDRESS, 32,
+					AFE_CTRL_C2HH_SRC_CTRL, 23, 24,
+					function_mode);
+			/* IF_MODE */
+			status = cx231xx_reg_mask_write(dev,
+					VID_BLK_I2C_ADDRESS, 32,
+					AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF);
+			/* no inv */
+			status = cx231xx_reg_mask_write(dev,
+					VID_BLK_I2C_ADDRESS, 32,
+					AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);
+		} else {
+			/* default PAL BG */
+			/* C2HH setup */
+			/* lo if big signal */
+			status = cx231xx_reg_mask_write(dev,
+					VID_BLK_I2C_ADDRESS, 32,
+					AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);
+			/* FUNC_MODE = DIF */
+			status = cx231xx_reg_mask_write(dev,
+					VID_BLK_I2C_ADDRESS, 32,
+					AFE_CTRL_C2HH_SRC_CTRL, 23, 24,
+					function_mode);
+			/* IF_MODE */
+			status = cx231xx_reg_mask_write(dev,
+					VID_BLK_I2C_ADDRESS, 32,
+					AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE);
+			/* no inv */
+			status = cx231xx_reg_mask_write(dev,
+					VID_BLK_I2C_ADDRESS, 32,
+					AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);
+		}
+	}
+
+	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 = vid_blk_read_word(dev, DIF_MISC_CTRL, &dif_misc_ctrl_value);
+	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 = vid_blk_write_word(dev, DIF_SRC_PHASE_INC, 0xDF7DF83);
+		status = vid_blk_read_word(dev, DIF_MISC_CTRL,
+						&dif_misc_ctrl_value);
+		dif_misc_ctrl_value |= FLD_DIF_DIF_BYPASS;
+		status = vid_blk_write_word(dev, DIF_MISC_CTRL,
+						dif_misc_ctrl_value);
+	} else if (standard & V4L2_STD_PAL_D) {
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL, 0, 31, 0x6503bc0c);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL1, 0, 31, 0xbd038c85);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL2, 0, 31, 0x1db4640a);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL3, 0, 31, 0x00008800);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_IF_REF, 0, 31, 0x444C1380);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_CTRL_IF, 0, 31, 0xDA302600);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_CTRL_INT, 0, 31, 0xDA261700);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_CTRL_RF, 0, 31, 0xDA262600);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_IF_INT_CURRENT, 0, 31,
+					   0x26001700);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_RF_CURRENT, 0, 31,
+					   0x00002660);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_VIDEO_AGC_CTRL, 0, 31,
+					   0x72500800);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_VID_AUD_OVERRIDE, 0, 31,
+					   0x27000100);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AV_SEP_CTRL, 0, 31, 0x3F3934EA);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_COMP_FLT_CTRL, 0, 31,
+					   0x00000000);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_SRC_PHASE_INC, 0, 31,
+					   0x1befbf06);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_SRC_GAIN_CONTROL, 0, 31,
+					   0x000035e8);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_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, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL, 0, 31, 0x6503bc0c);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL1, 0, 31, 0xbd038c85);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL2, 0, 31, 0x1db4640a);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL3, 0, 31, 0x00008800);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_IF_REF, 0, 31, 0x444C1380);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_CTRL_IF, 0, 31, 0xDA302600);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_CTRL_INT, 0, 31, 0xDA261700);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_CTRL_RF, 0, 31, 0xDA262600);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_IF_INT_CURRENT, 0, 31,
+					   0x26001700);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_RF_CURRENT, 0, 31,
+					   0x00002660);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_VIDEO_AGC_CTRL, 0, 31,
+					   0x72500800);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_VID_AUD_OVERRIDE, 0, 31,
+					   0x27000100);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AV_SEP_CTRL, 0, 31, 0x5F39A934);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_COMP_FLT_CTRL, 0, 31,
+					   0x00000000);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_SRC_PHASE_INC, 0, 31,
+					   0x1befbf06);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_SRC_GAIN_CONTROL, 0, 31,
+					   0x000035e8);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_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 = vid_blk_write_word(dev, DIF_PLL_CTRL, 0xFF01FF0C);
+		status = vid_blk_write_word(dev, DIF_PLL_CTRL1, 0xbd038c85);
+		status = vid_blk_write_word(dev, DIF_PLL_CTRL2, 0x1db4640a);
+		status = vid_blk_write_word(dev, DIF_PLL_CTRL3, 0x00008800);
+		status = vid_blk_write_word(dev, DIF_AGC_IF_REF, 0x444C1380);
+		status = vid_blk_write_word(dev, DIF_AGC_IF_INT_CURRENT,
+						0x26001700);
+		status = vid_blk_write_word(dev, DIF_AGC_RF_CURRENT,
+						0x00002660);
+		status = vid_blk_write_word(dev, DIF_VIDEO_AGC_CTRL,
+						0x72500800);
+		status = vid_blk_write_word(dev, DIF_VID_AUD_OVERRIDE,
+						0x27000100);
+		status = vid_blk_write_word(dev, DIF_AV_SEP_CTRL, 0x012c405d);
+		status = vid_blk_write_word(dev, DIF_COMP_FLT_CTRL,
+						0x009f50c1);
+		status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC,
+						0x1befbf06);
+		status = vid_blk_write_word(dev, DIF_SRC_GAIN_CONTROL,
+						0x000035e8);
+		status = vid_blk_write_word(dev, DIF_SOFT_RST_CTRL_REVB,
+						0x00000000);
+		/* 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 = vid_blk_write_word(dev, DIF_PLL_CTRL, 0xFF01FF0C);
+		status = vid_blk_write_word(dev, DIF_PLL_CTRL1, 0xbd038c85);
+		status = vid_blk_write_word(dev, DIF_PLL_CTRL2, 0x1db4640a);
+		status = vid_blk_write_word(dev, DIF_PLL_CTRL3, 0x00008800);
+		status = vid_blk_write_word(dev, DIF_AGC_IF_REF, 0x444C1380);
+		status = vid_blk_write_word(dev, DIF_AGC_IF_INT_CURRENT,
+						0x26001700);
+		status = vid_blk_write_word(dev, DIF_AGC_RF_CURRENT,
+						0x00002660);
+		status = vid_blk_write_word(dev, DIF_VIDEO_AGC_CTRL,
+						0x72500800);
+		status = vid_blk_write_word(dev, DIF_VID_AUD_OVERRIDE,
+						0x27000100);
+		status = vid_blk_write_word(dev, DIF_AV_SEP_CTRL,
+						0x012c405d);
+		status = vid_blk_write_word(dev, DIF_COMP_FLT_CTRL,
+						0x009f50c1);
+		status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC,
+						0x1befbf06);
+		status = vid_blk_write_word(dev, DIF_SRC_GAIN_CONTROL,
+						0x000035e8);
+		status = vid_blk_write_word(dev, DIF_SOFT_RST_CTRL_REVB,
+						0x00000000);
+		/* 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, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL, 0, 31, 0x6503bc0c);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL1, 0, 31, 0xbd038c85);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL2, 0, 31, 0x1db4640a);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL3, 0, 31, 0x00008800);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_IF_REF, 0, 31, 0x888C0380);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_CTRL_IF, 0, 31, 0xe0262600);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_CTRL_INT, 0, 31, 0xc2171700);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_CTRL_RF, 0, 31, 0xc2262600);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_IF_INT_CURRENT, 0, 31,
+					   0x26001700);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_RF_CURRENT, 0, 31,
+					   0x00002660);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_VID_AUD_OVERRIDE, 0, 31,
+					   0x27000100);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_COMP_FLT_CTRL, 0, 31,
+					   0x00000000);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_SRC_PHASE_INC, 0, 31,
+					   0x1befbf06);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_SRC_GAIN_CONTROL, 0, 31,
+					   0x000035e8);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_RPT_VARIANCE, 0, 31, 0x00000000);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_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, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL, 0, 31, 0x6503bc0c);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL1, 0, 31, 0xbd038c85);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL2, 0, 31, 0x1db4640a);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL3, 0, 31, 0x00008800);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_IF_REF, 0, 31, 0x888C0380);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_CTRL_IF, 0, 31, 0xe0262600);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_CTRL_INT, 0, 31, 0xc2171700);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_CTRL_RF, 0, 31, 0xc2262600);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_IF_INT_CURRENT, 0, 31,
+					   0x26001700);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_RF_CURRENT, 0, 31,
+					   0x00002660);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_VID_AUD_OVERRIDE, 0, 31,
+					   0x27000100);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_COMP_FLT_CTRL, 0, 31,
+					   0x00000000);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_SRC_PHASE_INC, 0, 31,
+					   0x1befbf06);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_SRC_GAIN_CONTROL, 0, 31,
+					   0x000035e8);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_RPT_VARIANCE, 0, 31, 0x00000000);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_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 if (standard & V4L2_STD_NTSC_M) {
+		/* 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 = vid_blk_write_word(dev, DIF_PLL_CTRL, 0x6503BC0C);
+		status = vid_blk_write_word(dev, DIF_PLL_CTRL1, 0xBD038C85);
+		status = vid_blk_write_word(dev, DIF_PLL_CTRL2, 0x1DB4640A);
+		status = vid_blk_write_word(dev, DIF_PLL_CTRL3, 0x00008800);
+		status = vid_blk_write_word(dev, DIF_AGC_IF_REF, 0x444C0380);
+		status = vid_blk_write_word(dev, DIF_AGC_IF_INT_CURRENT,
+						0x26001700);
+		status = vid_blk_write_word(dev, DIF_AGC_RF_CURRENT,
+						0x00002660);
+		status = vid_blk_write_word(dev, DIF_VIDEO_AGC_CTRL,
+						0x04000800);
+		status = vid_blk_write_word(dev, DIF_VID_AUD_OVERRIDE,
+						0x27000100);
+		status = vid_blk_write_word(dev, DIF_AV_SEP_CTRL, 0x01296e1f);
+
+		status = vid_blk_write_word(dev, DIF_COMP_FLT_CTRL,
+						0x009f50c1);
+		status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC,
+						0x1befbf06);
+		status = vid_blk_write_word(dev, DIF_SRC_GAIN_CONTROL,
+						0x000035e8);
+
+		status = vid_blk_write_word(dev, DIF_AGC_CTRL_IF, 0xC2262600);
+		status = vid_blk_write_word(dev, DIF_AGC_CTRL_INT,
+						0xC2262600);
+		status = vid_blk_write_word(dev, DIF_AGC_CTRL_RF, 0xC2262600);
+
+		/* Save the Spec Inversion value */
+		dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+		dif_misc_ctrl_value |= 0x3a003F10;
+	} else {
+		/* default PAL BG */
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL, 0, 31, 0x6503bc0c);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL1, 0, 31, 0xbd038c85);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL2, 0, 31, 0x1db4640a);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_PLL_CTRL3, 0, 31, 0x00008800);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_IF_REF, 0, 31, 0x444C1380);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_CTRL_IF, 0, 31, 0xDA302600);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_CTRL_INT, 0, 31, 0xDA261700);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_CTRL_RF, 0, 31, 0xDA262600);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_IF_INT_CURRENT, 0, 31,
+					   0x26001700);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AGC_RF_CURRENT, 0, 31,
+					   0x00002660);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_VIDEO_AGC_CTRL, 0, 31,
+					   0x72500800);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_VID_AUD_OVERRIDE, 0, 31,
+					   0x27000100);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_AV_SEP_CTRL, 0, 31, 0x3F3530EC);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_COMP_FLT_CTRL, 0, 31,
+					   0x00A653A8);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_SRC_PHASE_INC, 0, 31,
+					   0x1befbf06);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+					   DIF_SRC_GAIN_CONTROL, 0, 31,
+					   0x000035e8);
+		status = cx231xx_reg_mask_write(dev, VID_BLK_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;
+	}
+
+	/* 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 = vid_blk_write_word(dev, DIF_MISC_CTRL, dif_misc_ctrl_value);
+
+	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 = vid_blk_read_word(dev, DIF_AGC_IF_REF, &dwval);
+	dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF);
+	dwval |= 0x33000000;
+
+	status = vid_blk_write_word(dev, DIF_AGC_IF_REF, dwval);
+
+	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 L/B/D standards */
+	status = vid_blk_read_word(dev, DIF_AGC_IF_REF, &dwval);
+	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 = vid_blk_write_word(dev, DIF_AGC_IF_REF, dwval);
+
+	return status;
+}
+
+/******************************************************************************
+ *        	    I 2 S - B L O C K    C O N T R O L   functions            *
+ ******************************************************************************/
+int cx231xx_i2s_blk_initialize(struct cx231xx *dev)
+{
+	int status = 0;
+	u32 value;
+
+	status = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+				       CH_PWR_CTRL1, 1, &value, 1);
+	/* enables clock to delta-sigma and decimation filter */
+	value |= 0x80;
+	status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+					CH_PWR_CTRL1, 1, value, 1);
+	/* power up all channel */
+	status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+					CH_PWR_CTRL2, 1, 0x00, 1);
+
+	return status;
+}
+
+int cx231xx_i2s_blk_update_power_control(struct cx231xx *dev,
+					enum AV_MODE avmode)
+{
+	int status = 0;
+	u32 value = 0;
+
+	if (avmode != POLARIS_AVMODE_ENXTERNAL_AV) {
+		status = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+					  CH_PWR_CTRL2, 1, &value, 1);
+		value |= 0xfe;
+		status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+						CH_PWR_CTRL2, 1, value, 1);
+	} else {
+		status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+						CH_PWR_CTRL2, 1, 0x00, 1);
+	}
+
+	return status;
+}
+
+/* set i2s_blk for audio input types */
+int cx231xx_i2s_blk_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, I2S_BLK_DEVICE_ADDRESS,
+						CH_PWR_CTRL2, 1, 0x00, 1);
+		status = cx231xx_write_i2c_data(dev, I2S_BLK_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, enum 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);
+
+		/* reset state of xceive tuner */
+		dev->xc_fw_load_done = 0;
+		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 afe */
+	status = cx231xx_afe_update_power_control(dev, mode);
+
+	/* update power control for i2s_blk */
+	status = cx231xx_i2s_blk_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;
+	struct pcb_config *pcb_config;
+
+	/* get EP for media type */
+	pcb_config = (struct 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;
+
+	/* input */
+	if (pin_value == 0)
+		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;
+}
+
+/*
+* cx231xx_set_gpio_value
+*      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 -GPIO I2C 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
index 0000000..d2f2091
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx-cards.c
@@ -0,0 +1,919 @@
+/*
+   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",
+		.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",
+		.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, 0x5A3C),
+	 .driver_info = CX231XX_BOARD_UNKNOWN},
+	{USB_DEVICE(0x0572, 0x58A2),
+	 .driver_info = CX231XX_BOARD_CNXT_RDE_250},
+	{USB_DEVICE(0x0572, 0x58A1),
+	 .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 CB: RESET: cmd %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 inline void 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);
+
+	/* 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);
+
+	/* 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); */
+
+}
+
+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;
+
+	tuner_call(dev, tuner, s_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,
+		};
+		tuner_call(dev, tuner, s_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;
+	call_all(dev, tuner, s_frequency, &f);
+
+}
+
+/* ----------------------------------------------------------------------- */
+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;
+
+	/* request some modules */
+	if (dev->board.decoder == CX231XX_AVDECODER) {
+		dev->sd_cx25840 =
+			v4l2_i2c_new_subdev(&dev->i2c_bus[0].i2c_adap,
+					"cx25840", "cx25840", 0x88 >> 1);
+		if (dev->sd_cx25840 == NULL)
+			cx231xx_info("cx25840 subdev registration failure\n");
+		cx25840_call(dev, core, init, 0);
+
+	}
+
+	if (dev->board.tuner_type != TUNER_ABSENT) {
+		dev->sd_tuner =
+			v4l2_i2c_new_subdev(&dev->i2c_bus[1].i2c_adap,
+				"tuner", "tuner", 0xc2 >> 1);
+		if (dev->sd_tuner == NULL)
+			cx231xx_info("tuner subdev registration failure\n");
+
+		cx231xx_config_tuner(dev);
+	}
+
+	cx231xx_config_tuner(dev);
+
+#if 0
+	/* 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;
+
+	call_all(dev, video, s_stream, 1);
+}
+
+/*
+ * 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 = 0, 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;
+
+	if (!ifnum) {
+		/*
+		 * Interface number 0 - IR interface
+		 */
+		/* 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_err(DRIVER_NAME ": 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;
+
+		/* 0 - vbi ; 1 -sliced cc mode */
+		dev->vbi_or_sliced_cc_mode = 0;
+
+		/* get maximum no.of IAD interfaces */
+		assoc_desc = udev->actconfig->intf_assoc[0];
+		dev->max_iad_interface_count = assoc_desc->bInterfaceCount;
+
+		/* init CIR module TBD */
+
+		/* store the current interface */
+		lif = interface;
+
+		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) with %d interfaces\n",
+		     descr,
+		     speed,
+		     le16_to_cpu(udev->descriptor.idVendor),
+		     le16_to_cpu(udev->descriptor.idProduct),
+		     dev->max_iad_interface_count);
+	} else {
+		/* 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, for all interfaces but
+		 * interface 1 and the last one
+		 */
+		if ((ifnum != 1) && ((dev->interface_count - 1)
+				     != dev->max_iad_interface_count))
+			skip_interface = 1;
+
+		if (ifnum == 1) {
+			assoc_desc = udev->actconfig->intf_assoc[0];
+			if (assoc_desc->bFirstInterface != ifnum) {
+				cx231xx_err(DRIVER_NAME ": Not found "
+					    "matching IAD interface\n");
+				return -ENODEV;
+			}
+		}
+	}
+
+	if (skip_interface)
+		return -ENODEV;
+
+	cx231xx_info("registering interface %d\n", ifnum);
+
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(lif, dev);
+
+	if ((dev->interface_count - 1) != dev->max_iad_interface_count)
+		return 0;
+
+	/*
+	 * AV device initialization - only done at the last interface
+	 */
+
+	/* Create v4l2 device */
+	snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
+					"%s-%03d", "cx231xx", nr);
+	retval = v4l2_device_register(&udev->dev, &dev->v4l2_dev);
+	if (retval) {
+		cx231xx_errdev("v4l2_device_register failed\n");
+		cx231xx_devused &= ~(1 << nr);
+		kfree(dev);
+		return -EIO;
+	}
+
+	/* allocate device struct */
+	retval = cx231xx_init_dev(&dev, udev, nr);
+	if (retval) {
+		cx231xx_devused &= ~(1 << dev->devno);
+		v4l2_device_unregister(&dev->v4l2_dev);
+		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);
+		v4l2_device_unregister(&dev->v4l2_dev);
+		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);
+		v4l2_device_unregister(&dev->v4l2_dev);
+		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);
+		v4l2_device_unregister(&dev->v4l2_dev);
+		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);
+			v4l2_device_unregister(&dev->v4l2_dev);
+			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]);
+		}
+	}
+
+	/* load other modules required */
+	request_modules(dev);
+
+	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;
+
+	if (!dev->udev)
+		return;
+
+	/* delete v4l2 device */
+	v4l2_device_unregister(&dev->v4l2_dev);
+
+	/* 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 loaded.\n");
+
+	/* 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
index 0000000..a6f398a
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx-conf-reg.h
@@ -0,0 +1,494 @@
+/*
+   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 */
+
+enum AV_MODE{
+       POLARIS_AVMODE_DEFAULT = 0,
+       POLARIS_AVMODE_DIGITAL = 0x10,
+       POLARIS_AVMODE_ANALOGT_TV = 0x20,
+       POLARIS_AVMODE_ENXTERNAL_AV = 0x30,
+
+};
+
+/* 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 FLD_PWRDN_TUNING_BIAS	0x10
+#define FLD_PWRDN_ENABLE_PLL	0x08
+#define FLD_PWRDN_PD_BANDGAP	0x04
+#define FLD_PWRDN_PD_BIAS	0x02
+#define FLD_PWRDN_PD_TUNECK	0x01
+
+
+#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)
+/*****************************************************************************/
+#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)
+/*****************************************************************************/
+#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)
+/*****************************************************************************/
+#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)
+/*****************************************************************************/
+#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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+#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)
+/*****************************************************************************/
+#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)
+/*****************************************************************************/
+#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)
+/*****************************************************************************/
+#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)
+/*****************************************************************************/
+#define      FLD_DIF_IF_AGC_IN                          0xffff0000
+#define      FLD_DIF_INT_AGC_IN                         0x0000ffff
+
+/*****************************************************************************/
+#define      DIF_AGC_RF_CURRENT       (DIRECT_IF_REVB_BASE + 0x00000028)
+/*****************************************************************************/
+/*  Reserved                            [31:16] */
+#define      FLD_DIF_RF_AGC_IN                          0x0000ffff
+
+/*****************************************************************************/
+#define      DIF_VIDEO_AGC_CTRL       (DIRECT_IF_REVB_BASE + 0x0000002c)
+/*****************************************************************************/
+#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)
+/*****************************************************************************/
+#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)
+/*****************************************************************************/
+#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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+#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)
+/*****************************************************************************/
+/*  Reserved                             [31:29] */
+#define      FLD_DIF_PHASE_INC                          0x1fffffff
+
+/*****************************************************************************/
+#define      DIF_SRC_GAIN_CONTROL     (DIRECT_IF_REVB_BASE + 0x00000044)
+/*****************************************************************************/
+/*  Reserved                             [31:16] */
+#define      FLD_DIF_SRC_KI                             0x0000ff00
+#define      FLD_DIF_SRC_KD                             0x000000ff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF01          (DIRECT_IF_REVB_BASE + 0x00000048)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_36                       0x3fff0000
+/*  Reserved                             [15:0] */
+
+/*****************************************************************************/
+#define      DIF_RPT_VARIANCE         (DIRECT_IF_REVB_BASE + 0x00000094)
+/*****************************************************************************/
+/*  Reserved                             [31:20] */
+#define      FLD_DIF_RPT_VARIANCE                       0x000fffff
+
+/*****************************************************************************/
+#define      DIF_SOFT_RST_CTRL_REVB       (DIRECT_IF_REVB_BASE + 0x00000098)
+/*****************************************************************************/
+/*  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)
+/*****************************************************************************/
+/*  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
index 0000000..0d333e6
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx-core.c
@@ -0,0 +1,1200 @@
+/*
+   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");
+
+#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);
+	}
+	printk(KERN_INFO DRIVER_NAME ": %s initialized\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);
+	printk(KERN_INFO DRIVER_NAME ": %s removed\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;
+	struct 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) {
+		/* channel number, for read,spec required channel_num +4 */
+		ven_req.bRequest = i2c_bus->nr + 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, 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,
+				struct 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 alt %d with wMaxPktSize=%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 alt 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
+		("can't change interface %d alt no. to %d: Max. Pkt size = 0\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
+			("can't change interface %d alt no. to %d (err=%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,
+	afe can not be set up correctly */
+	errCode = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV);
+	if (errCode < 0) {
+		cx231xx_errdev
+		    ("%s: Failed to set Power - errCode [%d]!\n",
+		     __func__, errCode);
+		return errCode;
+	}
+
+	/* initialize Colibri block */
+	errCode = cx231xx_afe_init_super_block(dev, 0x23c);
+	if (errCode < 0) {
+		cx231xx_errdev
+		    ("%s: cx231xx_afe init super block - errCode [%d]!\n",
+		     __func__, errCode);
+		return errCode;
+	}
+	errCode = cx231xx_afe_init_channels(dev);
+	if (errCode < 0) {
+		cx231xx_errdev
+		    ("%s: cx231xx_afe 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;
+	}
+
+	/* I2S block related functions */
+	errCode = cx231xx_i2s_blk_initialize(dev);
+	if (errCode < 0) {
+		cx231xx_errdev
+		    ("%s: cx231xx_i2s block 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;
+	struct 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, 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
index 0000000..c5082a4
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx-dvb.c
@@ -0,0 +1,559 @@
+/*
+ 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
index 0000000..b4a03d8
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx-i2c.c
@@ -0,0 +1,555 @@
+/*
+   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;
+				/* FW Loading is done */
+				dev->xc_fw_load_done = 1;
+				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 WRITE: 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 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 */
+
+				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, saddr 0x%x, len %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 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;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	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,
+	.name = "cx231xx",
+	.id = I2C_HW_B_CX231XX,
+	.algo = &cx231xx_algo,
+	.client_register = attach_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_register()
+ * register i2c bus
+ */
+int cx231xx_i2c_register(struct cx231xx_i2c *bus)
+{
+	struct cx231xx *dev = bus->dev;
+
+	BUG_ON(!dev->cx231xx_send_usb_command);
+
+	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, &dev->v4l2_dev);
+	i2c_add_adapter(&bus->i2c_adap);
+
+	bus->i2c_client.adapter = &bus->i2c_adap;
+
+	if (0 == bus->i2c_rc) {
+		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
index 0000000..97e304c
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx-input.c
@@ -0,0 +1,246 @@
+/*
+  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-pcb-cfg.c b/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c
new file mode 100644
index 0000000..7473c33
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c
@@ -0,0 +1,795 @@
+/*
+   cx231xx-pcb-config.c - 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.
+ */
+
+#include "cx231xx.h"
+#include "cx231xx-conf-reg.h"
+
+static unsigned int pcb_debug;
+module_param(pcb_debug, int, 0644);
+MODULE_PARM_DESC(pcb_debug, "enable pcb config debug messages [video]");
+
+/******************************************************************************/
+
+struct pcb_config cx231xx_Scenario[] = {
+	{
+	 INDEX_SELFPOWER_DIGITAL_ONLY,	/* index */
+	 USB_SELF_POWER,	/* power_type */
+	 0,			/* speed , not decide yet */
+	 MOD_DIGITAL,		/* mode */
+	 SOURCE_TS_BDA,		/* ts1_source, digital tv only */
+	 NOT_SUPPORTED,		/* ts2_source  */
+	 NOT_SUPPORTED,		/* analog source */
+
+	 0,			/* digital_index  */
+	 0,			/* analog index */
+	 0,			/* dif_index   */
+	 0,			/* external_index */
+
+	 1,			/* only one configuration */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    1,			/* ts1 index */
+	    NOT_SUPPORTED,	/* TS2 index */
+	    NOT_SUPPORTED,	/* AUDIO */
+	    NOT_SUPPORTED,	/* VIDEO */
+	    NOT_SUPPORTED,	/* VANC */
+	    NOT_SUPPORTED,	/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   ,
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 ,
+	 /* full-speed config */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    1,			/* ts1 index */
+	    NOT_SUPPORTED,	/* TS2 index */
+	    NOT_SUPPORTED,	/* AUDIO */
+	    NOT_SUPPORTED,	/* VIDEO */
+	    NOT_SUPPORTED,	/* VANC */
+	    NOT_SUPPORTED,	/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 }
+	,
+
+	{
+	 INDEX_SELFPOWER_DUAL_DIGITAL,	/* index */
+	 USB_SELF_POWER,	/* power_type */
+	 0,			/* speed , not decide yet */
+	 MOD_DIGITAL,		/* mode */
+	 SOURCE_TS_BDA,		/* ts1_source, digital tv only */
+	 0,			/* ts2_source,need update from register */
+	 NOT_SUPPORTED,		/* analog source */
+	 0,			/* digital_index  */
+	 0,			/* analog index */
+	 0,			/* dif_index */
+	 0,			/* external_index */
+
+	 1,			/* only one configuration */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    1,			/* ts1 index */
+	    2,			/* TS2 index */
+	    NOT_SUPPORTED,	/* AUDIO */
+	    NOT_SUPPORTED,	/* VIDEO */
+	    NOT_SUPPORTED,	/* VANC */
+	    NOT_SUPPORTED,	/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 ,
+	 /* full-speed */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    1,			/* ts1 index */
+	    2,			/* TS2 index */
+	    NOT_SUPPORTED,	/* AUDIO */
+	    NOT_SUPPORTED,	/* VIDEO */
+	    NOT_SUPPORTED,	/* VANC */
+	    NOT_SUPPORTED,	/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 }
+	,
+
+	{
+	 INDEX_SELFPOWER_ANALOG_ONLY,	/* index */
+	 USB_SELF_POWER,	/* power_type */
+	 0,			/* speed , not decide yet */
+	 MOD_ANALOG | MOD_DIF | MOD_EXTERNAL,	/* mode ,analog tv only */
+	 NOT_SUPPORTED,		/* ts1_source, NOT SUPPORT */
+	 NOT_SUPPORTED,		/* ts2_source,NOT SUPPORT */
+	 0,			/* analog source, need update */
+
+	 0,			/* digital_index  */
+	 0,			/* analog index */
+	 0,			/* dif_index */
+	 0,			/* external_index */
+
+	 1,			/* only one configuration */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    NOT_SUPPORTED,	/* ts1 index */
+	    NOT_SUPPORTED,	/* TS2 index */
+	    1,			/* AUDIO */
+	    2,			/* VIDEO */
+	    3,			/* VANC */
+	    4,			/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 ,
+	 /* full-speed */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    NOT_SUPPORTED,	/* ts1 index */
+	    NOT_SUPPORTED,	/* TS2 index */
+	    1,			/* AUDIO */
+	    2,			/* VIDEO */
+	    NOT_SUPPORTED,	/* VANC */
+	    NOT_SUPPORTED,	/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 }
+	,
+
+	{
+	 INDEX_SELFPOWER_DUAL,	/* index */
+	 USB_SELF_POWER,	/* power_type */
+	 0,			/* speed , not decide yet */
+	 /* mode ,analog tv and digital path */
+	 MOD_ANALOG | MOD_DIF | MOD_DIGITAL | MOD_EXTERNAL,
+	 0,			/* ts1_source,will update in register */
+	 NOT_SUPPORTED,		/* ts2_source,NOT SUPPORT */
+	 0,			/* analog source need update */
+	 0,			/* digital_index  */
+	 0,			/* analog index */
+	 0,			/* dif_index */
+	 0,			/* external_index */
+	 1,			/* only one configuration */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    1,			/* ts1 index */
+	    NOT_SUPPORTED,	/* TS2 index */
+	    2,			/* AUDIO */
+	    3,			/* VIDEO */
+	    4,			/* VANC */
+	    5,			/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 ,
+	 /* full-speed */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    1,			/* ts1 index */
+	    NOT_SUPPORTED,	/* TS2 index */
+	    2,			/* AUDIO */
+	    3,			/* VIDEO */
+	    NOT_SUPPORTED,	/* VANC */
+	    NOT_SUPPORTED,	/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 }
+	,
+
+	{
+	 INDEX_SELFPOWER_TRIPLE,	/* index */
+	 USB_SELF_POWER,	/* power_type */
+	 0,			/* speed , not decide yet */
+	 /* mode ,analog tv and digital path */
+	 MOD_ANALOG | MOD_DIF | MOD_DIGITAL | MOD_EXTERNAL,
+	 0,			/* ts1_source, update in register */
+	 0,			/* ts2_source,update in register */
+	 0,			/* analog source, need update */
+
+	 0,			/* digital_index  */
+	 0,			/* analog index */
+	 0,			/* dif_index */
+	 0,			/* external_index */
+	 1,			/* only one configuration */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    1,			/* ts1 index */
+	    2,			/* TS2 index */
+	    3,			/* AUDIO */
+	    4,			/* VIDEO */
+	    5,			/* VANC */
+	    6,			/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 ,
+	 /* full-speed */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    1,			/* ts1 index */
+	    2,			/* TS2 index */
+	    3,			/* AUDIO */
+	    4,			/* VIDEO */
+	    NOT_SUPPORTED,	/* VANC */
+	    NOT_SUPPORTED,	/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 }
+	,
+
+	{
+	 INDEX_SELFPOWER_COMPRESSOR,	/* index */
+	 USB_SELF_POWER,	/* power_type */
+	 0,			/* speed , not decide yet */
+	 /* mode ,analog tv AND DIGITAL path */
+	 MOD_ANALOG | MOD_DIF | MOD_DIGITAL | MOD_EXTERNAL,
+	 NOT_SUPPORTED,		/* ts1_source, disable */
+	 SOURCE_TS_BDA,		/* ts2_source */
+	 0,			/* analog source,need update */
+	 0,			/* digital_index  */
+	 0,			/* analog index */
+	 0,			/* dif_index */
+	 0,			/* external_index */
+	 1,			/* only one configuration */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    NOT_SUPPORTED,	/* ts1 index */
+	    1,			/* TS2 index */
+	    2,			/* AUDIO */
+	    3,			/* VIDEO */
+	    4,			/* VANC */
+	    5,			/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 ,
+	 /* full-speed  */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    NOT_SUPPORTED,	/* ts1 index */
+	    1,			/* TS2 index */
+	    2,			/* AUDIO */
+	    3,			/* VIDEO */
+	    NOT_SUPPORTED,	/* VANC */
+	    NOT_SUPPORTED,	/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 }
+	,
+
+	{
+	 INDEX_BUSPOWER_DIGITAL_ONLY,	/* index */
+	 USB_BUS_POWER,		/* power_type */
+	 0,			/* speed , not decide yet */
+	 MOD_DIGITAL,		/* mode ,analog tv AND DIGITAL path */
+	 SOURCE_TS_BDA,		/* ts1_source, disable */
+	 NOT_SUPPORTED,		/* ts2_source */
+	 NOT_SUPPORTED,		/* analog source */
+
+	 0,			/* digital_index  */
+	 0,			/* analog index */
+	 0,			/* dif_index */
+	 0,			/* external_index */
+
+	 1,			/* only one configuration */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index  = 2 */
+	    1,			/* ts1 index */
+	    NOT_SUPPORTED,	/* TS2 index */
+	    NOT_SUPPORTED,	/* AUDIO */
+	    NOT_SUPPORTED,	/* VIDEO */
+	    NOT_SUPPORTED,	/* VANC */
+	    NOT_SUPPORTED,	/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 ,
+	 /* full-speed */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index  = 2 */
+	    1,			/* ts1 index */
+	    NOT_SUPPORTED,	/* TS2 index */
+	    NOT_SUPPORTED,	/* AUDIO */
+	    NOT_SUPPORTED,	/* VIDEO */
+	    NOT_SUPPORTED,	/* VANC */
+	    NOT_SUPPORTED,	/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 }
+	,
+	{
+	 INDEX_BUSPOWER_ANALOG_ONLY,	/* index */
+	 USB_BUS_POWER,		/* power_type */
+	 0,			/* speed , not decide yet */
+	 MOD_ANALOG,		/* mode ,analog tv AND DIGITAL path */
+	 NOT_SUPPORTED,		/* ts1_source, disable */
+	 NOT_SUPPORTED,		/* ts2_source */
+	 SOURCE_ANALOG,		/* analog source--analog */
+	 0,			/* digital_index  */
+	 0,			/* analog index */
+	 0,			/* dif_index */
+	 0,			/* external_index */
+	 1,			/* only one configuration */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    NOT_SUPPORTED,	/* ts1 index */
+	    NOT_SUPPORTED,	/* TS2 index */
+	    1,			/* AUDIO */
+	    2,			/* VIDEO */
+	    3,			/* VANC */
+	    4,			/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 ,
+	 {			/* full-speed */
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    NOT_SUPPORTED,	/* ts1 index */
+	    NOT_SUPPORTED,	/* TS2 index */
+	    1,			/* AUDIO */
+	    2,			/* VIDEO */
+	    NOT_SUPPORTED,	/* VANC */
+	    NOT_SUPPORTED,	/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 }
+	,
+	{
+	 INDEX_BUSPOWER_DIF_ONLY,	/* index */
+	 USB_BUS_POWER,		/* power_type */
+	 0,			/* speed , not decide yet */
+	 /* mode ,analog tv AND DIGITAL path */
+	 MOD_DIF | MOD_ANALOG | MOD_DIGITAL | MOD_EXTERNAL,
+	 SOURCE_TS_BDA,		/* ts1_source, disable */
+	 NOT_SUPPORTED,		/* ts2_source */
+	 SOURCE_DIF | SOURCE_ANALOG | SOURCE_EXTERNAL,	/* analog source, dif */
+	 0,			/* digital_index  */
+	 0,			/* analog index */
+	 0,			/* dif_index */
+	 0,			/* external_index */
+	 1,			/* only one configuration */
+	 {
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    1,			/* ts1 index */
+	    NOT_SUPPORTED,	/* TS2 index */
+	    2,			/* AUDIO */
+	    3,			/* VIDEO */
+	    4,			/* VANC */
+	    5,			/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 ,
+	 {			/* full speed */
+	  {
+	   0,			/* config index */
+	   {
+	    0,			/* interrupt ep index */
+	    1,			/* ts1 index */
+	    NOT_SUPPORTED,	/* TS2 index */
+	    2,			/* AUDIO */
+	    3,			/* VIDEO */
+	    NOT_SUPPORTED,	/* VANC */
+	    NOT_SUPPORTED,	/* HANC */
+	    NOT_SUPPORTED	/* ir_index */
+	    }
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  ,
+	  {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+			   NOT_SUPPORTED}
+	   }
+	  }
+	 }
+	,
+
+};
+
+/*****************************************************************/
+
+u32 initialize_cx231xx(struct cx231xx *dev)
+{
+	u32 config_info = 0;
+	struct pcb_config *p_pcb_info;
+	u8 usb_speed = 1;	/* from register,1--HS, 0--FS  */
+	u8 data[4] = { 0, 0, 0, 0 };
+	u32 ts1_source = 0;
+	u32 ts2_source = 0;
+	u32 analog_source = 0;
+	u8 _current_scenario_idx = 0xff;
+
+	ts1_source = SOURCE_TS_BDA;
+	ts2_source = SOURCE_TS_BDA;
+
+	/* read board config register to find out which
+	pcb config it is related to */
+	cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT, data, 4);
+
+	config_info = *((u32 *) data);
+	usb_speed = (u8) (config_info & 0x1);
+
+	/* Verify this device belongs to Bus power or Self power device */
+	if (config_info & BUS_POWER) {	/* bus-power */
+		switch (config_info & BUSPOWER_MASK) {
+		case TS1_PORT | BUS_POWER:
+			cx231xx_Scenario[INDEX_BUSPOWER_DIGITAL_ONLY].speed =
+			    usb_speed;
+			p_pcb_info =
+			    &cx231xx_Scenario[INDEX_BUSPOWER_DIGITAL_ONLY];
+			_current_scenario_idx = INDEX_BUSPOWER_DIGITAL_ONLY;
+			break;
+		case AVDEC_ENABLE | BUS_POWER:
+			cx231xx_Scenario[INDEX_BUSPOWER_ANALOG_ONLY].speed =
+			    usb_speed;
+			p_pcb_info =
+			    &cx231xx_Scenario[INDEX_BUSPOWER_ANALOG_ONLY];
+			_current_scenario_idx = INDEX_BUSPOWER_ANALOG_ONLY;
+			break;
+		case AVDEC_ENABLE | BUS_POWER | TS1_PORT:
+			cx231xx_Scenario[INDEX_BUSPOWER_DIF_ONLY].speed =
+			    usb_speed;
+			p_pcb_info = &cx231xx_Scenario[INDEX_BUSPOWER_DIF_ONLY];
+			_current_scenario_idx = INDEX_BUSPOWER_DIF_ONLY;
+			break;
+		default:
+			cx231xx_info("bad config in buspower!!!!\n");
+			cx231xx_info("config_info=%x\n",
+				     (config_info & BUSPOWER_MASK));
+			return 1;
+		}
+	} else {		/* self-power */
+
+		switch (config_info & SELFPOWER_MASK) {
+		case TS1_PORT | SELF_POWER:
+			cx231xx_Scenario[INDEX_SELFPOWER_DIGITAL_ONLY].speed =
+			    usb_speed;
+			p_pcb_info =
+			    &cx231xx_Scenario[INDEX_SELFPOWER_DIGITAL_ONLY];
+			_current_scenario_idx = INDEX_SELFPOWER_DIGITAL_ONLY;
+			break;
+		case TS1_TS2_PORT | SELF_POWER:
+			cx231xx_Scenario[INDEX_SELFPOWER_DUAL_DIGITAL].speed =
+			    usb_speed;
+			cx231xx_Scenario[INDEX_SELFPOWER_DUAL_DIGITAL].
+			    ts2_source = ts2_source;
+			p_pcb_info =
+			    &cx231xx_Scenario[INDEX_SELFPOWER_DUAL_DIGITAL];
+			_current_scenario_idx = INDEX_SELFPOWER_DUAL_DIGITAL;
+			break;
+		case AVDEC_ENABLE | SELF_POWER:
+			cx231xx_Scenario[INDEX_SELFPOWER_ANALOG_ONLY].speed =
+			    usb_speed;
+			cx231xx_Scenario[INDEX_SELFPOWER_ANALOG_ONLY].
+			    analog_source = analog_source;
+			p_pcb_info =
+			    &cx231xx_Scenario[INDEX_SELFPOWER_ANALOG_ONLY];
+			_current_scenario_idx = INDEX_SELFPOWER_ANALOG_ONLY;
+			break;
+		case AVDEC_ENABLE | TS1_PORT | SELF_POWER:
+			cx231xx_Scenario[INDEX_SELFPOWER_DUAL].speed =
+			    usb_speed;
+			cx231xx_Scenario[INDEX_SELFPOWER_DUAL].ts1_source =
+			    ts1_source;
+			cx231xx_Scenario[INDEX_SELFPOWER_DUAL].analog_source =
+			    analog_source;
+			p_pcb_info = &cx231xx_Scenario[INDEX_SELFPOWER_DUAL];
+			_current_scenario_idx = INDEX_SELFPOWER_DUAL;
+			break;
+		case AVDEC_ENABLE | TS1_TS2_PORT | SELF_POWER:
+			cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].speed =
+			    usb_speed;
+			cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].ts1_source =
+			    ts1_source;
+			cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].ts2_source =
+			    ts2_source;
+			cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].analog_source =
+			    analog_source;
+			p_pcb_info = &cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE];
+			_current_scenario_idx = INDEX_SELFPOWER_TRIPLE;
+			break;
+		case AVDEC_ENABLE | TS1VIP_TS2_PORT | SELF_POWER:
+			cx231xx_Scenario[INDEX_SELFPOWER_COMPRESSOR].speed =
+			    usb_speed;
+			cx231xx_Scenario[INDEX_SELFPOWER_COMPRESSOR].
+			    analog_source = analog_source;
+			p_pcb_info =
+			    &cx231xx_Scenario[INDEX_SELFPOWER_COMPRESSOR];
+			_current_scenario_idx = INDEX_SELFPOWER_COMPRESSOR;
+			break;
+		default:
+			cx231xx_info("bad senario!!!!!\n");
+			cx231xx_info("config_info=%x\n",
+				     (config_info & SELFPOWER_MASK));
+			return 1;
+		}
+	}
+
+	dev->current_scenario_idx = _current_scenario_idx;
+
+	memcpy(&dev->current_pcb_config, p_pcb_info,
+		   sizeof(struct pcb_config));
+
+	if (pcb_debug) {
+		cx231xx_info("SC(0x00) register = 0x%x\n", config_info);
+		cx231xx_info("scenario %d\n",
+			    (dev->current_pcb_config.index) + 1);
+		cx231xx_info("type=%x\n", dev->current_pcb_config.type);
+		cx231xx_info("mode=%x\n", dev->current_pcb_config.mode);
+		cx231xx_info("speed=%x\n", dev->current_pcb_config.speed);
+		cx231xx_info("ts1_source=%x\n",
+			     dev->current_pcb_config.ts1_source);
+		cx231xx_info("ts2_source=%x\n",
+			     dev->current_pcb_config.ts2_source);
+		cx231xx_info("analog_source=%x\n",
+			     dev->current_pcb_config.analog_source);
+	}
+
+	return 0;
+}
diff --git a/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h b/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h
new file mode 100644
index 0000000..f5e46e8
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h
@@ -0,0 +1,231 @@
+/*
+   cx231xx-pcb-cfg.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 _PCB_CONFIG_H_
+#define _PCB_CONFIG_H_
+
+#include <linux/init.h>
+#include <linux/module.h>
+
+/***************************************************************************
+				* Class Information *
+***************************************************************************/
+#define CLASS_DEFAULT       0xFF
+
+enum VENDOR_REQUEST_TYPE {
+	/* Set/Get I2C */
+	VRT_SET_I2C0 = 0x0,
+	VRT_SET_I2C1 = 0x1,
+	VRT_SET_I2C2 = 0x2,
+	VRT_GET_I2C0 = 0x4,
+	VRT_GET_I2C1 = 0x5,
+	VRT_GET_I2C2 = 0x6,
+
+	/* Set/Get GPIO */
+	VRT_SET_GPIO = 0x8,
+	VRT_GET_GPIO = 0x9,
+
+	/* Set/Get GPIE */
+	VRT_SET_GPIE = 0xA,
+	VRT_GET_GPIE = 0xB,
+
+	/* Set/Get Register Control/Status */
+	VRT_SET_REGISTER = 0xC,
+	VRT_GET_REGISTER = 0xD,
+
+	/* Get Extended Compat ID Descriptor */
+	VRT_GET_EXTCID_DESC = 0xFF,
+};
+
+enum BYTE_ENABLE_MASK {
+	ENABLE_ONE_BYTE = 0x1,
+	ENABLE_TWE_BYTE = 0x3,
+	ENABLE_THREE_BYTE = 0x7,
+	ENABLE_FOUR_BYTE = 0xF,
+};
+
+#define SPEED_MASK      0x1
+enum USB_SPEED{
+	FULL_SPEED = 0x0,	/* 0: full speed */
+	HIGH_SPEED = 0x1	/* 1: high speed */
+};
+
+enum _true_false{
+	FALSE = 0,
+	TRUE = 1
+};
+
+#define TS_MASK         0x6
+enum TS_PORT{
+	NO_TS_PORT = 0x0,	/* 2'b00: Neither port used. PCB not a Hybrid,
+				   only offers Analog TV or Video */
+	TS1_PORT = 0x4,		/* 2'b10: TS1 Input (Hybrid mode :
+				Digital or External Analog/Compressed source) */
+	TS1_TS2_PORT = 0x6,	/* 2'b11: TS1 & TS2 Inputs
+				(Dual inputs from Digital and/or
+				External Analog/Compressed sources) */
+	TS1_EXT_CLOCK = 0x6,	/* 2'b11: TS1 & TS2 as selector
+						to external clock */
+	TS1VIP_TS2_PORT = 0x2	/* 2'b01: TS1 used as 656/VIP Output,
+				   TS2 Input (from Compressor) */
+};
+
+#define EAVP_MASK       0x8
+enum EAV_PRESENT{
+	NO_EXTERNAL_AV = 0x0,	/* 0: No External A/V inputs
+						(no need for i2s blcok),
+						Analog Tuner must be present */
+	EXTERNAL_AV = 0x8	/* 1: External A/V inputs
+						present (requires i2s blk) */
+};
+
+#define ATM_MASK        0x30
+enum AT_MODE{
+	DIF_TUNER = 0x30,	/* 2'b11: IF Tuner (requires use of DIF) */
+	BASEBAND_SOUND = 0x20,	/* 2'b10: Baseband Composite &
+						Sound-IF Signals present */
+	NO_TUNER = 0x10		/* 2'b0x: No Analog Tuner present */
+};
+
+#define PWR_SEL_MASK    0x40
+enum POWE_TYPE{
+	SELF_POWER = 0x0,	/* 0: self power */
+	BUS_POWER = 0x40	/* 1: bus power */
+};
+
+enum USB_POWE_TYPE{
+	USB_SELF_POWER = 0,
+	USB_BUS_POWER
+};
+
+#define BO_0_MASK       0x80
+enum AVDEC_STATUS{
+	AVDEC_DISABLE = 0x0,	/* 0: A/V Decoder Disabled */
+	AVDEC_ENABLE = 0x80	/* 1: A/V Decoder Enabled */
+};
+
+#define BO_1_MASK       0x100
+
+#define BUSPOWER_MASK   0xC4	/* for Polaris spec 0.8 */
+#define SELFPOWER_MASK  0x86
+
+/***************************************************************************/
+#define NOT_DECIDE_YET  0xFE
+#define NOT_SUPPORTED   0xFF
+
+/***************************************************************************
+				* for mod field use *
+***************************************************************************/
+#define MOD_DIGITAL     0x1
+#define MOD_ANALOG      0x2
+#define MOD_DIF         0x4
+#define MOD_EXTERNAL    0x8
+#define CAP_ALL_MOD     0x0f
+
+/***************************************************************************
+				* source define *
+***************************************************************************/
+#define SOURCE_DIGITAL          0x1
+#define SOURCE_ANALOG           0x2
+#define SOURCE_DIF              0x4
+#define SOURCE_EXTERNAL         0x8
+#define SOURCE_TS_BDA			0x10
+#define SOURCE_TS_ENCODE		0x20
+#define SOURCE_TS_EXTERNAL   	0x40
+
+/***************************************************************************
+				* interface information define *
+***************************************************************************/
+struct INTERFACE_INFO {
+	u8 interrupt_index;
+	u8 ts1_index;
+	u8 ts2_index;
+	u8 audio_index;
+	u8 video_index;
+	u8 vanc_index;		/* VBI */
+	u8 hanc_index;		/* Sliced CC */
+	u8 ir_index;
+};
+
+enum INDEX_INTERFACE_INFO{
+	INDEX_INTERRUPT = 0x0,
+	INDEX_TS1,
+	INDEX_TS2,
+	INDEX_AUDIO,
+	INDEX_VIDEO,
+	INDEX_VANC,
+	INDEX_HANC,
+	INDEX_IR,
+};
+
+/***************************************************************************
+				* configuration information define *
+***************************************************************************/
+struct CONFIG_INFO {
+	u8 config_index;
+	struct INTERFACE_INFO interface_info;
+};
+
+struct pcb_config {
+	u8 index;
+	u8 type;		/* bus power or self power,
+					   self power--0, bus_power--1 */
+	u8 speed;		/* usb speed, 2.0--1, 1.1--0 */
+	u8 mode;		/* digital , anlog, dif or external A/V */
+	u32 ts1_source;		/* three source -- BDA,External,encode */
+	u32 ts2_source;
+	u32 analog_source;
+	u8 digital_index;	/* bus-power used */
+	u8 analog_index;	/* bus-power used */
+	u8 dif_index;		/* bus-power used */
+	u8 external_index;	/* bus-power used */
+	u8 config_num;		/* current config num, 0,1,2,
+						   for self-power, always 0 */
+	struct CONFIG_INFO hs_config_info[3];
+	struct CONFIG_INFO fs_config_info[3];
+};
+
+enum INDEX_PCB_CONFIG{
+	INDEX_SELFPOWER_DIGITAL_ONLY = 0x0,
+	INDEX_SELFPOWER_DUAL_DIGITAL,
+	INDEX_SELFPOWER_ANALOG_ONLY,
+	INDEX_SELFPOWER_DUAL,
+	INDEX_SELFPOWER_TRIPLE,
+	INDEX_SELFPOWER_COMPRESSOR,
+	INDEX_BUSPOWER_DIGITAL_ONLY,
+	INDEX_BUSPOWER_ANALOG_ONLY,
+	INDEX_BUSPOWER_DIF_ONLY,
+	INDEX_BUSPOWER_EXTERNAL_ONLY,
+	INDEX_BUSPOWER_EXTERNAL_ANALOG,
+	INDEX_BUSPOWER_EXTERNAL_DIF,
+	INDEX_BUSPOWER_EXTERNAL_DIGITAL,
+	INDEX_BUSPOWER_DIGITAL_ANALOG,
+	INDEX_BUSPOWER_DIGITAL_DIF,
+	INDEX_BUSPOWER_DIGITAL_ANALOG_EXTERNAL,
+	INDEX_BUSPOWER_DIGITAL_DIF_EXTERNAL,
+};
+
+/***************************************************************************/
+struct cx231xx;
+
+u32 initialize_cx231xx(struct cx231xx *p_dev);
+
+#endif
diff --git a/drivers/media/video/cx231xx/cx231xx-reg.h b/drivers/media/video/cx231xx/cx231xx-reg.h
new file mode 100644
index 0000000..750c5d3
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx-reg.h
@@ -0,0 +1,1564 @@
+/*
+   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          0x00000070
+#define      FLD_PATH1_SC_RMS_CON     0x0000000f
+
+/*****************************************************************************/
+#define      PATH2_CTL1               0x8e0
+/* Reserved [31:26] */
+#define      FLD_PATH2_MUTE_CTL       0x03000000
+/* Reserved [23:22] */
+#define      FLD_PATH2_AVC_CG         0x00300000
+#define      FLD_PATH2_AVC_RT         0x000f0000
+#define      FLD_PATH2_AVC_AT         0x0000f000
+#define      FLD_PATH2_AVC_STEREO     0x00000800
+#define      FLD_PATH2_AVC_CR         0x00000700
+#define      FLD_PATH2_AVC_RMS_CON    0x000000f0
+#define      FLD_PATH2_SEL_CTL        0x0000000f
+
+/*****************************************************************************/
+#define      PATH2_VOL_CTL            0x8e4
+#define      FLD_PATH2_AVC_THRESHOLD  0xffff0000
+#define      FLD_PATH2_BAL_LEFT       0x00008000
+#define      FLD_PATH2_BAL_LEVEL      0x00007f00
+#define      FLD_PATH2_VOLUME         0x000000ff
+
+/*****************************************************************************/
+#define      PATH2_EQ_CTL             0x8e8
+/* Reserved [31:30] */
+#define      FLD_PATH2_EQ_TREBLE_VOL  0x3f000000
+/* Reserved [23:22] */
+#define      FLD_PATH2_EQ_MID_VOL     0x003f0000
+/* Reserved [15:14] */
+#define      FLD_PATH2_EQ_BASS_VOL    0x00003f00
+/* Reserved [7:1] */
+#define      FLD_PATH2_EQ_BAND_SEL    0x00000001
+
+/*****************************************************************************/
+#define      PATH2_SC_CTL             0x8eC
+#define      FLD_PATH2_SC_THRESHOLD   0xffff0000
+#define      FLD_PATH2_SC_RT          0x0000f000
+#define      FLD_PATH2_SC_AT          0x00000f00
+#define      FLD_PATH2_SC_STEREO      0x00000080
+#define      FLD_PATH2_SC_CR          0x00000070
+#define      FLD_PATH2_SC_RMS_CON     0x0000000f
+
+/*****************************************************************************/
+#define      SRC_CTL                  0x8f0
+#define      FLD_SRC_STATUS           0xffffff00
+#define      FLD_FIFO_LF_EN           0x000000fc
+#define      FLD_BYPASS_LI            0x00000002
+#define      FLD_BYPASS_PF            0x00000001
+
+/*****************************************************************************/
+#define      SRC_LF_COEF              0x8f4
+#define      FLD_LOOP_FILTER_COEF2    0xffff0000
+#define      FLD_LOOP_FILTER_COEF1    0x0000ffff
+
+/*****************************************************************************/
+#define      SRC1_CTL                 0x8f8
+/* Reserved [31:28] */
+#define      FLD_SRC1_FIFO_RD_TH      0x0f000000
+/* Reserved [23:18] */
+#define      FLD_SRC1_PHASE_INC       0x0003ffff
+
+/*****************************************************************************/
+#define      SRC2_CTL                 0x8fc
+/* Reserved [31:28] */
+#define      FLD_SRC2_FIFO_RD_TH      0x0f000000
+/* Reserved [23:18] */
+#define      FLD_SRC2_PHASE_INC       0x0003ffff
+
+/*****************************************************************************/
+#define      SRC3_CTL                 0x900
+/* Reserved [31:28] */
+#define      FLD_SRC3_FIFO_RD_TH      0x0f000000
+/* Reserved [23:18] */
+#define      FLD_SRC3_PHASE_INC       0x0003ffff
+
+/*****************************************************************************/
+#define      SRC4_CTL                 0x904
+/* Reserved [31:28] */
+#define      FLD_SRC4_FIFO_RD_TH      0x0f000000
+/* Reserved [23:18] */
+#define      FLD_SRC4_PHASE_INC       0x0003ffff
+
+/*****************************************************************************/
+#define      SRC5_CTL                 0x908
+/* Reserved [31:28] */
+#define      FLD_SRC5_FIFO_RD_TH      0x0f000000
+/* Reserved [23:18] */
+#define      FLD_SRC5_PHASE_INC       0x0003ffff
+
+/*****************************************************************************/
+#define      SRC6_CTL                 0x90c
+/* Reserved [31:28] */
+#define      FLD_SRC6_FIFO_RD_TH      0x0f000000
+/* Reserved [23:18] */
+#define      FLD_SRC6_PHASE_INC       0x0003ffff
+
+/*****************************************************************************/
+#define      BAND_OUT_SEL             0x910
+#define      FLD_SRC6_IN_SEL          0xc0000000
+#define      FLD_SRC6_CLK_SEL         0x30000000
+#define      FLD_SRC5_IN_SEL          0x0c000000
+#define      FLD_SRC5_CLK_SEL         0x03000000
+#define      FLD_SRC4_IN_SEL          0x00c00000
+#define      FLD_SRC4_CLK_SEL         0x00300000
+#define      FLD_SRC3_IN_SEL          0x000c0000
+#define      FLD_SRC3_CLK_SEL         0x00030000
+#define      FLD_BASEBAND_BYPASS_CTL  0x0000ff00
+#define      FLD_AC97_SRC_SEL         0x000000c0
+#define      FLD_I2S_SRC_SEL          0x00000030
+#define      FLD_PARALLEL2_SRC_SEL    0x0000000c
+#define      FLD_PARALLEL1_SRC_SEL    0x00000003
+
+/*****************************************************************************/
+#define      I2S_IN_CTL               0x914
+/* Reserved [31:11] */
+#define      FLD_I2S_UP2X_BW20K       0x00000400
+#define      FLD_I2S_UP2X_BYPASS      0x00000200
+#define      FLD_I2S_IN_MASTER_MODE   0x00000100
+#define      FLD_I2S_IN_SONY_MODE     0x00000080
+#define      FLD_I2S_IN_RIGHT_JUST    0x00000040
+#define      FLD_I2S_IN_WS_SEL        0x00000020
+#define      FLD_I2S_IN_BCN_DEL       0x0000001f
+
+/*****************************************************************************/
+#define      I2S_OUT_CTL              0x918
+/* Reserved [31:17] */
+#define      FLD_I2S_OUT_SOFT_RESET_EN  0x00010000
+/* Reserved [15:9] */
+#define      FLD_I2S_OUT_MASTER_MODE  0x00000100
+#define      FLD_I2S_OUT_SONY_MODE    0x00000080
+#define      FLD_I2S_OUT_RIGHT_JUST   0x00000040
+#define      FLD_I2S_OUT_WS_SEL       0x00000020
+#define      FLD_I2S_OUT_BCN_DEL      0x0000001f
+
+/*****************************************************************************/
+#define      AC97_CTL                 0x91c
+/* Reserved [31:26] */
+#define      FLD_AC97_UP2X_BW20K      0x02000000
+#define      FLD_AC97_UP2X_BYPASS     0x01000000
+/* Reserved [23:17] */
+#define      FLD_AC97_RST_ACL         0x00010000
+/* Reserved [15:9] */
+#define      FLD_AC97_WAKE_UP_SYNC    0x00000100
+/* Reserved [7:1] */
+#define      FLD_AC97_SHUTDOWN        0x00000001
+
+/* Cx231xx redefine */
+#define      QPSK_IAGC_CTL1  		0x94c
+#define      QPSK_IAGC_CTL2  		0x950
+#define      QPSK_FEPR_FREQ  		0x954
+#define      QPSK_BTL_CTL1  		0x958
+#define      QPSK_BTL_CTL2  		0x95c
+#define      QPSK_CTL_CTL1  		0x960
+#define      QPSK_CTL_CTL2  		0x964
+#define      QPSK_MF_FAGC_CTL 		0x968
+#define      QPSK_EQ_CTL  		0x96c
+#define      QPSK_LOCK_CTL  		0x970
+
+/*****************************************************************************/
+#define      FM1_DFT_CTL              0x9a8
+#define      FLD_FM1_DFT_THRESHOLD    0xffff0000
+/* Reserved [15:8] */
+#define      FLD_FM1_DFT_CMP_CTL      0x00000080
+#define      FLD_FM1_DFT_AVG          0x00000070
+/* Reserved [3:1] */
+#define      FLD_FM1_DFT_START        0x00000001
+
+/*****************************************************************************/
+#define      FM1_DFT_STATUS           0x9ac
+#define      FLD_FM1_DFT_DONE         0x80000000
+/* Reserved [30:19] */
+#define      FLD_FM_DFT_TH_CMP        0x00040000
+#define      FLD_FM1_DFT              0x0003ffff
+
+/*****************************************************************************/
+#define      FM2_DFT_CTL              0x9b0
+#define      FLD_FM2_DFT_THRESHOLD    0xffff0000
+/* Reserved [15:8] */
+#define      FLD_FM2_DFT_CMP_CTL      0x00000080
+#define      FLD_FM2_DFT_AVG          0x00000070
+/* Reserved [3:1] */
+#define      FLD_FM2_DFT_START        0x00000001
+
+/*****************************************************************************/
+#define      FM2_DFT_STATUS           0x9b4
+#define      FLD_FM2_DFT_DONE         0x80000000
+/* Reserved [30:19] */
+#define      FLD_FM2_DFT_TH_CMP_STAT  0x00040000
+#define      FLD_FM2_DFT              0x0003ffff
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      AAGC_STATUS_REG          0x9b8
+#define      AAGC_STATUS              0x9b8
+/* Reserved [31:27] */
+#define      FLD_FM2_DAGC_OUT         0x07000000
+/* Reserved [23:19] */
+#define      FLD_FM1_DAGC_OUT         0x00070000
+/* Reserved [15:6] */
+#define      FLD_AFE_VGA_OUT          0x0000003f
+
+/*****************************************************************************/
+#define      MTS_GAIN_STATUS          0x9bc
+/* Reserved [31:14] */
+#define      FLD_MTS_GAIN             0x00003fff
+
+#define      RDS_OUT                  0x9c0
+#define      FLD_RDS_Q                0xffff0000
+#define      FLD_RDS_I                0x0000ffff
+
+/*****************************************************************************/
+#define      AUTOCONFIG_REG           0x9c4
+/* Reserved [31:4] */
+#define      FLD_AUTOCONFIG_MODE      0x0000000f
+
+#define      FM_AFC                   0x9c8
+#define      FLD_FM2_AFC              0xffff0000
+#define      FLD_FM1_AFC              0x0000ffff
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      NEW_SPARE                0x9cc
+#define      NEW_SPARE_REG            0x9cc
+
+/*****************************************************************************/
+#define      DBX_ADJ                  0x9d0
+/* Reserved [31:28] */
+#define      FLD_DBX2_ADJ             0x0fff0000
+/* Reserved [15:12] */
+#define      FLD_DBX1_ADJ             0x00000fff
+
+#define      VID_FMT_AUTO              0
+#define      VID_FMT_NTSC_M            1
+#define      VID_FMT_NTSC_J            2
+#define      VID_FMT_NTSC_443          3
+#define      VID_FMT_PAL_BDGHI         4
+#define      VID_FMT_PAL_M             5
+#define      VID_FMT_PAL_N             6
+#define      VID_FMT_PAL_NC            7
+#define      VID_FMT_PAL_60            8
+#define      VID_FMT_SECAM             12
+#define      VID_FMT_SECAM_60          13
+
+#define      INPUT_MODE_CVBS_0         0       /* INPUT_MODE_VALUE(0) */
+#define      INPUT_MODE_YC_1           1       /* INPUT_MODE_VALUE(1) */
+#define      INPUT_MODE_YC2_2          2       /* INPUT_MODE_VALUE(2) */
+#define      INPUT_MODE_YUV_3          3       /* INPUT_MODE_VALUE(3) */
+
+#define      LUMA_LPF_LOW_BANDPASS     0       /* 0.6Mhz LPF BW */
+#define      LUMA_LPF_MEDIUM_BANDPASS  1       /* 1.0Mhz LPF BW */
+#define      LUMA_LPF_HIGH_BANDPASS    2       /* 1.5Mhz LPF BW */
+
+#define      UV_LPF_LOW_BANDPASS       0       /* 0.6Mhz LPF BW */
+#define      UV_LPF_MEDIUM_BANDPASS    1       /* 1.0Mhz LPF BW */
+#define      UV_LPF_HIGH_BANDPASS      2       /* 1.5Mhz LPF BW */
+
+#define      TWO_TAP_FILT              0
+#define      THREE_TAP_FILT            1
+#define      FOUR_TAP_FILT             2
+#define      FIVE_TAP_FILT             3
+
+#define      AUD_CHAN_SRC_PARALLEL     0
+#define      AUD_CHAN_SRC_I2S_INPUT    1
+#define      AUD_CHAN_SRC_FLATIRON     2
+#define      AUD_CHAN_SRC_PARALLEL3    3
+
+#define      OUT_MODE_601              0
+#define      OUT_MODE_656              1
+#define      OUT_MODE_VIP11            2
+#define      OUT_MODE_VIP20            3
+
+#define      PHASE_INC_49MHZ          0x0df22
+#define      PHASE_INC_56MHZ          0x0fa5b
+#define      PHASE_INC_28MHZ          0x010000
+
+#endif
diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c
new file mode 100644
index 0000000..9418052
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx-vbi.c
@@ -0,0 +1,701 @@
+/*
+   cx231xx_vbi.c - driver for Conexant Cx23100/101/102 USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+	Based on cx88 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/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 <media/msp3400.h>
+#include <media/tuner.h>
+
+#include "cx231xx.h"
+#include "cx231xx-vbi.h"
+
+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) {
+		cx231xx_err(DRIVER_NAME "URB status %d [%s].\n", status,
+			    errmsg);
+	} else {
+		cx231xx_err(DRIVER_NAME "URB packet %d, status %d [%s].\n",
+			    packet, status, errmsg);
+	}
+}
+
+/*
+ * Controls the isoc copy of each urb packet
+ */
+static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb)
+{
+	struct cx231xx_buffer *buf;
+	struct cx231xx_dmaqueue *dma_q = urb->context;
+	int rc = 1;
+	unsigned char *p_buffer;
+	u32 bytes_parsed = 0, buffer_size = 0;
+	u8 sav_eav = 0;
+
+	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;
+	}
+
+	buf = dev->vbi_mode.isoc_ctl.buf;
+
+	/* get buffer pointer and length */
+	p_buffer = urb->transfer_buffer;
+	buffer_size = urb->actual_length;
+
+	if (buffer_size > 0) {
+		bytes_parsed = 0;
+
+		if (dma_q->is_partial_line) {
+			/* Handle the case where we were working on a partial
+			   line */
+			sav_eav = dma_q->last_sav;
+		} else {
+			/* Check for a SAV/EAV overlapping the
+			   buffer boundary */
+
+			sav_eav = cx231xx_find_boundary_SAV_EAV(p_buffer,
+							  dma_q->partial_buf,
+							  &bytes_parsed);
+		}
+
+		sav_eav &= 0xF0;
+		/* Get the first line if we have some portion of an SAV/EAV from
+		   the last buffer or a partial line */
+		if (sav_eav) {
+			bytes_parsed += cx231xx_get_vbi_line(dev, dma_q,
+				sav_eav,		       /* SAV/EAV */
+				p_buffer + bytes_parsed,       /* p_buffer */
+				buffer_size - bytes_parsed);   /* buffer size */
+		}
+
+		/* Now parse data that is completely in this buffer */
+		dma_q->is_partial_line = 0;
+
+		while (bytes_parsed < buffer_size) {
+			u32 bytes_used = 0;
+
+			sav_eav = cx231xx_find_next_SAV_EAV(
+				p_buffer + bytes_parsed,	/* p_buffer */
+				buffer_size - bytes_parsed, /* buffer size */
+				&bytes_used);	/* bytes used to get SAV/EAV */
+
+			bytes_parsed += bytes_used;
+
+			sav_eav &= 0xF0;
+			if (sav_eav && (bytes_parsed < buffer_size)) {
+				bytes_parsed += cx231xx_get_vbi_line(dev,
+					dma_q, sav_eav,	/* SAV/EAV */
+					p_buffer+bytes_parsed, /* p_buffer */
+					buffer_size-bytes_parsed);/*buf size*/
+			}
+		}
+
+		/* Save the last four bytes of the buffer so we can
+		check the buffer boundary condition next time */
+		memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4);
+		bytes_parsed = 0;
+	}
+
+	return rc;
+}
+
+/* ------------------------------------------------------------------
+	Vbi buf operations
+   ------------------------------------------------------------------*/
+
+static int
+vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count,
+		 unsigned int *size)
+{
+	struct cx231xx_fh *fh = vq->priv_data;
+	struct cx231xx *dev = fh->dev;
+	u32 height = 0;
+
+	height = ((dev->norm & V4L2_STD_625_50) ?
+		  PAL_VBI_LINES : NTSC_VBI_LINES);
+
+	*size = (dev->width * height * 2);
+	if (0 == *count)
+		*count = CX231XX_DEF_VBI_BUF;
+
+	if (*count < CX231XX_MIN_BUF)
+		*count = CX231XX_MIN_BUF;
+
+	return 0;
+}
+
+/* This is called *without* dev->slock held; please keep it that way */
+static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
+{
+	struct cx231xx_fh *fh = vq->priv_data;
+	struct cx231xx *dev = fh->dev;
+	unsigned long flags = 0;
+	if (in_interrupt())
+		BUG();
+
+	/* We used to wait for the buffer to finish here, but this didn't work
+	   because, as we were keeping the state as VIDEOBUF_QUEUED,
+	   videobuf_queue_cancel marked it as finished for us.
+	   (Also, it could wedge forever if the hardware was misconfigured.)
+
+	   This should be safe; by the time we get here, the buffer isn't
+	   queued anymore. If we ever start marking the buffers as
+	   VIDEOBUF_ACTIVE, it won't be, though.
+	 */
+	spin_lock_irqsave(&dev->vbi_mode.slock, flags);
+	if (dev->vbi_mode.isoc_ctl.buf == buf)
+		dev->vbi_mode.isoc_ctl.buf = NULL;
+	spin_unlock_irqrestore(&dev->vbi_mode.slock, flags);
+
+	videobuf_vmalloc_free(&buf->vb);
+	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int
+vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+		   enum v4l2_field field)
+{
+	struct cx231xx_fh *fh = vq->priv_data;
+	struct cx231xx_buffer *buf =
+	    container_of(vb, struct cx231xx_buffer, vb);
+	struct cx231xx *dev = fh->dev;
+	int rc = 0, urb_init = 0;
+	u32 height = 0;
+
+	height = ((dev->norm & V4L2_STD_625_50) ?
+		  PAL_VBI_LINES : NTSC_VBI_LINES);
+	buf->vb.size = ((dev->width << 1) * height);
+
+	if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+		return -EINVAL;
+
+	buf->vb.width = dev->width;
+	buf->vb.height = height;
+	buf->vb.field = field;
+	buf->vb.field = V4L2_FIELD_SEQ_TB;
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		rc = videobuf_iolock(vq, &buf->vb, NULL);
+		if (rc < 0)
+			goto fail;
+	}
+
+	if (!dev->vbi_mode.isoc_ctl.num_bufs)
+		urb_init = 1;
+
+	if (urb_init) {
+		rc = cx231xx_init_vbi_isoc(dev, CX231XX_NUM_VBI_PACKETS,
+					   CX231XX_NUM_VBI_BUFS,
+					   dev->vbi_mode.alt_max_pkt_size[0],
+					   cx231xx_isoc_vbi_copy);
+		if (rc < 0)
+			goto fail;
+	}
+
+	buf->vb.state = VIDEOBUF_PREPARED;
+	return 0;
+
+fail:
+	free_buffer(vq, buf);
+	return rc;
+}
+
+static void
+vbi_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+	struct cx231xx_buffer *buf =
+	    container_of(vb, struct cx231xx_buffer, vb);
+	struct cx231xx_fh *fh = vq->priv_data;
+	struct cx231xx *dev = fh->dev;
+	struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq;
+
+	buf->vb.state = VIDEOBUF_QUEUED;
+	list_add_tail(&buf->vb.queue, &vidq->active);
+
+}
+
+static void vbi_buffer_release(struct videobuf_queue *vq,
+			       struct videobuf_buffer *vb)
+{
+	struct cx231xx_buffer *buf =
+	    container_of(vb, struct cx231xx_buffer, vb);
+
+
+	free_buffer(vq, buf);
+}
+
+struct videobuf_queue_ops cx231xx_vbi_qops = {
+	.buf_setup   = vbi_buffer_setup,
+	.buf_prepare = vbi_buffer_prepare,
+	.buf_queue   = vbi_buffer_queue,
+	.buf_release = vbi_buffer_release,
+};
+
+/* ------------------------------------------------------------------
+	URB control
+   ------------------------------------------------------------------*/
+
+/*
+ * IRQ callback, called by URB callback
+ */
+static void cx231xx_irq_vbi_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, vbi_mode);
+	int rc;
+
+	switch (urb->status) {
+	case 0:		/* success */
+	case -ETIMEDOUT:	/* NAK */
+		break;
+	case -ECONNRESET:	/* kill */
+	case -ENOENT:
+	case -ESHUTDOWN:
+		return;
+	default:		/* error */
+		cx231xx_err(DRIVER_NAME "urb completition error %d.\n",
+			    urb->status);
+		break;
+	}
+
+	/* Copy data from URB */
+	spin_lock(&dev->vbi_mode.slock);
+	rc = dev->vbi_mode.isoc_ctl.isoc_copy(dev, urb);
+	spin_unlock(&dev->vbi_mode.slock);
+
+	/* Reset status */
+	urb->status = 0;
+
+	urb->status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (urb->status) {
+		cx231xx_err(DRIVER_NAME "urb resubmit failed (error=%i)\n",
+			    urb->status);
+	}
+}
+
+/*
+ * Stop and Deallocate URBs
+ */
+void cx231xx_uninit_vbi_isoc(struct cx231xx *dev)
+{
+	struct urb *urb;
+	int i;
+
+	cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_uninit_vbi_isoc\n");
+
+	dev->vbi_mode.isoc_ctl.nfields = -1;
+	for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) {
+		urb = dev->vbi_mode.isoc_ctl.urb[i];
+		if (urb) {
+			if (!irqs_disabled())
+				usb_kill_urb(urb);
+			else
+				usb_unlink_urb(urb);
+
+			if (dev->vbi_mode.isoc_ctl.transfer_buffer[i]) {
+
+				kfree(dev->vbi_mode.isoc_ctl.
+				      transfer_buffer[i]);
+				dev->vbi_mode.isoc_ctl.transfer_buffer[i] =
+				    NULL;
+			}
+			usb_free_urb(urb);
+			dev->vbi_mode.isoc_ctl.urb[i] = NULL;
+		}
+		dev->vbi_mode.isoc_ctl.transfer_buffer[i] = NULL;
+	}
+
+	kfree(dev->vbi_mode.isoc_ctl.urb);
+	kfree(dev->vbi_mode.isoc_ctl.transfer_buffer);
+
+	dev->vbi_mode.isoc_ctl.urb = NULL;
+	dev->vbi_mode.isoc_ctl.transfer_buffer = NULL;
+	dev->vbi_mode.isoc_ctl.num_bufs = 0;
+
+	cx231xx_capture_start(dev, 0, Vbi);
+}
+EXPORT_SYMBOL_GPL(cx231xx_uninit_vbi_isoc);
+
+/*
+ * Allocate URBs and start IRQ
+ */
+int cx231xx_init_vbi_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->vbi_mode.vidq;
+	int i;
+	int sb_size, pipe;
+	struct urb *urb;
+	int rc;
+
+	cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_prepare_isoc\n");
+
+	/* De-allocates all pending stuff */
+	cx231xx_uninit_vbi_isoc(dev);
+
+	/* clear if any halt */
+	usb_clear_halt(dev->udev,
+		       usb_rcvbulkpipe(dev->udev,
+				       dev->vbi_mode.end_point_addr));
+
+	dev->vbi_mode.isoc_ctl.isoc_copy = isoc_copy;
+	dev->vbi_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->bytes_left_in_line = dev->width << 1;
+	dma_q->lines_per_field = ((dev->norm & V4L2_STD_625_50) ?
+				  PAL_VBI_LINES : NTSC_VBI_LINES);
+	dma_q->lines_completed = 0;
+	for (i = 0; i < 8; i++)
+		dma_q->partial_buf[i] = 0;
+
+	dev->vbi_mode.isoc_ctl.urb = kzalloc(sizeof(void *) * num_bufs,
+					     GFP_KERNEL);
+	if (!dev->vbi_mode.isoc_ctl.urb) {
+		cx231xx_errdev("cannot alloc memory for usb buffers\n");
+		return -ENOMEM;
+	}
+
+	dev->vbi_mode.isoc_ctl.transfer_buffer =
+	    kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
+	if (!dev->vbi_mode.isoc_ctl.transfer_buffer) {
+		cx231xx_errdev("cannot allocate memory for usbtransfer\n");
+		kfree(dev->vbi_mode.isoc_ctl.urb);
+		return -ENOMEM;
+	}
+
+	dev->vbi_mode.isoc_ctl.max_pkt_size = max_pkt_size;
+	dev->vbi_mode.isoc_ctl.buf = NULL;
+
+	sb_size = max_packets * dev->vbi_mode.isoc_ctl.max_pkt_size;
+
+	/* allocate urbs and transfer buffers */
+	for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) {
+
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb) {
+			cx231xx_err(DRIVER_NAME
+				    ": cannot alloc isoc_ctl.urb %i\n", i);
+			cx231xx_uninit_vbi_isoc(dev);
+			return -ENOMEM;
+		}
+		dev->vbi_mode.isoc_ctl.urb[i] = urb;
+		urb->transfer_flags = 0;
+
+		dev->vbi_mode.isoc_ctl.transfer_buffer[i] =
+		    kzalloc(sb_size, GFP_KERNEL);
+		if (!dev->vbi_mode.isoc_ctl.transfer_buffer[i]) {
+			cx231xx_err(DRIVER_NAME
+				    ": unable to allocate %i bytes for transfer"
+				    " buffer %i%s\n", sb_size, i,
+				    in_interrupt() ? " while in int" : "");
+			cx231xx_uninit_vbi_isoc(dev);
+			return -ENOMEM;
+		}
+
+		pipe = usb_rcvbulkpipe(dev->udev, dev->vbi_mode.end_point_addr);
+		usb_fill_bulk_urb(urb, dev->udev, pipe,
+				  dev->vbi_mode.isoc_ctl.transfer_buffer[i],
+				  sb_size, cx231xx_irq_vbi_callback, dma_q);
+	}
+
+	init_waitqueue_head(&dma_q->wq);
+
+	/* submit urbs and enables IRQ */
+	for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) {
+		rc = usb_submit_urb(dev->vbi_mode.isoc_ctl.urb[i], GFP_ATOMIC);
+		if (rc) {
+			cx231xx_err(DRIVER_NAME
+				    ": submit of urb %i failed (error=%i)\n", i,
+				    rc);
+			cx231xx_uninit_vbi_isoc(dev);
+			return rc;
+		}
+	}
+
+	cx231xx_capture_start(dev, 1, Vbi);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cx231xx_init_vbi_isoc);
+
+u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+			 u8 sav_eav, u8 *p_buffer, u32 buffer_size)
+{
+	u32 bytes_copied = 0;
+	int current_field = -1;
+
+	switch (sav_eav) {
+
+	case SAV_VBI_FIELD1:
+		current_field = 1;
+		break;
+
+	case SAV_VBI_FIELD2:
+		current_field = 2;
+		break;
+	default:
+		break;
+	}
+
+	if (current_field < 0)
+		return bytes_copied;
+
+	dma_q->last_sav = sav_eav;
+
+	bytes_copied =
+	    cx231xx_copy_vbi_line(dev, dma_q, p_buffer, buffer_size,
+				  current_field);
+
+	return bytes_copied;
+}
+
+/*
+ * Announces that a buffer were filled and request the next
+ */
+static inline void vbi_buffer_filled(struct cx231xx *dev,
+				     struct cx231xx_dmaqueue *dma_q,
+				     struct cx231xx_buffer *buf)
+{
+	/* Advice that buffer was filled */
+	/* cx231xx_info(DRIVER_NAME "[%p/%d] wakeup\n", buf, buf->vb.i); */
+
+	buf->vb.state = VIDEOBUF_DONE;
+	buf->vb.field_count++;
+	do_gettimeofday(&buf->vb.ts);
+
+	dev->vbi_mode.isoc_ctl.buf = NULL;
+
+	list_del(&buf->vb.queue);
+	wake_up(&buf->vb.done);
+}
+
+u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+			  u8 *p_line, u32 length, int field_number)
+{
+	u32 bytes_to_copy;
+	struct cx231xx_buffer *buf;
+	u32 _line_size = dev->width * 2;
+
+	if (dma_q->current_field != field_number)
+		cx231xx_reset_vbi_buffer(dev, dma_q);
+
+	/* get the buffer pointer */
+	buf = dev->vbi_mode.isoc_ctl.buf;
+
+	/* Remember the field number for next time */
+	dma_q->current_field = field_number;
+
+	bytes_to_copy = dma_q->bytes_left_in_line;
+	if (bytes_to_copy > length)
+		bytes_to_copy = length;
+
+	if (dma_q->lines_completed >= dma_q->lines_per_field) {
+		dma_q->bytes_left_in_line -= bytes_to_copy;
+		dma_q->is_partial_line =
+		    (dma_q->bytes_left_in_line == 0) ? 0 : 1;
+		return 0;
+	}
+
+	dma_q->is_partial_line = 1;
+
+	/* If we don't have a buffer, just return the number of bytes we would
+	   have copied if we had a buffer. */
+	if (!buf) {
+		dma_q->bytes_left_in_line -= bytes_to_copy;
+		dma_q->is_partial_line =
+		    (dma_q->bytes_left_in_line == 0) ? 0 : 1;
+		return bytes_to_copy;
+	}
+
+	/* copy the data to video buffer */
+	cx231xx_do_vbi_copy(dev, dma_q, p_line, bytes_to_copy);
+
+	dma_q->pos += bytes_to_copy;
+	dma_q->bytes_left_in_line -= bytes_to_copy;
+
+	if (dma_q->bytes_left_in_line == 0) {
+
+		dma_q->bytes_left_in_line = _line_size;
+		dma_q->lines_completed++;
+		dma_q->is_partial_line = 0;
+
+		if (cx231xx_is_vbi_buffer_done(dev, dma_q) && buf) {
+
+			vbi_buffer_filled(dev, dma_q, buf);
+
+			dma_q->pos = 0;
+			buf = NULL;
+			dma_q->lines_completed = 0;
+		}
+	}
+
+	return bytes_to_copy;
+}
+
+/*
+ * video-buf generic routine to get the next available buffer
+ */
+static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q,
+				    struct cx231xx_buffer **buf)
+{
+	struct cx231xx_video_mode *vmode =
+	    container_of(dma_q, struct cx231xx_video_mode, vidq);
+	struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode);
+	char *outp;
+
+	if (list_empty(&dma_q->active)) {
+		cx231xx_err(DRIVER_NAME ": No active queue to serve\n");
+		dev->vbi_mode.isoc_ctl.buf = NULL;
+		*buf = NULL;
+		return;
+	}
+
+	/* Get the next buffer */
+	*buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue);
+
+	/* Cleans up buffer - Usefull for testing for frame/URB loss */
+	outp = videobuf_to_vmalloc(&(*buf)->vb);
+	memset(outp, 0, (*buf)->vb.size);
+
+	dev->vbi_mode.isoc_ctl.buf = *buf;
+
+	return;
+}
+
+void cx231xx_reset_vbi_buffer(struct cx231xx *dev,
+			      struct cx231xx_dmaqueue *dma_q)
+{
+	struct cx231xx_buffer *buf;
+
+	buf = dev->vbi_mode.isoc_ctl.buf;
+
+	if (buf == NULL) {
+		/* first try to get the buffer */
+		get_next_vbi_buf(dma_q, &buf);
+
+		dma_q->pos = 0;
+		dma_q->current_field = -1;
+	}
+
+	dma_q->bytes_left_in_line = dev->width << 1;
+	dma_q->lines_completed = 0;
+}
+
+int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+			u8 *p_buffer, u32 bytes_to_copy)
+{
+	u8 *p_out_buffer = NULL;
+	u32 current_line_bytes_copied = 0;
+	struct cx231xx_buffer *buf;
+	u32 _line_size = dev->width << 1;
+	void *startwrite;
+	int offset, lencopy;
+
+	buf = dev->vbi_mode.isoc_ctl.buf;
+
+	if (buf == NULL)
+		return -EINVAL;
+
+	p_out_buffer = videobuf_to_vmalloc(&buf->vb);
+
+	if (dma_q->bytes_left_in_line != _line_size) {
+		current_line_bytes_copied =
+		    _line_size - dma_q->bytes_left_in_line;
+	}
+
+	offset = (dma_q->lines_completed * _line_size) +
+		 current_line_bytes_copied;
+
+	/* prepare destination address */
+	startwrite = p_out_buffer + offset;
+
+	lencopy = dma_q->bytes_left_in_line > bytes_to_copy ?
+		  bytes_to_copy : dma_q->bytes_left_in_line;
+
+	memcpy(startwrite, p_buffer, lencopy);
+
+	return 0;
+}
+
+u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev,
+			      struct cx231xx_dmaqueue *dma_q)
+{
+	u32 height = 0;
+
+	height = ((dev->norm & V4L2_STD_625_50) ?
+		  PAL_VBI_LINES : NTSC_VBI_LINES);
+	return (dma_q->lines_completed == height) ? 1 : 0;
+}
diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.h b/drivers/media/video/cx231xx/cx231xx-vbi.h
new file mode 100644
index 0000000..89c7fe8
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx-vbi.h
@@ -0,0 +1,65 @@
+/*
+   cx231xx_vbi.h - driver for Conexant Cx23100/101/102 USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+		Based on cx88 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.
+ */
+
+#ifndef _CX231XX_VBI_H
+#define _CX231XX_VBI_H
+
+extern struct videobuf_queue_ops cx231xx_vbi_qops;
+
+#define   NTSC_VBI_START_LINE 10	/* line 10 - 21 */
+#define   NTSC_VBI_END_LINE   21
+#define   NTSC_VBI_LINES	  (NTSC_VBI_END_LINE-NTSC_VBI_START_LINE+1)
+
+#define   PAL_VBI_START_LINE  6
+#define   PAL_VBI_END_LINE    23
+#define   PAL_VBI_LINES       (PAL_VBI_END_LINE-PAL_VBI_START_LINE+1)
+
+#define   VBI_STRIDE            1440
+#define   VBI_SAMPLES_PER_LINE  1440
+
+#define   CX231XX_NUM_VBI_PACKETS       4
+#define   CX231XX_NUM_VBI_BUFS          5
+
+/* stream functions */
+int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
+			  int num_bufs, int max_pkt_size,
+			  int (*isoc_copy) (struct cx231xx *dev,
+					    struct urb *urb));
+
+void cx231xx_uninit_vbi_isoc(struct cx231xx *dev);
+
+/* vbi data copy functions */
+u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+			 u8 sav_eav, u8 *p_buffer, u32 buffer_size);
+
+u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+			  u8 *p_line, u32 length, int field_number);
+
+void cx231xx_reset_vbi_buffer(struct cx231xx *dev,
+			      struct cx231xx_dmaqueue *dma_q);
+
+int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+			u8 *p_buffer, u32 bytes_to_copy);
+
+u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev,
+			      struct cx231xx_dmaqueue *dma_q);
+
+#endif
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c
new file mode 100644
index 0000000..d660c08
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx-video.c
@@ -0,0 +1,2439 @@
+/*
+   cx231xx-video.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
+	Based on cx88 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/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 <media/msp3400.h>
+#include <media/tuner.h>
+
+#include "dvb_frontend.h"
+
+#include "cx231xx.h"
+#include "cx231xx-vbi.h"
+
+#define CX231XX_VERSION_CODE            KERNEL_VERSION(0, 0, 1)
+
+#define DRIVER_AUTHOR   "Srinivasa Deevi <srinivasa.deevi@conexant.com>"
+#define DRIVER_DESC     "Conexant cx231xx based USB video device driver"
+
+#define cx231xx_videodbg(fmt, arg...) do {\
+	if (video_debug) \
+		printk(KERN_INFO "%s %s :"fmt, \
+			 dev->name, __func__ , ##arg); } while (0)
+
+static unsigned int isoc_debug;
+module_param(isoc_debug, int, 0644);
+MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
+
+#define cx231xx_isocdbg(fmt, arg...) \
+do {\
+	if (isoc_debug) { \
+		printk(KERN_INFO "%s %s :"fmt, \
+			 dev->name, __func__ , ##arg); \
+	} \
+  } while (0)
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+static unsigned int card[]     = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
+static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
+static unsigned int vbi_nr[]   = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(card, int, NULL, 0444);
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(vbi_nr, int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+
+MODULE_PARM_DESC(card, "card type");
+MODULE_PARM_DESC(video_nr, "video device numbers");
+MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
+MODULE_PARM_DESC(radio_nr, "radio device numbers");
+
+static unsigned int video_debug;
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
+
+/* supported video standards */
+static struct cx231xx_fmt format[] = {
+	{
+	 .name = "16bpp YUY2, 4:2:2, packed",
+	 .fourcc = V4L2_PIX_FMT_YUYV,
+	 .depth = 16,
+	 .reg = 0,
+	 },
+};
+
+/* supported controls */
+/* Common to all boards */
+
+/* ------------------------------------------------------------------- */
+
+static const struct v4l2_queryctrl no_ctl = {
+	.name = "42",
+	.flags = V4L2_CTRL_FLAG_DISABLED,
+};
+
+static struct cx231xx_ctrl cx231xx_ctls[] = {
+	/* --- video --- */
+	{
+		.v = {
+			.id = V4L2_CID_BRIGHTNESS,
+			.name = "Brightness",
+			.minimum = 0x00,
+			.maximum = 0xff,
+			.step = 1,
+			.default_value = 0x7f,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+		},
+		.off = 128,
+		.reg = LUMA_CTRL,
+		.mask = 0x00ff,
+		.shift = 0,
+	}, {
+		.v = {
+			.id = V4L2_CID_CONTRAST,
+			.name = "Contrast",
+			.minimum = 0,
+			.maximum = 0xff,
+			.step = 1,
+			.default_value = 0x3f,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+		},
+		.off = 0,
+		.reg = LUMA_CTRL,
+		.mask = 0xff00,
+		.shift = 8,
+	}, {
+		.v = {
+			.id = V4L2_CID_HUE,
+			.name = "Hue",
+			.minimum = 0,
+			.maximum = 0xff,
+			.step = 1,
+			.default_value = 0x7f,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+		},
+		.off = 128,
+		.reg = CHROMA_CTRL,
+		.mask = 0xff0000,
+		.shift = 16,
+	}, {
+	/* strictly, this only describes only U saturation.
+	* V saturation is handled specially through code.
+	*/
+		.v = {
+			.id = V4L2_CID_SATURATION,
+			.name = "Saturation",
+			.minimum = 0,
+			.maximum = 0xff,
+			.step = 1,
+			.default_value = 0x7f,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+		},
+		.off = 0,
+		.reg = CHROMA_CTRL,
+		.mask = 0x00ff,
+		.shift = 0,
+	}, {
+		/* --- audio --- */
+		.v = {
+			.id = V4L2_CID_AUDIO_MUTE,
+			.name = "Mute",
+			.minimum = 0,
+			.maximum = 1,
+			.default_value = 1,
+			.type = V4L2_CTRL_TYPE_BOOLEAN,
+		},
+		.reg = PATH1_CTL1,
+		.mask = (0x1f << 24),
+		.shift = 24,
+	}, {
+		.v = {
+			.id = V4L2_CID_AUDIO_VOLUME,
+			.name = "Volume",
+			.minimum = 0,
+			.maximum = 0x3f,
+			.step = 1,
+			.default_value = 0x3f,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+		},
+		.reg = PATH1_VOL_CTL,
+		.mask = 0xff,
+		.shift = 0,
+	}
+};
+static const int CX231XX_CTLS = ARRAY_SIZE(cx231xx_ctls);
+
+static const u32 cx231xx_user_ctrls[] = {
+	V4L2_CID_USER_CLASS,
+	V4L2_CID_BRIGHTNESS,
+	V4L2_CID_CONTRAST,
+	V4L2_CID_SATURATION,
+	V4L2_CID_HUE,
+	V4L2_CID_AUDIO_VOLUME,
+#if 0
+	V4L2_CID_AUDIO_BALANCE,
+#endif
+	V4L2_CID_AUDIO_MUTE,
+	0
+};
+
+static const u32 *ctrl_classes[] = {
+	cx231xx_user_ctrls,
+	NULL
+};
+
+/* ------------------------------------------------------------------
+	Video buffer and parser functions
+   ------------------------------------------------------------------*/
+
+/*
+ * Announces that a buffer were filled and request the next
+ */
+static inline void buffer_filled(struct cx231xx *dev,
+				 struct cx231xx_dmaqueue *dma_q,
+				 struct cx231xx_buffer *buf)
+{
+	/* Advice that buffer was filled */
+	cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
+	buf->vb.state = VIDEOBUF_DONE;
+	buf->vb.field_count++;
+	do_gettimeofday(&buf->vb.ts);
+
+	dev->video_mode.isoc_ctl.buf = NULL;
+
+	list_del(&buf->vb.queue);
+	wake_up(&buf->vb.done);
+}
+
+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) {
+		cx231xx_isocdbg("URB status %d [%s].\n", status, errmsg);
+	} else {
+		cx231xx_isocdbg("URB packet %d, status %d [%s].\n",
+				packet, status, errmsg);
+	}
+}
+
+/*
+ * video-buf generic routine to get the next available buffer
+ */
+static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q,
+				struct cx231xx_buffer **buf)
+{
+	struct cx231xx_video_mode *vmode =
+	    container_of(dma_q, struct cx231xx_video_mode, vidq);
+	struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode);
+
+	char *outp;
+
+	if (list_empty(&dma_q->active)) {
+		cx231xx_isocdbg("No active queue to serve\n");
+		dev->video_mode.isoc_ctl.buf = NULL;
+		*buf = NULL;
+		return;
+	}
+
+	/* Get the next buffer */
+	*buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue);
+
+	/* Cleans up buffer - Usefull for testing for frame/URB loss */
+	outp = videobuf_to_vmalloc(&(*buf)->vb);
+	memset(outp, 0, (*buf)->vb.size);
+
+	dev->video_mode.isoc_ctl.buf = *buf;
+
+	return;
+}
+
+/*
+ * Controls the isoc copy of each urb packet
+ */
+static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
+{
+	struct cx231xx_buffer *buf;
+	struct cx231xx_dmaqueue *dma_q = urb->context;
+	unsigned char *outp = NULL;
+	int i, rc = 1;
+	unsigned char *p_buffer;
+	u32 bytes_parsed = 0, buffer_size = 0;
+	u8 sav_eav = 0;
+
+	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;
+	}
+
+	buf = dev->video_mode.isoc_ctl.buf;
+	if (buf != NULL)
+		outp = videobuf_to_vmalloc(&buf->vb);
+
+	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;
+		}
+
+		if (urb->iso_frame_desc[i].actual_length <= 0) {
+			/* cx231xx_isocdbg("packet %d is empty",i); - spammy */
+			continue;
+		}
+		if (urb->iso_frame_desc[i].actual_length >
+		    dev->video_mode.max_pkt_size) {
+			cx231xx_isocdbg("packet bigger than packet size");
+			continue;
+		}
+
+		/*  get buffer pointer and length */
+		p_buffer = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+		buffer_size = urb->iso_frame_desc[i].actual_length;
+		bytes_parsed = 0;
+
+		if (dma_q->is_partial_line) {
+			/* Handle the case of a partial line */
+			sav_eav = dma_q->last_sav;
+		} else {
+			/* Check for a SAV/EAV overlapping
+				the buffer boundary */
+			sav_eav =
+			    cx231xx_find_boundary_SAV_EAV(p_buffer,
+							  dma_q->partial_buf,
+							  &bytes_parsed);
+		}
+
+		sav_eav &= 0xF0;
+		/* Get the first line if we have some portion of an SAV/EAV from
+		   the last buffer or a partial line  */
+		if (sav_eav) {
+			bytes_parsed += cx231xx_get_video_line(dev, dma_q,
+				sav_eav,	/* SAV/EAV */
+				p_buffer + bytes_parsed,	/* p_buffer */
+				buffer_size - bytes_parsed);/* buf size */
+		}
+
+		/* Now parse data that is completely in this buffer */
+		/* dma_q->is_partial_line = 0;  */
+
+		while (bytes_parsed < buffer_size) {
+			u32 bytes_used = 0;
+
+			sav_eav = cx231xx_find_next_SAV_EAV(
+				p_buffer + bytes_parsed,	/* p_buffer */
+				buffer_size - bytes_parsed,	/* buf size */
+				&bytes_used);/* bytes used to get SAV/EAV */
+
+			bytes_parsed += bytes_used;
+
+			sav_eav &= 0xF0;
+			if (sav_eav && (bytes_parsed < buffer_size)) {
+				bytes_parsed += cx231xx_get_video_line(dev,
+					dma_q, sav_eav,	/* SAV/EAV */
+					p_buffer + bytes_parsed,/* p_buffer */
+					buffer_size - bytes_parsed);/*buf size*/
+			}
+		}
+
+		/* Save the last four bytes of the buffer so we can check the
+		   buffer boundary condition next time */
+		memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4);
+		bytes_parsed = 0;
+
+	}
+	return rc;
+}
+
+u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf,
+				 u32 *p_bytes_used)
+{
+	u32 bytes_used;
+	u8 boundary_bytes[8];
+	u8 sav_eav = 0;
+
+	*p_bytes_used = 0;
+
+	/* Create an array of the last 4 bytes of the last buffer and the first
+	   4 bytes of the current buffer. */
+
+	memcpy(boundary_bytes, partial_buf, 4);
+	memcpy(boundary_bytes + 4, p_buffer, 4);
+
+	/* Check for the SAV/EAV in the boundary buffer */
+	sav_eav = cx231xx_find_next_SAV_EAV((u8 *)&boundary_bytes, 8,
+					    &bytes_used);
+
+	if (sav_eav) {
+		/* found a boundary SAV/EAV.  Updates the bytes used to reflect
+		   only those used in the new buffer */
+		*p_bytes_used = bytes_used - 4;
+	}
+
+	return sav_eav;
+}
+
+u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size, u32 *p_bytes_used)
+{
+	u32 i;
+	u8 sav_eav = 0;
+
+	/*
+	 * Don't search if the buffer size is less than 4.  It causes a page
+	 * fault since buffer_size - 4 evaluates to a large number in that
+	 * case.
+	 */
+	if (buffer_size < 4) {
+		*p_bytes_used = buffer_size;
+		return 0;
+	}
+
+	for (i = 0; i < (buffer_size - 3); i++) {
+
+		if ((p_buffer[i] == 0xFF) &&
+		    (p_buffer[i + 1] == 0x00) && (p_buffer[i + 2] == 0x00)) {
+
+			*p_bytes_used = i + 4;
+			sav_eav = p_buffer[i + 3];
+			return sav_eav;
+		}
+	}
+
+	*p_bytes_used = buffer_size;
+	return 0;
+}
+
+u32 cx231xx_get_video_line(struct cx231xx *dev,
+			   struct cx231xx_dmaqueue *dma_q, u8 sav_eav,
+			   u8 *p_buffer, u32 buffer_size)
+{
+	u32 bytes_copied = 0;
+	int current_field = -1;
+
+	switch (sav_eav) {
+	case SAV_ACTIVE_VIDEO_FIELD1:
+		/* looking for skipped line which occurred in PAL 720x480 mode.
+		   In this case, there will be no active data contained
+		   between the SAV and EAV */
+		if ((buffer_size > 3) && (p_buffer[0] == 0xFF) &&
+		    (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) &&
+		    ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) ||
+		     (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) ||
+		     (p_buffer[3] == EAV_VBLANK_FIELD1) ||
+		     (p_buffer[3] == EAV_VBLANK_FIELD2)))
+			return bytes_copied;
+		current_field = 1;
+		break;
+
+	case SAV_ACTIVE_VIDEO_FIELD2:
+		/* looking for skipped line which occurred in PAL 720x480 mode.
+		   In this case, there will be no active data contained between
+		   the SAV and EAV */
+		if ((buffer_size > 3) && (p_buffer[0] == 0xFF) &&
+		    (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) &&
+		    ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) ||
+		     (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) ||
+		     (p_buffer[3] == EAV_VBLANK_FIELD1)       ||
+		     (p_buffer[3] == EAV_VBLANK_FIELD2)))
+			return bytes_copied;
+		current_field = 2;
+		break;
+	}
+
+	dma_q->last_sav = sav_eav;
+
+	bytes_copied = cx231xx_copy_video_line(dev, dma_q, p_buffer,
+					       buffer_size, current_field);
+
+	return bytes_copied;
+}
+
+u32 cx231xx_copy_video_line(struct cx231xx *dev,
+			    struct cx231xx_dmaqueue *dma_q, u8 *p_line,
+			    u32 length, int field_number)
+{
+	u32 bytes_to_copy;
+	struct cx231xx_buffer *buf;
+	u32 _line_size = dev->width * 2;
+
+	if (dma_q->current_field != field_number)
+		cx231xx_reset_video_buffer(dev, dma_q);
+
+	/* get the buffer pointer */
+	buf = dev->video_mode.isoc_ctl.buf;
+
+	/* Remember the field number for next time */
+	dma_q->current_field = field_number;
+
+	bytes_to_copy = dma_q->bytes_left_in_line;
+	if (bytes_to_copy > length)
+		bytes_to_copy = length;
+
+	if (dma_q->lines_completed >= dma_q->lines_per_field) {
+		dma_q->bytes_left_in_line -= bytes_to_copy;
+		dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ?
+					  0 : 1;
+		return 0;
+	}
+
+	dma_q->is_partial_line = 1;
+
+	/* If we don't have a buffer, just return the number of bytes we would
+	   have copied if we had a buffer. */
+	if (!buf) {
+		dma_q->bytes_left_in_line -= bytes_to_copy;
+		dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0)
+					 ? 0 : 1;
+		return bytes_to_copy;
+	}
+
+	/* copy the data to video buffer */
+	cx231xx_do_copy(dev, dma_q, p_line, bytes_to_copy);
+
+	dma_q->pos += bytes_to_copy;
+	dma_q->bytes_left_in_line -= bytes_to_copy;
+
+	if (dma_q->bytes_left_in_line == 0) {
+		dma_q->bytes_left_in_line = _line_size;
+		dma_q->lines_completed++;
+		dma_q->is_partial_line = 0;
+
+		if (cx231xx_is_buffer_done(dev, dma_q) && buf) {
+			buffer_filled(dev, dma_q, buf);
+
+			dma_q->pos = 0;
+			buf = NULL;
+			dma_q->lines_completed = 0;
+		}
+	}
+
+	return bytes_to_copy;
+}
+
+void cx231xx_reset_video_buffer(struct cx231xx *dev,
+				struct cx231xx_dmaqueue *dma_q)
+{
+	struct cx231xx_buffer *buf;
+
+	/* handle the switch from field 1 to field 2 */
+	if (dma_q->current_field == 1) {
+		if (dma_q->lines_completed >= dma_q->lines_per_field)
+			dma_q->field1_done = 1;
+		else
+			dma_q->field1_done = 0;
+	}
+
+	buf = dev->video_mode.isoc_ctl.buf;
+
+	if (buf == NULL) {
+		u8 *outp = NULL;
+		/* first try to get the buffer */
+		get_next_buf(dma_q, &buf);
+
+		if (buf)
+			outp = videobuf_to_vmalloc(&buf->vb);
+
+		dma_q->pos = 0;
+		dma_q->field1_done = 0;
+		dma_q->current_field = -1;
+	}
+
+	/* reset the counters */
+	dma_q->bytes_left_in_line = dev->width << 1;
+	dma_q->lines_completed = 0;
+}
+
+int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+		    u8 *p_buffer, u32 bytes_to_copy)
+{
+	u8 *p_out_buffer = NULL;
+	u32 current_line_bytes_copied = 0;
+	struct cx231xx_buffer *buf;
+	u32 _line_size = dev->width << 1;
+	void *startwrite;
+	int offset, lencopy;
+
+	buf = dev->video_mode.isoc_ctl.buf;
+
+	if (buf == NULL)
+		return -1;
+
+	p_out_buffer = videobuf_to_vmalloc(&buf->vb);
+
+	current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line;
+
+	/* Offset field 2 one line from the top of the buffer */
+	offset = (dma_q->current_field == 1) ? 0 : _line_size;
+
+	/* Offset for field 2 */
+	startwrite = p_out_buffer + offset;
+
+	/* lines already completed in the current field */
+	startwrite += (dma_q->lines_completed * _line_size * 2);
+
+	/* bytes already completed in the current line */
+	startwrite += current_line_bytes_copied;
+
+	lencopy = dma_q->bytes_left_in_line > bytes_to_copy ?
+		  bytes_to_copy : dma_q->bytes_left_in_line;
+
+	if ((u8 *)(startwrite + lencopy) > (u8 *)(p_out_buffer + buf->vb.size))
+		return 0;
+
+	/* The below copies the UYVY data straight into video buffer */
+	cx231xx_swab((u16 *) p_buffer, (u16 *) startwrite, (u16) lencopy);
+
+	return 0;
+}
+
+void cx231xx_swab(u16 *from, u16 *to, u16 len)
+{
+	u16 i;
+
+	if (len <= 0)
+		return;
+
+	for (i = 0; i < len / 2; i++)
+		to[i] = (from[i] << 8) | (from[i] >> 8);
+}
+
+u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q)
+{
+	u8 buffer_complete = 0;
+
+	/* Dual field stream */
+	buffer_complete = ((dma_q->current_field == 2) &&
+			   (dma_q->lines_completed >= dma_q->lines_per_field) &&
+			    dma_q->field1_done);
+
+	return buffer_complete;
+}
+
+/* ------------------------------------------------------------------
+	Videobuf operations
+   ------------------------------------------------------------------*/
+
+static int
+buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
+{
+	struct cx231xx_fh *fh = vq->priv_data;
+	struct cx231xx *dev = fh->dev;
+	struct v4l2_frequency f;
+
+	*size = (fh->dev->width * fh->dev->height * dev->format->depth + 7)>>3;
+	if (0 == *count)
+		*count = CX231XX_DEF_BUF;
+
+	if (*count < CX231XX_MIN_BUF)
+		*count = CX231XX_MIN_BUF;
+
+	/* Ask tuner to go to analog mode */
+	memset(&f, 0, sizeof(f));
+	f.frequency = dev->ctl_freq;
+	f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+
+	call_all(dev, tuner, s_frequency, &f);
+
+	return 0;
+}
+
+/* This is called *without* dev->slock held; please keep it that way */
+static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
+{
+	struct cx231xx_fh *fh = vq->priv_data;
+	struct cx231xx *dev = fh->dev;
+	unsigned long flags = 0;
+
+	if (in_interrupt())
+		BUG();
+
+	/* We used to wait for the buffer to finish here, but this didn't work
+	   because, as we were keeping the state as VIDEOBUF_QUEUED,
+	   videobuf_queue_cancel marked it as finished for us.
+	   (Also, it could wedge forever if the hardware was misconfigured.)
+
+	   This should be safe; by the time we get here, the buffer isn't
+	   queued anymore. If we ever start marking the buffers as
+	   VIDEOBUF_ACTIVE, it won't be, though.
+	 */
+	spin_lock_irqsave(&dev->video_mode.slock, flags);
+	if (dev->video_mode.isoc_ctl.buf == buf)
+		dev->video_mode.isoc_ctl.buf = NULL;
+	spin_unlock_irqrestore(&dev->video_mode.slock, flags);
+
+	videobuf_vmalloc_free(&buf->vb);
+	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int
+buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+	       enum v4l2_field field)
+{
+	struct cx231xx_fh *fh = vq->priv_data;
+	struct cx231xx_buffer *buf =
+	    container_of(vb, struct cx231xx_buffer, vb);
+	struct cx231xx *dev = fh->dev;
+	int rc = 0, urb_init = 0;
+
+	/* The only currently supported format is 16 bits/pixel */
+	buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth
+			+ 7) >> 3;
+	if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+		return -EINVAL;
+
+	buf->vb.width = dev->width;
+	buf->vb.height = dev->height;
+	buf->vb.field = field;
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		rc = videobuf_iolock(vq, &buf->vb, NULL);
+		if (rc < 0)
+			goto fail;
+	}
+
+	if (!dev->video_mode.isoc_ctl.num_bufs)
+		urb_init = 1;
+
+	if (urb_init) {
+		rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
+				       CX231XX_NUM_BUFS,
+				       dev->video_mode.max_pkt_size,
+				       cx231xx_isoc_copy);
+		if (rc < 0)
+			goto fail;
+	}
+
+	buf->vb.state = VIDEOBUF_PREPARED;
+	return 0;
+
+fail:
+	free_buffer(vq, buf);
+	return rc;
+}
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+	struct cx231xx_buffer *buf =
+	    container_of(vb, struct cx231xx_buffer, vb);
+	struct cx231xx_fh *fh = vq->priv_data;
+	struct cx231xx *dev = fh->dev;
+	struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
+
+	buf->vb.state = VIDEOBUF_QUEUED;
+	list_add_tail(&buf->vb.queue, &vidq->active);
+
+}
+
+static void buffer_release(struct videobuf_queue *vq,
+			   struct videobuf_buffer *vb)
+{
+	struct cx231xx_buffer *buf =
+	    container_of(vb, struct cx231xx_buffer, vb);
+	struct cx231xx_fh *fh = vq->priv_data;
+	struct cx231xx *dev = (struct cx231xx *)fh->dev;
+
+	cx231xx_isocdbg("cx231xx: called buffer_release\n");
+
+	free_buffer(vq, buf);
+}
+
+static struct videobuf_queue_ops cx231xx_video_qops = {
+	.buf_setup = buffer_setup,
+	.buf_prepare = buffer_prepare,
+	.buf_queue = buffer_queue,
+	.buf_release = buffer_release,
+};
+
+/*********************  v4l2 interface  **************************************/
+
+void video_mux(struct cx231xx *dev, int index)
+{
+
+	struct v4l2_routing route;
+
+	route.input = INPUT(index)->vmux;
+	route.output = 0;
+	dev->video_input = index;
+	dev->ctl_ainput = INPUT(index)->amux;
+
+	cx231xx_set_video_input_mux(dev, index);
+
+	cx25840_call(dev, video, s_routing, &route);
+
+	cx231xx_set_audio_input(dev, dev->ctl_ainput);
+
+	cx231xx_info("video_mux : %d\n", index);
+
+	/* do mode control overrides if required */
+	cx231xx_do_mode_ctrl_overrides(dev);
+}
+
+/* Usage lock check functions */
+static int res_get(struct cx231xx_fh *fh)
+{
+	struct cx231xx *dev = fh->dev;
+	int rc = 0;
+
+	/* This instance already has stream_on */
+	if (fh->stream_on)
+		return rc;
+
+	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		if (dev->stream_on)
+			return -EBUSY;
+		dev->stream_on = 1;
+	} else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+		if (dev->vbi_stream_on)
+			return -EBUSY;
+		dev->vbi_stream_on = 1;
+	} else
+		return -EINVAL;
+
+	fh->stream_on = 1;
+
+	return rc;
+}
+
+static int res_check(struct cx231xx_fh *fh)
+{
+	return fh->stream_on;
+}
+
+static void res_free(struct cx231xx_fh *fh)
+{
+	struct cx231xx *dev = fh->dev;
+
+	fh->stream_on = 0;
+
+	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		dev->stream_on = 0;
+	if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+		dev->vbi_stream_on = 0;
+}
+
+static int check_dev(struct cx231xx *dev)
+{
+	if (dev->state & DEV_DISCONNECTED) {
+		cx231xx_errdev("v4l2 ioctl: device not present\n");
+		return -ENODEV;
+	}
+
+	if (dev->state & DEV_MISCONFIGURED) {
+		cx231xx_errdev("v4l2 ioctl: device is misconfigured; "
+			       "close and open it again\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+void get_scale(struct cx231xx *dev,
+	       unsigned int width, unsigned int height,
+	       unsigned int *hscale, unsigned int *vscale)
+{
+	unsigned int maxw = norm_maxw(dev);
+	unsigned int maxh = norm_maxh(dev);
+
+	*hscale = (((unsigned long)maxw) << 12) / width - 4096L;
+	if (*hscale >= 0x4000)
+		*hscale = 0x3fff;
+
+	*vscale = (((unsigned long)maxh) << 12) / height - 4096L;
+	if (*vscale >= 0x4000)
+		*vscale = 0x3fff;
+
+	dev->hscale = *hscale;
+	dev->vscale = *vscale;
+
+}
+
+/* ------------------------------------------------------------------
+	IOCTL vidioc handling
+   ------------------------------------------------------------------*/
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+
+	mutex_lock(&dev->lock);
+
+	f->fmt.pix.width = dev->width;
+	f->fmt.pix.height = dev->height;
+	f->fmt.pix.pixelformat = dev->format->fourcc;;
+	f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;;
+	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height;
+	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+	f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+
+	mutex_unlock(&dev->lock);
+
+	return 0;
+}
+
+static struct cx231xx_fmt *format_by_fourcc(unsigned int fourcc)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(format); i++)
+		if (format[i].fourcc == fourcc)
+			return &format[i];
+
+	return NULL;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+				  struct v4l2_format *f)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int width = f->fmt.pix.width;
+	int height = f->fmt.pix.height;
+	unsigned int maxw = norm_maxw(dev);
+	unsigned int maxh = norm_maxh(dev);
+	unsigned int hscale, vscale;
+	struct cx231xx_fmt *fmt;
+
+	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+	if (!fmt) {
+		cx231xx_videodbg("Fourcc format (%08x) invalid.\n",
+				 f->fmt.pix.pixelformat);
+		return -EINVAL;
+	}
+
+	/* width must even because of the YUYV format
+	   height must be even because of interlacing */
+	height &= 0xfffe;
+	width &= 0xfffe;
+
+	if (unlikely(height < 32))
+		height = 32;
+	if (unlikely(height > maxh))
+		height = maxh;
+	if (unlikely(width < 48))
+		width = 48;
+	if (unlikely(width > maxw))
+		width = maxw;
+
+	get_scale(dev, width, height, &hscale, &vscale);
+
+	width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
+	height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
+
+	f->fmt.pix.width = width;
+	f->fmt.pix.height = height;
+	f->fmt.pix.pixelformat = fmt->fourcc;
+	f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3;
+	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
+	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+	f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+
+	return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+	struct cx231xx_fmt *fmt;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	mutex_lock(&dev->lock);
+
+	vidioc_try_fmt_vid_cap(file, priv, f);
+
+	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+	if (!fmt) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+		cx231xx_errdev("%s queue busy\n", __func__);
+		rc = -EBUSY;
+		goto out;
+	}
+
+	if (dev->stream_on && !fh->stream_on) {
+		cx231xx_errdev("%s device in use by another fh\n", __func__);
+		rc = -EBUSY;
+		goto out;
+	}
+
+	/* set new image size */
+	dev->width = f->fmt.pix.width;
+	dev->height = f->fmt.pix.height;
+	dev->format = fmt;
+	get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
+
+	call_all(dev, video, s_fmt, f);
+
+	/* Set the correct alternate setting for this resolution */
+	cx231xx_resolution_set(dev);
+
+out:
+	mutex_unlock(&dev->lock);
+	return rc;
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id * id)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+
+	*id = dev->norm;
+	return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	struct v4l2_format f;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	cx231xx_info("vidioc_s_std : 0x%x\n", (unsigned int)*norm);
+
+	mutex_lock(&dev->lock);
+	dev->norm = *norm;
+
+	/* Adjusts width/height, if needed */
+	f.fmt.pix.width = dev->width;
+	f.fmt.pix.height = dev->height;
+	vidioc_try_fmt_vid_cap(file, priv, &f);
+
+	/* set new image size */
+	dev->width = f.fmt.pix.width;
+	dev->height = f.fmt.pix.height;
+	get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
+
+	call_all(dev, tuner, s_std, dev->norm);
+
+	mutex_unlock(&dev->lock);
+
+	cx231xx_resolution_set(dev);
+
+	/* do mode control overrides */
+	cx231xx_do_mode_ctrl_overrides(dev);
+
+	return 0;
+}
+
+static const char *iname[] = {
+	[CX231XX_VMUX_COMPOSITE1] = "Composite1",
+	[CX231XX_VMUX_SVIDEO]     = "S-Video",
+	[CX231XX_VMUX_TELEVISION] = "Television",
+	[CX231XX_VMUX_CABLE]      = "Cable TV",
+	[CX231XX_VMUX_DVB]        = "DVB",
+	[CX231XX_VMUX_DEBUG]      = "for debug only",
+};
+
+static int vidioc_enum_input(struct file *file, void *priv,
+			     struct v4l2_input *i)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	unsigned int n;
+
+	n = i->index;
+	if (n >= MAX_CX231XX_INPUT)
+		return -EINVAL;
+	if (0 == INPUT(n)->type)
+		return -EINVAL;
+
+	i->index = n;
+	i->type = V4L2_INPUT_TYPE_CAMERA;
+
+	strcpy(i->name, iname[INPUT(n)->type]);
+
+	if ((CX231XX_VMUX_TELEVISION == INPUT(n)->type) ||
+	    (CX231XX_VMUX_CABLE == INPUT(n)->type))
+		i->type = V4L2_INPUT_TYPE_TUNER;
+
+	i->std = dev->vdev->tvnorms;
+
+	return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+
+	*i = dev->video_input;
+
+	return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	if (i >= MAX_CX231XX_INPUT)
+		return -EINVAL;
+	if (0 == INPUT(i)->type)
+		return -EINVAL;
+
+	mutex_lock(&dev->lock);
+
+	video_mux(dev, i);
+
+	mutex_unlock(&dev->lock);
+	return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+
+	switch (a->index) {
+	case CX231XX_AMUX_VIDEO:
+		strcpy(a->name, "Television");
+		break;
+	case CX231XX_AMUX_LINE_IN:
+		strcpy(a->name, "Line In");
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	a->index = dev->ctl_ainput;
+	a->capability = V4L2_AUDCAP_STEREO;
+
+	return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int status = 0;
+
+	/* Doesn't allow manual routing */
+	if (a->index != dev->ctl_ainput)
+		return -EINVAL;
+
+	dev->ctl_ainput = INPUT(a->index)->amux;
+	status = cx231xx_set_audio_input(dev, dev->ctl_ainput);
+
+	return status;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+			    struct v4l2_queryctrl *qc)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int id = qc->id;
+	int i;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	qc->id = v4l2_ctrl_next(ctrl_classes, qc->id);
+	if (unlikely(qc->id == 0))
+		return -EINVAL;
+
+	memset(qc, 0, sizeof(*qc));
+
+	qc->id = id;
+
+	if (qc->id < V4L2_CID_BASE || qc->id >= V4L2_CID_LASTP1)
+		return -EINVAL;
+
+	for (i = 0; i < CX231XX_CTLS; i++)
+		if (cx231xx_ctls[i].v.id == qc->id)
+			break;
+
+	if (i == CX231XX_CTLS) {
+		*qc = no_ctl;
+		return 0;
+	}
+	*qc = cx231xx_ctls[i].v;
+
+	mutex_lock(&dev->lock);
+	call_all(dev, core, queryctrl, qc);
+	mutex_unlock(&dev->lock);
+
+	if (qc->type)
+		return 0;
+	else
+		return -EINVAL;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+			 struct v4l2_control *ctrl)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	mutex_lock(&dev->lock);
+	call_all(dev, core, g_ctrl, ctrl);
+	mutex_unlock(&dev->lock);
+	return rc;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+			 struct v4l2_control *ctrl)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	mutex_lock(&dev->lock);
+	call_all(dev, core, s_ctrl, ctrl);
+	mutex_unlock(&dev->lock);
+	return rc;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	if (0 != t->index)
+		return -EINVAL;
+
+	strcpy(t->name, "Tuner");
+
+	t->type = V4L2_TUNER_ANALOG_TV;
+	t->capability = V4L2_TUNER_CAP_NORM;
+	t->rangehigh = 0xffffffffUL;
+	t->signal = 0xffff;	/* LOCKED */
+
+	return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	if (0 != t->index)
+		return -EINVAL;
+#if 0
+	mutex_lock(&dev->lock);
+	call_all(dev, tuner, s_tuner, t);
+	mutex_unlock(&dev->lock);
+#endif
+	return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+			      struct v4l2_frequency *f)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+
+	mutex_lock(&dev->lock);
+	f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+	f->frequency = dev->ctl_freq;
+
+	call_all(dev, tuner, g_frequency, f);
+
+	mutex_unlock(&dev->lock);
+
+	return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+			      struct v4l2_frequency *f)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	if (0 != f->tuner)
+		return -EINVAL;
+
+	if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))
+		return -EINVAL;
+	if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))
+		return -EINVAL;
+
+	/* set pre channel change settings in DIF first */
+	rc = cx231xx_tuner_pre_channel_change(dev);
+
+	mutex_lock(&dev->lock);
+
+	dev->ctl_freq = f->frequency;
+
+	if (dev->tuner_type == TUNER_XC5000) {
+		if (dev->cx231xx_set_analog_freq != NULL)
+			dev->cx231xx_set_analog_freq(dev, f->frequency);
+	} else
+		call_all(dev, tuner, s_frequency, f);
+
+	mutex_unlock(&dev->lock);
+
+	/* set post channel change settings in DIF first */
+	rc = cx231xx_tuner_post_channel_change(dev);
+
+	cx231xx_info("Set New FREQUENCY to %d\n", f->frequency);
+
+	return rc;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+
+/*
+  -R, --list-registers=type=<host/i2cdrv/i2caddr>,
+				chip=<chip>[,min=<addr>,max=<addr>]
+		     dump registers from <min> to <max> [VIDIOC_DBG_G_REGISTER]
+  -r, --set-register=type=<host/i2cdrv/i2caddr>,
+				chip=<chip>,reg=<addr>,val=<val>
+		     set the register [VIDIOC_DBG_S_REGISTER]
+
+  if type == host, then <chip> is the hosts chip ID (default 0)
+  if type == i2cdrv (default), then <chip> is the I2C driver name or ID
+  if type == i2caddr, then <chip> is the 7-bit I2C address
+*/
+
+static int vidioc_g_register(struct file *file, void *priv,
+			     struct v4l2_dbg_register *reg)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int ret = 0;
+	u8 value[4] = { 0, 0, 0, 0 };
+	u32 data = 0;
+
+	switch (reg->match.type) {
+	case V4L2_CHIP_MATCH_HOST:
+		switch (reg->match.addr) {
+		case 0:	/* Cx231xx - internal registers */
+			ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER,
+						  (u16)reg->reg, value, 4);
+			reg->val = value[0] | value[1] << 8 |
+				   value[2] << 16 | value[3] << 24;
+			break;
+		case 1:	/* AFE - read byte */
+			ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS,
+						  (u16)reg->reg, 2, &data, 1);
+			reg->val = le32_to_cpu(data & 0xff);
+			break;
+		case 14: /* AFE - read dword */
+			ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS,
+						  (u16)reg->reg, 2, &data, 4);
+			reg->val = le32_to_cpu(data);
+			break;
+		case 2:	/* Video Block - read byte */
+			ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
+						  (u16)reg->reg, 2, &data, 1);
+			reg->val = le32_to_cpu(data & 0xff);
+			break;
+		case 24: /* Video Block - read dword */
+			ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
+						  (u16)reg->reg, 2, &data, 4);
+			reg->val = le32_to_cpu(data);
+			break;
+		case 3:	/* I2S block - read byte */
+			ret = cx231xx_read_i2c_data(dev,
+						    I2S_BLK_DEVICE_ADDRESS,
+						    (u16)reg->reg, 1,
+						    &data, 1);
+			reg->val = le32_to_cpu(data & 0xff);
+			break;
+		case 34: /* I2S Block - read dword */
+			ret =
+			    cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+						  (u16)reg->reg, 1, &data, 4);
+			reg->val = le32_to_cpu(data);
+			break;
+		}
+		return ret < 0 ? ret : 0;
+
+	case V4L2_CHIP_MATCH_I2C_DRIVER:
+		call_all(dev, core, g_register, reg);
+		return 0;
+	case V4L2_CHIP_MATCH_I2C_ADDR:
+		/* Not supported yet */
+		return -EINVAL;
+	default:
+		if (!v4l2_chip_match_host(&reg->match))
+			return -EINVAL;
+	}
+
+	mutex_lock(&dev->lock);
+	call_all(dev, core, g_register, reg);
+	mutex_unlock(&dev->lock);
+
+	return ret;
+}
+
+static int vidioc_s_register(struct file *file, void *priv,
+			     struct v4l2_dbg_register *reg)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int ret = 0;
+	__le64 buf;
+	u32 value;
+	u8 data[4] = { 0, 0, 0, 0 };
+
+	buf = cpu_to_le64(reg->val);
+
+	switch (reg->match.type) {
+	case V4L2_CHIP_MATCH_HOST:
+		{
+			value = (u32) buf & 0xffffffff;
+
+			switch (reg->match.addr) {
+			case 0:	/* cx231xx internal registers */
+				data[0] = (u8) value;
+				data[1] = (u8) (value >> 8);
+				data[2] = (u8) (value >> 16);
+				data[3] = (u8) (value >> 24);
+				ret = cx231xx_write_ctrl_reg(dev,
+							   VRT_SET_REGISTER,
+							   (u16)reg->reg, data,
+							   4);
+				break;
+			case 1:	/* AFE - read byte */
+				ret = cx231xx_write_i2c_data(dev,
+							AFE_DEVICE_ADDRESS,
+							(u16)reg->reg, 2,
+							value, 1);
+				break;
+			case 14: /* AFE - read dword */
+				ret = cx231xx_write_i2c_data(dev,
+							AFE_DEVICE_ADDRESS,
+							(u16)reg->reg, 2,
+							value, 4);
+				break;
+			case 2:	/* Video Block - read byte */
+				ret =
+				    cx231xx_write_i2c_data(dev,
+							VID_BLK_I2C_ADDRESS,
+							(u16)reg->reg, 2,
+							value, 1);
+				break;
+			case 24: /* Video Block - read dword */
+				ret =
+				    cx231xx_write_i2c_data(dev,
+							VID_BLK_I2C_ADDRESS,
+							(u16)reg->reg, 2,
+							value, 4);
+				break;
+			case 3:	/* I2S block - read byte */
+				ret =
+				    cx231xx_write_i2c_data(dev,
+							I2S_BLK_DEVICE_ADDRESS,
+							(u16)reg->reg, 1,
+							value, 1);
+				break;
+			case 34: /* I2S block - read dword */
+				ret =
+				    cx231xx_write_i2c_data(dev,
+							I2S_BLK_DEVICE_ADDRESS,
+							(u16)reg->reg, 1,
+							value, 4);
+				break;
+			}
+		}
+		return ret < 0 ? ret : 0;
+
+	default:
+		break;
+	}
+
+	mutex_lock(&dev->lock);
+	call_all(dev, core, s_register, reg);
+	mutex_unlock(&dev->lock);
+
+	return ret;
+}
+#endif
+
+static int vidioc_cropcap(struct file *file, void *priv,
+			  struct v4l2_cropcap *cc)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+
+	if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	cc->bounds.left = 0;
+	cc->bounds.top = 0;
+	cc->bounds.width = dev->width;
+	cc->bounds.height = dev->height;
+	cc->defrect = cc->bounds;
+	cc->pixelaspect.numerator = 54;	/* 4:3 FIXME: remove magic numbers */
+	cc->pixelaspect.denominator = 59;
+
+	return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv,
+			   enum v4l2_buf_type type)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	mutex_lock(&dev->lock);
+	rc = res_get(fh);
+
+	if (likely(rc >= 0))
+		rc = videobuf_streamon(&fh->vb_vidq);
+
+	call_all(dev, video, s_stream, 1);
+
+	mutex_unlock(&dev->lock);
+
+	return rc;
+}
+
+static int vidioc_streamoff(struct file *file, void *priv,
+			    enum v4l2_buf_type type)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+	    (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
+		return -EINVAL;
+	if (type != fh->type)
+		return -EINVAL;
+
+	mutex_lock(&dev->lock);
+
+	cx25840_call(dev, video, s_stream, 0);
+
+	videobuf_streamoff(&fh->vb_vidq);
+	res_free(fh);
+
+	mutex_unlock(&dev->lock);
+
+	return 0;
+}
+
+static int vidioc_querycap(struct file *file, void *priv,
+			   struct v4l2_capability *cap)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+
+	strlcpy(cap->driver, "cx231xx", sizeof(cap->driver));
+	strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
+	usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
+
+	cap->version = CX231XX_VERSION_CODE;
+
+	cap->capabilities = V4L2_CAP_VBI_CAPTURE |
+#if 0
+		V4L2_CAP_SLICED_VBI_CAPTURE |
+#endif
+		V4L2_CAP_VIDEO_CAPTURE	|
+		V4L2_CAP_AUDIO		|
+		V4L2_CAP_READWRITE	|
+		V4L2_CAP_STREAMING;
+
+	if (dev->tuner_type != TUNER_ABSENT)
+		cap->capabilities |= V4L2_CAP_TUNER;
+
+	return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+				   struct v4l2_fmtdesc *f)
+{
+	if (unlikely(f->index >= ARRAY_SIZE(format)))
+		return -EINVAL;
+
+	strlcpy(f->description, format[f->index].name, sizeof(f->description));
+	f->pixelformat = format[f->index].fourcc;
+
+	return 0;
+}
+
+/* Sliced VBI ioctls */
+static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
+				       struct v4l2_format *f)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	mutex_lock(&dev->lock);
+
+	f->fmt.sliced.service_set = 0;
+
+	call_all(dev, video, g_fmt, f);
+
+	if (f->fmt.sliced.service_set == 0)
+		rc = -EINVAL;
+
+	mutex_unlock(&dev->lock);
+	return rc;
+}
+
+static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,
+					 struct v4l2_format *f)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	mutex_lock(&dev->lock);
+	call_all(dev, video, g_fmt, f);
+	mutex_unlock(&dev->lock);
+
+	if (f->fmt.sliced.service_set == 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* RAW VBI ioctls */
+
+static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+
+	f->fmt.vbi.sampling_rate = (dev->norm & V4L2_STD_625_50) ?
+	    35468950 : 28636363;
+	f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
+	f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+	f->fmt.vbi.offset = 64 * 4;
+	f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ?
+	    PAL_VBI_START_LINE : NTSC_VBI_START_LINE;
+	f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ?
+	    PAL_VBI_LINES : NTSC_VBI_LINES;
+	f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ?
+	    PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263;
+	f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
+
+	return 0;
+
+}
+
+static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv,
+				  struct v4l2_format *f)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+
+	if (dev->vbi_stream_on && !fh->stream_on) {
+		cx231xx_errdev("%s device in use by another fh\n", __func__);
+		return -EBUSY;
+	}
+
+	f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+	f->fmt.vbi.sampling_rate = (dev->norm & V4L2_STD_625_50) ?
+	    35468950 : 28636363;
+	f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
+	f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+	f->fmt.vbi.offset = 244;
+	f->fmt.vbi.flags = 0;
+	f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ?
+	    PAL_VBI_START_LINE : NTSC_VBI_START_LINE;
+	f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ?
+	    PAL_VBI_LINES : NTSC_VBI_LINES;
+	f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ?
+	    PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263;
+	f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
+
+	return 0;
+
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+			  struct v4l2_requestbuffers *rb)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	return videobuf_reqbufs(&fh->vb_vidq, rb);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	return videobuf_querybuf(&fh->vb_vidq, b);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	return videobuf_qbuf(&fh->vb_vidq, b);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+	struct cx231xx_fh *fh = priv;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
+}
+
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
+{
+	struct cx231xx_fh *fh = priv;
+
+	return videobuf_cgmbuf(&fh->vb_vidq, mbuf, 8);
+}
+#endif
+
+/* ----------------------------------------------------------- */
+/* RADIO ESPECIFIC IOCTLS                                      */
+/* ----------------------------------------------------------- */
+
+static int radio_querycap(struct file *file, void *priv,
+			  struct v4l2_capability *cap)
+{
+	struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
+
+	strlcpy(cap->driver, "cx231xx", sizeof(cap->driver));
+	strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
+	usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
+
+	cap->version = CX231XX_VERSION_CODE;
+	cap->capabilities = V4L2_CAP_TUNER;
+	return 0;
+}
+
+static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+	struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
+
+	if (unlikely(t->index > 0))
+		return -EINVAL;
+
+	strcpy(t->name, "Radio");
+	t->type = V4L2_TUNER_RADIO;
+
+	mutex_lock(&dev->lock);
+	call_all(dev, tuner, s_tuner, t);
+	mutex_unlock(&dev->lock);
+
+	return 0;
+}
+
+static int radio_enum_input(struct file *file, void *priv, struct v4l2_input *i)
+{
+	if (i->index != 0)
+		return -EINVAL;
+	strcpy(i->name, "Radio");
+	i->type = V4L2_INPUT_TYPE_TUNER;
+
+	return 0;
+}
+
+static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+	if (unlikely(a->index))
+		return -EINVAL;
+
+	strcpy(a->name, "Radio");
+	return 0;
+}
+
+static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+	struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
+
+	if (0 != t->index)
+		return -EINVAL;
+
+	mutex_lock(&dev->lock);
+	call_all(dev, tuner, s_tuner, t);
+	mutex_unlock(&dev->lock);
+
+	return 0;
+}
+
+static int radio_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+	return 0;
+}
+
+static int radio_s_input(struct file *file, void *fh, unsigned int i)
+{
+	return 0;
+}
+
+static int radio_queryctrl(struct file *file, void *priv,
+			   struct v4l2_queryctrl *c)
+{
+	int i;
+
+	if (c->id < V4L2_CID_BASE || c->id >= V4L2_CID_LASTP1)
+		return -EINVAL;
+	if (c->id == V4L2_CID_AUDIO_MUTE) {
+		for (i = 0; i < CX231XX_CTLS; i++)
+			if (cx231xx_ctls[i].v.id == c->id)
+				break;
+		*c = cx231xx_ctls[i].v;
+	} else
+		*c = no_ctl;
+	return 0;
+}
+
+/*
+ * cx231xx_v4l2_open()
+ * inits the device and starts isoc transfer
+ */
+static int cx231xx_v4l2_open(struct file *filp)
+{
+	int minor = video_devdata(filp)->minor;
+	int errCode = 0, radio = 0;
+	struct cx231xx *dev = NULL;
+	struct cx231xx_fh *fh;
+	enum v4l2_buf_type fh_type = 0;
+
+	dev = cx231xx_get_device(minor, &fh_type, &radio);
+	if (NULL == dev)
+		return -ENODEV;
+
+	mutex_lock(&dev->lock);
+
+	cx231xx_videodbg("open minor=%d type=%s users=%d\n",
+			 minor, v4l2_type_names[fh_type], dev->users);
+
+#if 0
+	errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
+	if (errCode < 0) {
+		cx231xx_errdev
+		    ("Device locked on digital mode. Can't open analog\n");
+		mutex_unlock(&dev->lock);
+		return -EBUSY;
+	}
+#endif
+
+	fh = kzalloc(sizeof(struct cx231xx_fh), GFP_KERNEL);
+	if (!fh) {
+		cx231xx_errdev("cx231xx-video.c: Out of memory?!\n");
+		mutex_unlock(&dev->lock);
+		return -ENOMEM;
+	}
+	fh->dev = dev;
+	fh->radio = radio;
+	fh->type = fh_type;
+	filp->private_data = fh;
+
+	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
+		dev->width = norm_maxw(dev);
+		dev->height = norm_maxh(dev);
+		dev->hscale = 0;
+		dev->vscale = 0;
+
+		/* Power up in Analog TV mode */
+		cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV);
+
+#if 0
+		cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
+#endif
+		cx231xx_resolution_set(dev);
+
+		/* set video alternate setting */
+		cx231xx_set_video_alternate(dev);
+
+		/* Needed, since GPIO might have disabled power of
+		   some i2c device */
+		cx231xx_config_i2c(dev);
+
+		/* device needs to be initialized before isoc transfer */
+		dev->video_input = dev->video_input > 2 ? 2 : dev->video_input;
+		video_mux(dev, dev->video_input);
+
+	}
+	if (fh->radio) {
+		cx231xx_videodbg("video_open: setting radio device\n");
+
+		/* cx231xx_start_radio(dev); */
+
+		call_all(dev, tuner, s_radio);
+	}
+
+	dev->users++;
+
+	if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_video_qops,
+					    NULL, &dev->video_mode.slock,
+					    fh->type, V4L2_FIELD_INTERLACED,
+					    sizeof(struct cx231xx_buffer), fh);
+	if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+		/* Set the required alternate setting  VBI interface works in
+		   Bulk mode only */
+		cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
+
+		videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops,
+					    NULL, &dev->vbi_mode.slock,
+					    fh->type, V4L2_FIELD_SEQ_TB,
+					    sizeof(struct cx231xx_buffer), fh);
+	}
+
+	mutex_unlock(&dev->lock);
+
+	return errCode;
+}
+
+/*
+ * cx231xx_realease_resources()
+ * unregisters the v4l2,i2c and usb devices
+ * called when the device gets disconected or at module unload
+*/
+void cx231xx_release_analog_resources(struct cx231xx *dev)
+{
+
+	/*FIXME: I2C IR should be disconnected */
+
+	if (dev->radio_dev) {
+		if (-1 != dev->radio_dev->minor)
+			video_unregister_device(dev->radio_dev);
+		else
+			video_device_release(dev->radio_dev);
+		dev->radio_dev = NULL;
+	}
+	if (dev->vbi_dev) {
+		cx231xx_info("V4L2 device /dev/vbi%d deregistered\n",
+			     dev->vbi_dev->num);
+		if (-1 != dev->vbi_dev->minor)
+			video_unregister_device(dev->vbi_dev);
+		else
+			video_device_release(dev->vbi_dev);
+		dev->vbi_dev = NULL;
+	}
+	if (dev->vdev) {
+		cx231xx_info("V4L2 device /dev/video%d deregistered\n",
+			     dev->vdev->num);
+		if (-1 != dev->vdev->minor)
+			video_unregister_device(dev->vdev);
+		else
+			video_device_release(dev->vdev);
+		dev->vdev = NULL;
+	}
+}
+
+/*
+ * cx231xx_v4l2_close()
+ * stops streaming and deallocates all resources allocated by the v4l2
+ * calls and ioctls
+ */
+static int cx231xx_v4l2_close(struct file *filp)
+{
+	struct cx231xx_fh *fh = filp->private_data;
+	struct cx231xx *dev = fh->dev;
+
+	cx231xx_videodbg("users=%d\n", dev->users);
+
+	mutex_lock(&dev->lock);
+
+	if (res_check(fh))
+		res_free(fh);
+
+	if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+		videobuf_stop(&fh->vb_vidq);
+		videobuf_mmap_free(&fh->vb_vidq);
+
+		/* the device is already disconnect,
+		   free the remaining resources */
+		if (dev->state & DEV_DISCONNECTED) {
+			cx231xx_release_resources(dev);
+			mutex_unlock(&dev->lock);
+			kfree(dev);
+			return 0;
+		}
+
+		/* do this before setting alternate! */
+		cx231xx_uninit_vbi_isoc(dev);
+
+		/* set alternate 0 */
+		if (!dev->vbi_or_sliced_cc_mode)
+			cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
+		else
+			cx231xx_set_alt_setting(dev, INDEX_HANC, 0);
+
+		kfree(fh);
+		dev->users--;
+		wake_up_interruptible_nr(&dev->open, 1);
+		mutex_unlock(&dev->lock);
+		return 0;
+	}
+
+	if (dev->users == 1) {
+		videobuf_stop(&fh->vb_vidq);
+		videobuf_mmap_free(&fh->vb_vidq);
+
+		/* the device is already disconnect,
+		   free the remaining resources */
+		if (dev->state & DEV_DISCONNECTED) {
+			cx231xx_release_resources(dev);
+			mutex_unlock(&dev->lock);
+			kfree(dev);
+			return 0;
+		}
+
+		/* Save some power by putting tuner to sleep */
+		call_all(dev, core, s_standby, 0);
+
+		/* do this before setting alternate! */
+		cx231xx_uninit_isoc(dev);
+		cx231xx_set_mode(dev, CX231XX_SUSPEND);
+
+		/* set alternate 0 */
+		cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0);
+	}
+	kfree(fh);
+	dev->users--;
+	wake_up_interruptible_nr(&dev->open, 1);
+	mutex_unlock(&dev->lock);
+	return 0;
+}
+
+/*
+ * cx231xx_v4l2_read()
+ * will allocate buffers when called for the first time
+ */
+static ssize_t
+cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
+		  loff_t *pos)
+{
+	struct cx231xx_fh *fh = filp->private_data;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	if ((fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+	    (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)) {
+		mutex_lock(&dev->lock);
+		rc = res_get(fh);
+		mutex_unlock(&dev->lock);
+
+		if (unlikely(rc < 0))
+			return rc;
+
+		return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
+					    filp->f_flags & O_NONBLOCK);
+	}
+	return 0;
+}
+
+/*
+ * cx231xx_v4l2_poll()
+ * will allocate buffers when called for the first time
+ */
+static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table * wait)
+{
+	struct cx231xx_fh *fh = filp->private_data;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	mutex_lock(&dev->lock);
+	rc = res_get(fh);
+	mutex_unlock(&dev->lock);
+
+	if (unlikely(rc < 0))
+		return POLLERR;
+
+	if ((V4L2_BUF_TYPE_VIDEO_CAPTURE == fh->type) ||
+	    (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type))
+		return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
+	else
+		return POLLERR;
+}
+
+/*
+ * cx231xx_v4l2_mmap()
+ */
+static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct cx231xx_fh *fh = filp->private_data;
+	struct cx231xx *dev = fh->dev;
+	int rc;
+
+	rc = check_dev(dev);
+	if (rc < 0)
+		return rc;
+
+	mutex_lock(&dev->lock);
+	rc = res_get(fh);
+	mutex_unlock(&dev->lock);
+
+	if (unlikely(rc < 0))
+		return rc;
+
+	rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
+
+	cx231xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",
+			 (unsigned long)vma->vm_start,
+			 (unsigned long)vma->vm_end -
+			 (unsigned long)vma->vm_start, rc);
+
+	return rc;
+}
+
+static const struct v4l2_file_operations cx231xx_v4l_fops = {
+	.owner   = THIS_MODULE,
+	.open    = cx231xx_v4l2_open,
+	.release = cx231xx_v4l2_close,
+	.read    = cx231xx_v4l2_read,
+	.poll    = cx231xx_v4l2_poll,
+	.mmap    = cx231xx_v4l2_mmap,
+	.ioctl   = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+	.vidioc_querycap               = vidioc_querycap,
+	.vidioc_enum_fmt_vid_cap       = vidioc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap          = vidioc_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap        = vidioc_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap          = vidioc_s_fmt_vid_cap,
+	.vidioc_g_fmt_vbi_cap          = vidioc_g_fmt_vbi_cap,
+	.vidioc_try_fmt_vbi_cap        = vidioc_try_fmt_vbi_cap,
+	.vidioc_s_fmt_vbi_cap          = vidioc_try_fmt_vbi_cap,
+	.vidioc_g_audio                =  vidioc_g_audio,
+	.vidioc_s_audio                = vidioc_s_audio,
+	.vidioc_cropcap                = vidioc_cropcap,
+	.vidioc_g_fmt_sliced_vbi_cap   = vidioc_g_fmt_sliced_vbi_cap,
+	.vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
+	.vidioc_reqbufs                = vidioc_reqbufs,
+	.vidioc_querybuf               = vidioc_querybuf,
+	.vidioc_qbuf                   = vidioc_qbuf,
+	.vidioc_dqbuf                  = vidioc_dqbuf,
+	.vidioc_s_std                  = vidioc_s_std,
+	.vidioc_g_std                  = vidioc_g_std,
+	.vidioc_enum_input             = vidioc_enum_input,
+	.vidioc_g_input                = vidioc_g_input,
+	.vidioc_s_input                = vidioc_s_input,
+	.vidioc_queryctrl              = vidioc_queryctrl,
+	.vidioc_g_ctrl                 = vidioc_g_ctrl,
+	.vidioc_s_ctrl                 = vidioc_s_ctrl,
+	.vidioc_streamon               = vidioc_streamon,
+	.vidioc_streamoff              = vidioc_streamoff,
+	.vidioc_g_tuner                = vidioc_g_tuner,
+	.vidioc_s_tuner                = vidioc_s_tuner,
+	.vidioc_g_frequency            = vidioc_g_frequency,
+	.vidioc_s_frequency            = vidioc_s_frequency,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register             = vidioc_g_register,
+	.vidioc_s_register             = vidioc_s_register,
+#endif
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+	.vidiocgmbuf                   = vidiocgmbuf,
+#endif
+};
+
+static struct video_device cx231xx_vbi_template;
+
+static const struct video_device cx231xx_video_template = {
+	.fops         = &cx231xx_v4l_fops,
+	.release      = video_device_release,
+	.ioctl_ops    = &video_ioctl_ops,
+	.minor        = -1,
+	.tvnorms      = V4L2_STD_ALL,
+	.current_norm = V4L2_STD_PAL,
+};
+
+static const struct v4l2_file_operations radio_fops = {
+	.owner   = THIS_MODULE,
+	.open   = cx231xx_v4l2_open,
+	.release = cx231xx_v4l2_close,
+	.ioctl   = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
+	.vidioc_querycap    = radio_querycap,
+	.vidioc_g_tuner     = radio_g_tuner,
+	.vidioc_enum_input  = radio_enum_input,
+	.vidioc_g_audio     = radio_g_audio,
+	.vidioc_s_tuner     = radio_s_tuner,
+	.vidioc_s_audio     = radio_s_audio,
+	.vidioc_s_input     = radio_s_input,
+	.vidioc_queryctrl   = radio_queryctrl,
+	.vidioc_g_ctrl      = vidioc_g_ctrl,
+	.vidioc_s_ctrl      = vidioc_s_ctrl,
+	.vidioc_g_frequency = vidioc_g_frequency,
+	.vidioc_s_frequency = vidioc_s_frequency,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register  = vidioc_g_register,
+	.vidioc_s_register  = vidioc_s_register,
+#endif
+};
+
+static struct video_device cx231xx_radio_template = {
+	.name      = "cx231xx-radio",
+	.fops      = &radio_fops,
+	.ioctl_ops = &radio_ioctl_ops,
+	.minor     = -1,
+};
+
+/******************************** usb interface ******************************/
+
+static struct video_device *cx231xx_vdev_init(struct cx231xx *dev,
+		const struct video_device
+		*template, const char *type_name)
+{
+	struct video_device *vfd;
+
+	vfd = video_device_alloc();
+	if (NULL == vfd)
+		return NULL;
+
+	*vfd = *template;
+	vfd->minor = -1;
+	vfd->v4l2_dev = &dev->v4l2_dev;
+	vfd->release = video_device_release;
+	vfd->debug = video_debug;
+
+	snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
+
+	return vfd;
+}
+
+int cx231xx_register_analog_devices(struct cx231xx *dev)
+{
+	int ret;
+
+	cx231xx_info("%s: v4l2 driver version %d.%d.%d\n",
+		     dev->name,
+		     (CX231XX_VERSION_CODE >> 16) & 0xff,
+		     (CX231XX_VERSION_CODE >> 8) & 0xff,
+		     CX231XX_VERSION_CODE & 0xff);
+
+	/* set default norm */
+	/*dev->norm = cx231xx_video_template.current_norm; */
+	dev->width = norm_maxw(dev);
+	dev->height = norm_maxh(dev);
+	dev->interlaced = 0;
+	dev->hscale = 0;
+	dev->vscale = 0;
+
+	/* Analog specific initialization */
+	dev->format = &format[0];
+	/* video_mux(dev, dev->video_input); */
+
+	/* Audio defaults */
+	dev->mute = 1;
+	dev->volume = 0x1f;
+
+	/* enable vbi capturing */
+	/* write code here...  */
+
+	/* allocate and fill video video_device struct */
+	dev->vdev = cx231xx_vdev_init(dev, &cx231xx_video_template, "video");
+	if (!dev->vdev) {
+		cx231xx_errdev("cannot allocate video_device.\n");
+		return -ENODEV;
+	}
+
+	/* register v4l2 video video_device */
+	ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
+				    video_nr[dev->devno]);
+	if (ret) {
+		cx231xx_errdev("unable to register video device (error=%i).\n",
+			       ret);
+		return ret;
+	}
+
+	cx231xx_info("%s/0: registered device video%d [v4l2]\n",
+		     dev->name, dev->vdev->num);
+
+	/* Initialize VBI template */
+	memcpy(&cx231xx_vbi_template, &cx231xx_video_template,
+	       sizeof(cx231xx_vbi_template));
+	strcpy(cx231xx_vbi_template.name, "cx231xx-vbi");
+
+	/* Allocate and fill vbi video_device struct */
+	dev->vbi_dev = cx231xx_vdev_init(dev, &cx231xx_vbi_template, "vbi");
+
+	/* register v4l2 vbi video_device */
+	ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
+				    vbi_nr[dev->devno]);
+	if (ret < 0) {
+		cx231xx_errdev("unable to register vbi device\n");
+		return ret;
+	}
+
+	cx231xx_info("%s/0: registered device vbi%d\n",
+		     dev->name, dev->vbi_dev->num);
+
+	if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) {
+		dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template,
+						   "radio");
+		if (!dev->radio_dev) {
+			cx231xx_errdev("cannot allocate video_device.\n");
+			return -ENODEV;
+		}
+		ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
+					    radio_nr[dev->devno]);
+		if (ret < 0) {
+			cx231xx_errdev("can't register radio device\n");
+			return ret;
+		}
+		cx231xx_info("Registered radio device as /dev/radio%d\n",
+			     dev->radio_dev->num);
+	}
+
+	cx231xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n",
+		     dev->vdev->num, dev->vbi_dev->num);
+
+	return 0;
+}
diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h
new file mode 100644
index 0000000..aa4a23e
--- /dev/null
+++ b/drivers/media/video/cx231xx/cx231xx.h
@@ -0,0 +1,779 @@
+/*
+   cx231xx.h - 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.
+ */
+
+#ifndef _CX231XX_H
+#define _CX231XX_H
+
+#include <linux/videodev2.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/mutex.h>
+
+
+#include <media/videobuf-vmalloc.h>
+#include <media/v4l2-device.h>
+#include <media/ir-kbd-i2c.h>
+#if defined(CONFIG_VIDEO_CX231XX_DVB) || \
+	defined(CONFIG_VIDEO_CX231XX_DVB_MODULE)
+#include <media/videobuf-dvb.h>
+#endif
+
+#include "cx231xx-reg.h"
+#include "cx231xx-pcb-cfg.h"
+#include "cx231xx-conf-reg.h"
+
+#define DRIVER_NAME                     "cx231xx"
+#define PWR_SLEEP_INTERVAL              5
+
+/* I2C addresses for control block in Cx231xx */
+#define     AFE_DEVICE_ADDRESS		0x60
+#define     I2S_BLK_DEVICE_ADDRESS	0x98
+#define     VID_BLK_I2C_ADDRESS		0x88
+#define     DIF_USE_BASEBAND            0xFFFFFFFF
+
+/* Boards supported by driver */
+#define CX231XX_BOARD_UNKNOWN		    0
+#define CX231XX_BOARD_CNXT_RDE_250     	1
+#define CX231XX_BOARD_CNXT_RDU_250     	2
+
+/* Limits minimum and default number of buffers */
+#define CX231XX_MIN_BUF                 4
+#define CX231XX_DEF_BUF                 12
+#define CX231XX_DEF_VBI_BUF             6
+
+#define VBI_LINE_COUNT                  17
+#define VBI_LINE_LENGTH                 1440
+
+/*Limits the max URB message size */
+#define URB_MAX_CTRL_SIZE               80
+
+/* Params for validated field */
+#define CX231XX_BOARD_NOT_VALIDATED     1
+#define CX231XX_BOARD_VALIDATED		0
+
+/* maximum number of cx231xx boards */
+#define CX231XX_MAXBOARDS               8
+
+/* maximum number of frames that can be queued */
+#define CX231XX_NUM_FRAMES              5
+
+/* number of buffers for isoc transfers */
+#define CX231XX_NUM_BUFS                8
+
+/* number of packets for each buffer
+   windows requests only 40 packets .. so we better do the same
+   this is what I found out for all alternate numbers there!
+ */
+#define CX231XX_NUM_PACKETS             40
+
+/* default alternate; 0 means choose the best */
+#define CX231XX_PINOUT                  0
+
+#define CX231XX_INTERLACED_DEFAULT      1
+
+/* time to wait when stopping the isoc transfer */
+#define CX231XX_URB_TIMEOUT		\
+		msecs_to_jiffies(CX231XX_NUM_BUFS * CX231XX_NUM_PACKETS)
+
+enum cx231xx_mode {
+	CX231XX_SUSPEND,
+	CX231XX_ANALOG_MODE,
+	CX231XX_DIGITAL_MODE,
+};
+
+enum cx231xx_std_mode {
+	CX231XX_TV_AIR = 0,
+	CX231XX_TV_CABLE
+};
+
+enum cx231xx_stream_state {
+	STREAM_OFF,
+	STREAM_INTERRUPT,
+	STREAM_ON,
+};
+
+struct cx231xx;
+
+struct cx231xx_usb_isoc_ctl {
+	/* max packet size of isoc transaction */
+	int max_pkt_size;
+
+	/* number of allocated urbs */
+	int num_bufs;
+
+	/* urb for isoc transfers */
+	struct urb **urb;
+
+	/* transfer buffers for isoc transfer */
+	char **transfer_buffer;
+
+	/* Last buffer command and region */
+	u8 cmd;
+	int pos, size, pktsize;
+
+	/* Last field: ODD or EVEN? */
+	int field;
+
+	/* Stores incomplete commands */
+	u32 tmp_buf;
+	int tmp_buf_len;
+
+	/* Stores already requested buffers */
+	struct cx231xx_buffer *buf;
+
+	/* Stores the number of received fields */
+	int nfields;
+
+	/* isoc urb callback */
+	int (*isoc_copy) (struct cx231xx *dev, struct urb *urb);
+};
+
+struct cx231xx_fmt {
+	char *name;
+	u32 fourcc;		/* v4l2 format id */
+	int depth;
+	int reg;
+};
+
+/* buffer for one video frame */
+struct cx231xx_buffer {
+	/* common v4l buffer stuff -- must be first */
+	struct videobuf_buffer vb;
+
+	struct list_head frame;
+	int top_field;
+	int receiving;
+};
+
+struct cx231xx_dmaqueue {
+	struct list_head active;
+	struct list_head queued;
+
+	wait_queue_head_t wq;
+
+	/* Counters to control buffer fill */
+	int pos;
+	u8 is_partial_line;
+	u8 partial_buf[8];
+	u8 last_sav;
+	int current_field;
+	u32 bytes_left_in_line;
+	u32 lines_completed;
+	u8 field1_done;
+	u32 lines_per_field;
+};
+
+/* inputs */
+
+#define MAX_CX231XX_INPUT               4
+
+enum cx231xx_itype {
+	CX231XX_VMUX_COMPOSITE1 = 1,
+	CX231XX_VMUX_SVIDEO,
+	CX231XX_VMUX_TELEVISION,
+	CX231XX_VMUX_CABLE,
+	CX231XX_RADIO,
+	CX231XX_VMUX_DVB,
+	CX231XX_VMUX_DEBUG
+};
+
+enum cx231xx_v_input {
+	CX231XX_VIN_1_1 = 0x1,
+	CX231XX_VIN_2_1,
+	CX231XX_VIN_3_1,
+	CX231XX_VIN_4_1,
+	CX231XX_VIN_1_2 = 0x01,
+	CX231XX_VIN_2_2,
+	CX231XX_VIN_3_2,
+	CX231XX_VIN_1_3 = 0x1,
+	CX231XX_VIN_2_3,
+	CX231XX_VIN_3_3,
+};
+
+/* cx231xx has two audio inputs: tuner and line in */
+enum cx231xx_amux {
+	/* This is the only entry for cx231xx tuner input */
+	CX231XX_AMUX_VIDEO,	/* cx231xx tuner */
+	CX231XX_AMUX_LINE_IN,	/* Line In */
+};
+
+struct cx231xx_reg_seq {
+	unsigned char bit;
+	unsigned char val;
+	int sleep;
+};
+
+struct cx231xx_input {
+	enum cx231xx_itype type;
+	unsigned int vmux;
+	enum cx231xx_amux amux;
+	struct cx231xx_reg_seq *gpio;
+};
+
+#define INPUT(nr) (&cx231xx_boards[dev->model].input[nr])
+
+enum cx231xx_decoder {
+	CX231XX_NODECODER,
+	CX231XX_AVDECODER
+};
+
+enum CX231XX_I2C_MASTER_PORT {
+	I2C_0 = 0,
+	I2C_1 = 1,
+	I2C_2 = 2,
+	I2C_3 = 3
+};
+
+struct cx231xx_board {
+	char *name;
+	int vchannels;
+	int tuner_type;
+	int tuner_addr;
+	v4l2_std_id norm;	/* tv norm */
+
+	/* demod related */
+	int demod_addr;
+	u8 demod_xfer_mode;	/* 0 - Serial; 1 - parallel */
+
+	/* GPIO Pins */
+	struct cx231xx_reg_seq *dvb_gpio;
+	struct cx231xx_reg_seq *suspend_gpio;
+	struct cx231xx_reg_seq *tuner_gpio;
+	u8 tuner_sif_gpio;
+	u8 tuner_scl_gpio;
+	u8 tuner_sda_gpio;
+
+	/* PIN ctrl */
+	u32 ctl_pin_status_mask;
+	u8 agc_analog_digital_select_gpio;
+	u32 gpio_pin_status_mask;
+
+	/* i2c masters */
+	u8 tuner_i2c_master;
+	u8 demod_i2c_master;
+
+	unsigned int max_range_640_480:1;
+	unsigned int has_dvb:1;
+	unsigned int valid:1;
+
+	unsigned char xclk, i2c_speed;
+
+	enum cx231xx_decoder decoder;
+
+	struct cx231xx_input input[MAX_CX231XX_INPUT];
+	struct cx231xx_input radio;
+	IR_KEYTAB_TYPE *ir_codes;
+};
+
+/* device states */
+enum cx231xx_dev_state {
+	DEV_INITIALIZED = 0x01,
+	DEV_DISCONNECTED = 0x02,
+	DEV_MISCONFIGURED = 0x04,
+};
+
+enum AFE_MODE {
+	AFE_MODE_LOW_IF,
+	AFE_MODE_BASEBAND,
+	AFE_MODE_EU_HI_IF,
+	AFE_MODE_US_HI_IF,
+	AFE_MODE_JAPAN_HI_IF
+};
+
+enum AUDIO_INPUT {
+	AUDIO_INPUT_MUTE,
+	AUDIO_INPUT_LINE,
+	AUDIO_INPUT_TUNER_TV,
+	AUDIO_INPUT_SPDIF,
+	AUDIO_INPUT_TUNER_FM
+};
+
+#define CX231XX_AUDIO_BUFS              5
+#define CX231XX_NUM_AUDIO_PACKETS       64
+#define CX231XX_CAPTURE_STREAM_EN       1
+#define CX231XX_STOP_AUDIO              0
+#define CX231XX_START_AUDIO             1
+
+/* cx231xx extensions */
+#define CX231XX_AUDIO                   0x10
+#define CX231XX_DVB                     0x20
+
+struct cx231xx_audio {
+	char name[50];
+	char *transfer_buffer[CX231XX_AUDIO_BUFS];
+	struct urb *urb[CX231XX_AUDIO_BUFS];
+	struct usb_device *udev;
+	unsigned int capture_transfer_done;
+	struct snd_pcm_substream *capture_pcm_substream;
+
+	unsigned int hwptr_done_capture;
+	struct snd_card *sndcard;
+
+	int users, shutdown;
+	enum cx231xx_stream_state capture_stream;
+	spinlock_t slock;
+
+	int alt;		/* alternate */
+	int max_pkt_size;	/* max packet size of isoc transaction */
+	int num_alt;		/* Number of alternative settings */
+	unsigned int *alt_max_pkt_size;	/* array of wMaxPacketSize */
+	u16 end_point_addr;
+};
+
+struct cx231xx;
+
+struct cx231xx_fh {
+	struct cx231xx *dev;
+	unsigned int stream_on:1;	/* Locks streams */
+	int radio;
+
+	struct videobuf_queue vb_vidq;
+
+	enum v4l2_buf_type type;
+};
+
+/*****************************************************************/
+/* set/get i2c */
+/* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */
+#define I2C_SPEED_1M            0x0
+#define I2C_SPEED_400K          0x1
+#define I2C_SPEED_100K          0x2
+#define I2C_SPEED_5M            0x3
+
+/* 0-- STOP transaction */
+#define I2C_STOP                0x0
+/* 1-- do not transmit STOP at end of transaction */
+#define I2C_NOSTOP              0x1
+/* 1--alllow slave to insert clock wait states */
+#define I2C_SYNC                0x1
+
+struct cx231xx_i2c {
+	struct cx231xx *dev;
+
+	int nr;
+
+	/* i2c i/o */
+	struct i2c_adapter i2c_adap;
+	struct i2c_algo_bit_data i2c_algo;
+	struct i2c_client i2c_client;
+	u32 i2c_rc;
+
+	/* different settings for each bus */
+	u8 i2c_period;
+	u8 i2c_nostop;
+	u8 i2c_reserve;
+};
+
+struct cx231xx_i2c_xfer_data {
+	u8 dev_addr;
+	u8 direction;		/* 1 - IN, 0 - OUT */
+	u8 saddr_len;		/* sub address len */
+	u16 saddr_dat;		/* sub addr data */
+	u8 buf_size;		/* buffer size */
+	u8 *p_buffer;		/* pointer to the buffer */
+};
+
+struct VENDOR_REQUEST_IN {
+	u8 bRequest;
+	u16 wValue;
+	u16 wIndex;
+	u16 wLength;
+	u8 direction;
+	u8 bData;
+	u8 *pBuff;
+};
+
+struct cx231xx_ctrl {
+	struct v4l2_queryctrl v;
+	u32 off;
+	u32 reg;
+	u32 mask;
+	u32 shift;
+};
+
+enum TRANSFER_TYPE {
+	Raw_Video = 0,
+	Audio,
+	Vbi,			/* VANC */
+	Sliced_cc,		/* HANC */
+	TS1_serial_mode,
+	TS2,
+	TS1_parallel_mode
+} ;
+
+struct cx231xx_video_mode {
+	/* Isoc control struct */
+	struct cx231xx_dmaqueue vidq;
+	struct cx231xx_usb_isoc_ctl isoc_ctl;
+	spinlock_t slock;
+
+	/* usb transfer */
+	int alt;		/* alternate */
+	int max_pkt_size;	/* max packet size of isoc transaction */
+	int num_alt;		/* Number of alternative settings */
+	unsigned int *alt_max_pkt_size;	/* array of wMaxPacketSize */
+	u16 end_point_addr;
+};
+
+/* main device struct */
+struct cx231xx {
+	/* generic device properties */
+	char name[30];		/* name (including minor) of the device */
+	int model;		/* index in the device_data struct */
+	int devno;		/* marks the number of this device */
+
+	struct cx231xx_board board;
+
+	unsigned int stream_on:1;	/* Locks streams */
+	unsigned int vbi_stream_on:1;	/* Locks streams for VBI */
+	unsigned int has_audio_class:1;
+	unsigned int has_alsa_audio:1;
+
+	struct cx231xx_fmt *format;
+
+	struct v4l2_device v4l2_dev;
+	struct v4l2_subdev *sd_cx25840;
+	struct v4l2_subdev *sd_tuner;
+
+	struct cx231xx_IR *ir;
+
+	struct list_head devlist;
+
+	int tuner_type;		/* type of the tuner */
+	int tuner_addr;		/* tuner address */
+
+	/* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
+	struct cx231xx_i2c i2c_bus[3];
+	unsigned int xc_fw_load_done:1;
+	struct mutex gpio_i2c_lock;
+
+	/* video for linux */
+	int users;		/* user count for exclusive use */
+	struct video_device *vdev;	/* video for linux device struct */
+	v4l2_std_id norm;	/* selected tv norm */
+	int ctl_freq;		/* selected frequency */
+	unsigned int ctl_ainput;	/* selected audio input */
+	int mute;
+	int volume;
+
+	/* frame properties */
+	int width;		/* current frame width */
+	int height;		/* current frame height */
+	unsigned hscale;	/* horizontal scale factor (see datasheet) */
+	unsigned vscale;	/* vertical scale factor (see datasheet) */
+	int interlaced;		/* 1=interlace fileds, 0=just top fileds */
+
+	struct cx231xx_audio adev;
+
+	/* states */
+	enum cx231xx_dev_state state;
+
+	struct work_struct request_module_wk;
+
+	/* locks */
+	struct mutex lock;
+	struct mutex ctrl_urb_lock;	/* protects urb_buf */
+	struct list_head inqueue, outqueue;
+	wait_queue_head_t open, wait_frame, wait_stream;
+	struct video_device *vbi_dev;
+	struct video_device *radio_dev;
+
+	unsigned char eedata[256];
+
+	struct cx231xx_video_mode video_mode;
+	struct cx231xx_video_mode vbi_mode;
+	struct cx231xx_video_mode sliced_cc_mode;
+	struct cx231xx_video_mode ts1_mode;
+
+	struct usb_device *udev;	/* the usb device */
+	char urb_buf[URB_MAX_CTRL_SIZE];	/* urb control msg buffer */
+
+	/* helper funcs that call usb_control_msg */
+	int (*cx231xx_read_ctrl_reg) (struct cx231xx *dev, u8 req, u16 reg,
+				      char *buf, int len);
+	int (*cx231xx_write_ctrl_reg) (struct cx231xx *dev, u8 req, u16 reg,
+				       char *buf, int len);
+	int (*cx231xx_send_usb_command) (struct cx231xx_i2c *i2c_bus,
+				struct cx231xx_i2c_xfer_data *req_data);
+	int (*cx231xx_gpio_i2c_read) (struct cx231xx *dev, u8 dev_addr,
+				      u8 *buf, u8 len);
+	int (*cx231xx_gpio_i2c_write) (struct cx231xx *dev, u8 dev_addr,
+				       u8 *buf, u8 len);
+
+	int (*cx231xx_set_analog_freq) (struct cx231xx *dev, u32 freq);
+	int (*cx231xx_reset_analog_tuner) (struct cx231xx *dev);
+
+	enum cx231xx_mode mode;
+
+	struct cx231xx_dvb *dvb;
+
+	/* Cx231xx supported PCB config's */
+	struct pcb_config current_pcb_config;
+	u8 current_scenario_idx;
+	u8 interface_count;
+	u8 max_iad_interface_count;
+
+	/* GPIO related register direction and values */
+	u32 gpio_dir;
+	u32 gpio_val;
+
+	/* Power Modes */
+	int power_mode;
+
+	/* afe parameters */
+	enum AFE_MODE afe_mode;
+	u32 afe_ref_count;
+
+	/* video related parameters */
+	u32 video_input;
+	u32 active_mode;
+	u8 vbi_or_sliced_cc_mode;	/* 0 - vbi ; 1 - sliced cc mode */
+	enum cx231xx_std_mode std_mode;	/* 0 - Air; 1 - cable */
+
+};
+
+#define cx25840_call(cx231xx, o, f, args...) \
+	v4l2_subdev_call(cx231xx->sd_cx25840, o, f, ##args)
+#define tuner_call(cx231xx, o, f, args...) \
+	v4l2_subdev_call(cx231xx->sd_tuner, o, f, ##args)
+#define call_all(dev, o, f, args...) \
+	v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
+
+struct cx231xx_ops {
+	struct list_head next;
+	char *name;
+	int id;
+	int (*init) (struct cx231xx *);
+	int (*fini) (struct cx231xx *);
+};
+
+/* call back functions in dvb module */
+int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq);
+int cx231xx_reset_analog_tuner(struct cx231xx *dev);
+
+/* Provided by cx231xx-i2c.c */
+void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c);
+int cx231xx_i2c_register(struct cx231xx_i2c *bus);
+int cx231xx_i2c_unregister(struct cx231xx_i2c *bus);
+
+/* Internal block control functions */
+int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr,
+			  u16 saddr, u8 saddr_len, u32 *data, u8 data_len);
+int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr,
+			   u16 saddr, u8 saddr_len, u32 data, u8 data_len);
+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 cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr,
+					u16 saddr, u32 mask, u32 value);
+u32 cx231xx_set_field(u32 field_mask, u32 data);
+
+/* afe related functions */
+int cx231xx_afe_init_super_block(struct cx231xx *dev, u32 ref_count);
+int cx231xx_afe_init_channels(struct cx231xx *dev);
+int cx231xx_afe_setup_AFE_for_baseband(struct cx231xx *dev);
+int cx231xx_afe_set_input_mux(struct cx231xx *dev, u32 input_mux);
+int cx231xx_afe_set_mode(struct cx231xx *dev, enum AFE_MODE mode);
+int cx231xx_afe_update_power_control(struct cx231xx *dev,
+					enum AV_MODE avmode);
+int cx231xx_afe_adjust_ref_count(struct cx231xx *dev, u32 video_input);
+
+/* i2s block related functions */
+int cx231xx_i2s_blk_initialize(struct cx231xx *dev);
+int cx231xx_i2s_blk_update_power_control(struct cx231xx *dev,
+					enum AV_MODE avmode);
+int cx231xx_i2s_blk_set_audio_input(struct cx231xx *dev, u8 audio_input);
+
+/* DIF related functions */
+int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode,
+					  u32 function_mode, u32 standard);
+int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard);
+int cx231xx_tuner_pre_channel_change(struct cx231xx *dev);
+int cx231xx_tuner_post_channel_change(struct cx231xx *dev);
+
+/* video parser functions */
+u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size,
+			     u32 *p_bytes_used);
+u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf,
+				 u32 *p_bytes_used);
+int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+		    u8 *p_buffer, u32 bytes_to_copy);
+void cx231xx_reset_video_buffer(struct cx231xx *dev,
+				struct cx231xx_dmaqueue *dma_q);
+u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q);
+u32 cx231xx_copy_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+			    u8 *p_line, u32 length, int field_number);
+u32 cx231xx_get_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+			   u8 sav_eav, u8 *p_buffer, u32 buffer_size);
+void cx231xx_swab(u16 *from, u16 *to, u16 len);
+
+/* Provided by cx231xx-core.c */
+
+u32 cx231xx_request_buffers(struct cx231xx *dev, u32 count);
+void cx231xx_queue_unusedframes(struct cx231xx *dev);
+void cx231xx_release_buffers(struct cx231xx *dev);
+
+/* read from control pipe */
+int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg,
+			  char *buf, int len);
+
+/* write to control pipe */
+int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg,
+			   char *buf, int len);
+int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode);
+
+int cx231xx_send_vendor_cmd(struct cx231xx *dev,
+				struct VENDOR_REQUEST_IN *ven_req);
+int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus,
+				struct cx231xx_i2c_xfer_data *req_data);
+
+/* Gpio related functions */
+int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val,
+			  u8 len, u8 request, u8 direction);
+int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val);
+int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val);
+int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value);
+int cx231xx_set_gpio_direction(struct cx231xx *dev, int pin_number,
+			       int pin_value);
+
+int cx231xx_gpio_i2c_start(struct cx231xx *dev);
+int cx231xx_gpio_i2c_end(struct cx231xx *dev);
+int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data);
+int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf);
+int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev);
+int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev);
+int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev);
+
+int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len);
+int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len);
+
+/* audio related functions */
+int cx231xx_set_audio_decoder_input(struct cx231xx *dev,
+				    enum AUDIO_INPUT audio_input);
+
+int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type);
+int cx231xx_resolution_set(struct cx231xx *dev);
+int cx231xx_set_video_alternate(struct cx231xx *dev);
+int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt);
+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));
+void cx231xx_uninit_isoc(struct cx231xx *dev);
+int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode);
+int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio);
+
+/* Device list functions */
+void cx231xx_release_resources(struct cx231xx *dev);
+void cx231xx_release_analog_resources(struct cx231xx *dev);
+int cx231xx_register_analog_devices(struct cx231xx *dev);
+void cx231xx_remove_from_devlist(struct cx231xx *dev);
+void cx231xx_add_into_devlist(struct cx231xx *dev);
+struct cx231xx *cx231xx_get_device(int minor,
+				   enum v4l2_buf_type *fh_type, int *has_radio);
+void cx231xx_init_extension(struct cx231xx *dev);
+void cx231xx_close_extension(struct cx231xx *dev);
+
+/* hardware init functions */
+int cx231xx_dev_init(struct cx231xx *dev);
+void cx231xx_dev_uninit(struct cx231xx *dev);
+void cx231xx_config_i2c(struct cx231xx *dev);
+int cx231xx_config(struct cx231xx *dev);
+
+/* Stream control functions */
+int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask);
+int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask);
+
+int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type);
+
+/* Power control functions */
+int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode);
+int cx231xx_power_suspend(struct cx231xx *dev);
+
+/* chip specific control functions */
+int cx231xx_init_ctrl_pin_status(struct cx231xx *dev);
+int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev,
+					      u8 analog_or_digital);
+int cx231xx_enable_i2c_for_tuner(struct cx231xx *dev, u8 I2CIndex);
+
+/* video audio decoder related functions */
+void video_mux(struct cx231xx *dev, int index);
+int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input);
+int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input);
+int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev);
+int cx231xx_set_audio_input(struct cx231xx *dev, u8 input);
+void get_scale(struct cx231xx *dev,
+	       unsigned int width, unsigned int height,
+	       unsigned int *hscale, unsigned int *vscale);
+
+/* Provided by cx231xx-video.c */
+int cx231xx_register_extension(struct cx231xx_ops *dev);
+void cx231xx_unregister_extension(struct cx231xx_ops *dev);
+void cx231xx_init_extension(struct cx231xx *dev);
+void cx231xx_close_extension(struct cx231xx *dev);
+
+/* Provided by cx231xx-cards.c */
+extern void cx231xx_pre_card_setup(struct cx231xx *dev);
+extern void cx231xx_card_setup(struct cx231xx *dev);
+extern struct cx231xx_board cx231xx_boards[];
+extern struct usb_device_id cx231xx_id_table[];
+extern const unsigned int cx231xx_bcount;
+void cx231xx_set_ir(struct cx231xx *dev, struct IR_i2c *ir);
+int cx231xx_tuner_callback(void *ptr, int component, int command, int arg);
+
+/* Provided by cx231xx-input.c */
+int cx231xx_ir_init(struct cx231xx *dev);
+int cx231xx_ir_fini(struct cx231xx *dev);
+
+/* printk macros */
+
+#define cx231xx_err(fmt, arg...) do {\
+	printk(KERN_ERR fmt , ##arg); } while (0)
+
+#define cx231xx_errdev(fmt, arg...) do {\
+	printk(KERN_ERR "%s: "fmt,\
+			dev->name , ##arg); } while (0)
+
+#define cx231xx_info(fmt, arg...) do {\
+	printk(KERN_INFO "%s: "fmt,\
+			dev->name , ##arg); } while (0)
+#define cx231xx_warn(fmt, arg...) do {\
+	printk(KERN_WARNING "%s: "fmt,\
+			dev->name , ##arg); } while (0)
+
+static inline unsigned int norm_maxw(struct cx231xx *dev)
+{
+	if (dev->board.max_range_640_480)
+		return 640;
+	else
+		return 720;
+}
+
+static inline unsigned int norm_maxh(struct cx231xx *dev)
+{
+	if (dev->board.max_range_640_480)
+		return 480;
+	else
+		return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
+}
+#endif
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index 93d74be..2f846f5 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -32,7 +32,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
 
 	/* common for all inputs and rates */
 	/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
-	if (!state->is_cx23885)
+	if (!state->is_cx23885 && !state->is_cx231xx)
 		cx25840_write(client, 0x127, 0x50);
 
 	if (state->aud_input != CX25840_AUDIO_SERIAL) {
@@ -43,11 +43,14 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
 				 * so avoid destroying registers. */
 				break;
 			}
-			/* VID_PLL and AUX_PLL */
-			cx25840_write4(client, 0x108, 0x1006040f);
 
-			/* AUX_PLL_FRAC */
-			cx25840_write4(client, 0x110, 0x01bb39ee);
+			if (!state->is_cx231xx) {
+				/* VID_PLL and AUX_PLL */
+				cx25840_write4(client, 0x108, 0x1006040f);
+
+				/* AUX_PLL_FRAC */
+				cx25840_write4(client, 0x110, 0x01bb39ee);
+			}
 
 			if (state->is_cx25836)
 				break;
@@ -64,11 +67,14 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
 				 * so avoid destroying registers. */
 				break;
 			}
-			/* VID_PLL and AUX_PLL */
-			cx25840_write4(client, 0x108, 0x1009040f);
 
-			/* AUX_PLL_FRAC */
-			cx25840_write4(client, 0x110, 0x00ec6bd6);
+			if (!state->is_cx231xx) {
+				/* VID_PLL and AUX_PLL */
+				cx25840_write4(client, 0x108, 0x1009040f);
+
+				/* AUX_PLL_FRAC */
+				cx25840_write4(client, 0x110, 0x00ec6bd6);
+			}
 
 			if (state->is_cx25836)
 				break;
@@ -85,11 +91,14 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
 				 * so avoid destroying registers. */
 				break;
 			}
-			/* VID_PLL and AUX_PLL */
-			cx25840_write4(client, 0x108, 0x100a040f);
 
-			/* AUX_PLL_FRAC */
-			cx25840_write4(client, 0x110, 0x0098d6e5);
+			if (!state->is_cx231xx) {
+				/* VID_PLL and AUX_PLL */
+				cx25840_write4(client, 0x108, 0x100a040f);
+
+				/* AUX_PLL_FRAC */
+				cx25840_write4(client, 0x110, 0x0098d6e5);
+			}
 
 			if (state->is_cx25836)
 				break;
@@ -108,11 +117,14 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
 				 * so avoid destroying registers. */
 				break;
 			}
-			/* VID_PLL and AUX_PLL */
-			cx25840_write4(client, 0x108, 0x1e08040f);
 
-			/* AUX_PLL_FRAC */
-			cx25840_write4(client, 0x110, 0x012a0869);
+			if (!state->is_cx231xx) {
+				/* VID_PLL and AUX_PLL */
+				cx25840_write4(client, 0x108, 0x1e08040f);
+
+				/* AUX_PLL_FRAC */
+				cx25840_write4(client, 0x110, 0x012a0869);
+			}
 
 			if (state->is_cx25836)
 				break;
@@ -136,11 +148,14 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
 				break;
 			}
 
-			/* VID_PLL and AUX_PLL */
-			cx25840_write4(client, 0x108, 0x1809040f);
 
-			/* AUX_PLL_FRAC */
-			cx25840_write4(client, 0x110, 0x00ec6bd6);
+			if (!state->is_cx231xx) {
+				/* VID_PLL and AUX_PLL */
+				cx25840_write4(client, 0x108, 0x1809040f);
+
+				/* AUX_PLL_FRAC */
+				cx25840_write4(client, 0x110, 0x00ec6bd6);
+			}
 
 			if (state->is_cx25836)
 				break;
@@ -155,7 +170,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
 			break;
 
 		case 48000:
-			if (!state->is_cx23885) {
+			if (!state->is_cx23885 && !state->is_cx231xx) {
 				/* VID_PLL and AUX_PLL */
 				cx25840_write4(client, 0x108, 0x180a040f);
 
@@ -166,7 +181,7 @@ static int set_audclk_freq(struct i2c_client *client, u32 freq)
 			if (state->is_cx25836)
 				break;
 
-			if (!state->is_cx23885) {
+			if (!state->is_cx23885 && !state->is_cx231xx) {
 				/* src1_ctl */
 				cx25840_write4(client, 0x8f8, 0x08018000);
 
@@ -227,10 +242,9 @@ void cx25840_audio_set_path(struct i2c_client *client)
 	/* deassert soft reset */
 	cx25840_and_or(client, 0x810, ~0x1, 0x00);
 
-	if (state->is_cx23885) {
-		/* Ensure the controller is running when we exit */
+	/* Ensure the controller is running when we exit */
+	if (state->is_cx23885 || state->is_cx231xx)
 		cx25840_and_or(client, 0x803, ~0x10, 0x10);
-	}
 }
 
 static int get_volume(struct i2c_client *client)
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 737ee4e..f8ed3c0 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -345,6 +345,77 @@ static void cx23885_initialize(struct i2c_client *client)
 
 /* ----------------------------------------------------------------------- */
 
+static void cx231xx_initialize(struct i2c_client *client)
+{
+	DEFINE_WAIT(wait);
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+	struct workqueue_struct *q;
+
+	/* Internal Reset */
+	cx25840_and_or(client, 0x102, ~0x01, 0x01);
+	cx25840_and_or(client, 0x102, ~0x01, 0x00);
+
+	/* Stop microcontroller */
+	cx25840_and_or(client, 0x803, ~0x10, 0x00);
+
+	/* DIF in reset? */
+	cx25840_write(client, 0x398, 0);
+
+	/* Trust the default xtal, no division */
+	/* This changes for the cx23888 products */
+	cx25840_write(client, 0x2, 0x76);
+
+	/* Bring down the regulator for AUX clk */
+	cx25840_write(client, 0x1, 0x40);
+
+	/* Disable DIF bypass */
+	cx25840_write4(client, 0x33c, 0x00000001);
+
+	/* DIF Src phase inc */
+	cx25840_write4(client, 0x340, 0x0df7df83);
+
+	/* Luma */
+	cx25840_write4(client, 0x414, 0x00107d12);
+
+	/* Chroma */
+	cx25840_write4(client, 0x420, 0x3d008282);
+
+	/* ADC2 input select */
+	cx25840_write(client, 0x102, 0x10);
+
+	/* VIN1 & VIN5 */
+	cx25840_write(client, 0x103, 0x11);
+
+	/* Enable format auto detect */
+	cx25840_write(client, 0x400, 0);
+	/* Fast subchroma lock */
+	/* White crush, Chroma AGC & Chroma Killer enabled */
+	cx25840_write(client, 0x401, 0xe8);
+
+	/* Do the firmware load in a work handler to prevent.
+	   Otherwise the kernel is blocked waiting for the
+	   bit-banging i2c interface to finish uploading the
+	   firmware. */
+	INIT_WORK(&state->fw_work, cx25840_work_handler);
+	init_waitqueue_head(&state->fw_wait);
+	q = create_singlethread_workqueue("cx25840_fw");
+	prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE);
+	queue_work(q, &state->fw_work);
+	schedule();
+	finish_wait(&state->fw_wait, &wait);
+	destroy_workqueue(q);
+
+	cx25840_std_setup(client);
+
+	/* (re)set input */
+	set_input(client, state->vid_input, state->aud_input);
+
+	/* start microcontroller */
+	cx25840_and_or(client, 0x803, ~0x10, 0x10);
+}
+
+/* ----------------------------------------------------------------------- */
+
 void cx25840_std_setup(struct i2c_client *client)
 {
 	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
@@ -414,39 +485,41 @@ void cx25840_std_setup(struct i2c_client *client)
 	}
 
 	/* DEBUG: Displays configured PLL frequency */
-	pll_int = cx25840_read(client, 0x108);
-	pll_frac = cx25840_read4(client, 0x10c) & 0x1ffffff;
-	pll_post = cx25840_read(client, 0x109);
-	v4l_dbg(1, cx25840_debug, client,
-				"PLL regs = int: %u, frac: %u, post: %u\n",
-				pll_int, pll_frac, pll_post);
-
-	if (pll_post) {
-		int fin, fsc;
-		int pll = (28636363L * ((((u64)pll_int) << 25L) + pll_frac)) >> 25L;
-
-		pll /= pll_post;
-		v4l_dbg(1, cx25840_debug, client, "PLL = %d.%06d MHz\n",
-				pll / 1000000, pll % 1000000);
-		v4l_dbg(1, cx25840_debug, client, "PLL/8 = %d.%06d MHz\n",
-				pll / 8000000, (pll / 8) % 1000000);
-
-		fin = ((u64)src_decimation * pll) >> 12;
+	if (!state->is_cx231xx) {
+		pll_int = cx25840_read(client, 0x108);
+		pll_frac = cx25840_read4(client, 0x10c) & 0x1ffffff;
+		pll_post = cx25840_read(client, 0x109);
 		v4l_dbg(1, cx25840_debug, client,
-				"ADC Sampling freq = %d.%06d MHz\n",
-				fin / 1000000, fin % 1000000);
-
-		fsc = (((u64)sc) * pll) >> 24L;
-		v4l_dbg(1, cx25840_debug, client,
-				"Chroma sub-carrier freq = %d.%06d MHz\n",
-				fsc / 1000000, fsc % 1000000);
-
-		v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, "
-			"vblank %i, vactive %i, vblank656 %i, src_dec %i, "
-			"burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x, "
-			"sc 0x%06x\n",
-			hblank, hactive, vblank, vactive, vblank656,
-			src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
+			"PLL regs = int: %u, frac: %u, post: %u\n",
+			pll_int, pll_frac, pll_post);
+
+		if (pll_post) {
+			int fin, fsc;
+			int pll = (28636363L * ((((u64)pll_int) << 25L) + pll_frac)) >> 25L;
+
+			pll /= pll_post;
+			v4l_dbg(1, cx25840_debug, client, "PLL = %d.%06d MHz\n",
+					pll / 1000000, pll % 1000000);
+			v4l_dbg(1, cx25840_debug, client, "PLL/8 = %d.%06d MHz\n",
+					pll / 8000000, (pll / 8) % 1000000);
+
+			fin = ((u64)src_decimation * pll) >> 12;
+			v4l_dbg(1, cx25840_debug, client,
+					"ADC Sampling freq = %d.%06d MHz\n",
+					fin / 1000000, fin % 1000000);
+
+			fsc = (((u64)sc) * pll) >> 24L;
+			v4l_dbg(1, cx25840_debug, client,
+					"Chroma sub-carrier freq = %d.%06d MHz\n",
+					fsc / 1000000, fsc % 1000000);
+
+			v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, "
+				"vblank %i, vactive %i, vblank656 %i, src_dec %i, "
+				"burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x, "
+				"sc 0x%06x\n",
+				hblank, hactive, vblank, vactive, vblank656,
+				src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
+		}
 	}
 
 	/* Sets horizontal blanking delay and active lines */
@@ -596,7 +669,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
 	 * configuration in reg (for the cx23885) so we have no
 	 * need to attempt to flip bits for earlier av decoders.
 	 */
-	if (!state->is_cx23885) {
+	if (!state->is_cx23885 && !state->is_cx231xx) {
 		switch (aud_input) {
 		case CX25840_AUDIO_SERIAL:
 			/* do nothing, use serial audio input */
@@ -619,7 +692,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
 	/* Set INPUT_MODE to Composite (0) or S-Video (1) */
 	cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02);
 
-	if (!state->is_cx23885) {
+	if (!state->is_cx23885 && !state->is_cx231xx) {
 		/* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
 		cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
 		/* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2&CH3 */
@@ -659,6 +732,19 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
 		 */
 		cx25840_write(client, 0x918, 0xa0);
 		cx25840_write(client, 0x919, 0x01);
+	} else if (state->is_cx231xx) {
+		/* Audio channel 1 src : Parallel 1 */
+		cx25840_write(client, 0x124, 0x03);
+
+		/* I2S_IN_CTL: I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 */
+		cx25840_write(client, 0x914, 0xa0);
+
+		/* I2S_OUT_CTL:
+		 * I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1
+		 * I2S_OUT_MASTER_MODE = Master
+		 */
+		cx25840_write(client, 0x918, 0xa0);
+		cx25840_write(client, 0x919, 0x01);
 	}
 
 	return 0;
@@ -1118,6 +1204,8 @@ static int cx25840_init(struct v4l2_subdev *sd, u32 val)
 			cx25836_initialize(client);
 		else if (state->is_cx23885)
 			cx23885_initialize(client);
+		else if (state->is_cx231xx)
+			cx231xx_initialize(client);
 		else
 			cx25840_initialize(client);
 	}
@@ -1159,7 +1247,7 @@ static int cx25840_s_stream(struct v4l2_subdev *sd, int enable)
 	v4l_dbg(1, cx25840_debug, client, "%s output\n",
 			enable ? "enable" : "disable");
 	if (enable) {
-		if (state->is_cx23885) {
+		if (state->is_cx23885 || state->is_cx231xx) {
 			u8 v = (cx25840_read(client, 0x421) | 0x0b);
 			cx25840_write(client, 0x421, v);
 		} else {
@@ -1169,7 +1257,7 @@ static int cx25840_s_stream(struct v4l2_subdev *sd, int enable)
 					state->is_cx25836 ? 0x04 : 0x07);
 		}
 	} else {
-		if (state->is_cx23885) {
+		if (state->is_cx23885 || state->is_cx231xx) {
 			u8 v = cx25840_read(client, 0x421) & ~(0x0b);
 			cx25840_write(client, 0x421, v);
 		} else {
@@ -1350,6 +1438,8 @@ static int cx25840_reset(struct v4l2_subdev *sd, u32 val)
 		cx25836_initialize(client);
 	else if (state->is_cx23885)
 		cx23885_initialize(client);
+	else if (state->is_cx231xx)
+		cx231xx_initialize(client);
 	else
 		cx25840_initialize(client);
 	return 0;
@@ -1449,6 +1539,8 @@ static int cx25840_probe(struct i2c_client *client,
 		id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6;
 	} else if (device_id == 0x1313) {
 		id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6;
+	} else if ((device_id & 0xfff0) == 0x5A30) {
+		id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf);
 	}
 	else {
 		v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n");
@@ -1471,6 +1563,7 @@ static int cx25840_probe(struct i2c_client *client,
 	state->c = client;
 	state->is_cx25836 = ((device_id & 0xff00) == 0x8300);
 	state->is_cx23885 = (device_id == 0x0000) || (device_id == 0x1313);
+	state->is_cx231xx = (device_id == 0x5a3e);
 	state->vid_input = CX25840_COMPOSITE7;
 	state->aud_input = CX25840_AUDIO8;
 	state->audclk_freq = 48000;
diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h
index 9ad0eb8..814b565 100644
--- a/drivers/media/video/cx25840/cx25840-core.h
+++ b/drivers/media/video/cx25840/cx25840-core.h
@@ -50,6 +50,7 @@ struct cx25840_state {
 	u32 rev;
 	int is_cx25836;
 	int is_cx23885;
+	int is_cx231xx;
 	int is_initialized;
 	wait_queue_head_t fw_wait;    /* wake up when the fw load is finished */
 	struct work_struct fw_work;   /* work entry for fw load */
diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c
index 0b2dceb..0df53b0 100644
--- a/drivers/media/video/cx25840/cx25840-firmware.c
+++ b/drivers/media/video/cx25840/cx25840-firmware.c
@@ -25,6 +25,7 @@
 
 #define FWFILE "v4l-cx25840.fw"
 #define FWFILE_CX23885 "v4l-cx23885-avcore-01.fw"
+#define FWFILE_CX231XX "v4l-cx231xx-avcore-01.fw"
 
 /*
  * Mike Isely <isely@pobox.com> - The FWSEND parameter controls the
@@ -96,9 +97,17 @@ int cx25840_loadfw(struct i2c_client *client)
 	u8 buffer[FWSEND];
 	const u8 *ptr;
 	int size, retval;
+	int MAX_BUF_SIZE = FWSEND;
 
 	if (state->is_cx23885)
 		firmware = FWFILE_CX23885;
+	else if (state->is_cx231xx)
+		firmware = FWFILE_CX231XX;
+
+	if ((state->is_cx231xx) && MAX_BUF_SIZE > 16) {
+		v4l_err(client, " Firmware download size changed to 16 bytes max length\n");
+		MAX_BUF_SIZE = 16;  /* cx231xx cannot accept more than 16 bytes at a time */
+	}
 
 	if (request_firmware(&fw, firmware, FWDEV(client)) != 0) {
 		v4l_err(client, "unable to open firmware %s\n", firmware);
@@ -113,7 +122,7 @@ int cx25840_loadfw(struct i2c_client *client)
 	size = fw->size;
 	ptr = fw->data;
 	while (size > 0) {
-		int len = min(FWSEND - 2, size);
+		int len = min(MAX_BUF_SIZE - 2, size);
 
 		memcpy(buffer + 2, ptr, len);
 
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index f27604a..f9d48c9 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -88,6 +88,7 @@
 #define I2C_HW_B_CX2341X	0x010020 /* Conexant CX2341X MPEG encoder cards */
 #define I2C_HW_B_CX23885	0x010022 /* conexant 23885 based tv cards (bus1) */
 #define I2C_HW_B_AU0828		0x010023 /* auvitek au0828 usb bridge */
+#define I2C_HW_B_CX231XX	0x010024 /* Conexant CX231XX USB based cards */
 #define I2C_HW_B_HDPVR		0x010025 /* Hauppauge HD PVR */
 
 /* --- SGI adapters							*/
diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
index ea1bf5b..3d7533d 100644
--- a/include/linux/mmc/sdio_ids.h
+++ b/include/linux/mmc/sdio_ids.h
@@ -24,6 +24,14 @@
  */
 
 #define SDIO_VENDOR_ID_MARVELL			0x02df
+#define SDIO_VENDOR_ID_SIANO			0x039a
+
 #define SDIO_DEVICE_ID_MARVELL_LIBERTAS		0x9103
+#define SDIO_DEVICE_ID_SIANO_STELLAR 		0x5347
+#define SDIO_DEVICE_ID_SIANO_NOVA_A0		0x1100
+#define SDIO_DEVICE_ID_SIANO_NOVA_B0		0x0201
+#define SDIO_DEVICE_ID_SIANO_NICE		0x0202
+#define SDIO_DEVICE_ID_SIANO_VEGA_A0		0x0300
+#define SDIO_DEVICE_ID_SIANO_VENICE		0x0301
 
 #endif