V4L/DVB (12730): Add conexant cx25821 driver
authorMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 15 Sep 2009 14:33:54 +0000 (11:33 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 19 Sep 2009 02:47:36 +0000 (23:47 -0300)
GIT_BRANCH=devel
GIT_AUTHOR_DATE=1252851239
GIT_AUTHOR_NAME=Palash Bandyopadhyay
GIT_AUTHOR_EMAIL=Palash.Bandyopadhyay@conexant.com
Add conexant cx25821 driver release v106 of the Athena driver.

Signed-off-by: Palash Bandyopadhyay <palash.bandyopadhyay@conexant.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
37 files changed:
drivers/staging/cx25821/Kconfig [new file with mode: 0644]
drivers/staging/cx25821/Makefile [new file with mode: 0644]
drivers/staging/cx25821/cx25821-alsa.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-audio-upstream.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-audio-upstream.h [new file with mode: 0644]
drivers/staging/cx25821/cx25821-audio.h [new file with mode: 0644]
drivers/staging/cx25821/cx25821-audups11.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-biffuncs.h [new file with mode: 0644]
drivers/staging/cx25821/cx25821-cards.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-core.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-gpio.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-gpio.h [new file with mode: 0644]
drivers/staging/cx25821/cx25821-i2c.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-medusa-defines.h [new file with mode: 0644]
drivers/staging/cx25821/cx25821-medusa-reg.h [new file with mode: 0644]
drivers/staging/cx25821/cx25821-medusa-video.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-medusa-video.h [new file with mode: 0644]
drivers/staging/cx25821/cx25821-reg.h [new file with mode: 0644]
drivers/staging/cx25821/cx25821-sram.h [new file with mode: 0644]
drivers/staging/cx25821/cx25821-video-upstream-ch2.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-video-upstream-ch2.h [new file with mode: 0644]
drivers/staging/cx25821/cx25821-video-upstream.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-video-upstream.h [new file with mode: 0644]
drivers/staging/cx25821/cx25821-video.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-video.h [new file with mode: 0644]
drivers/staging/cx25821/cx25821-video0.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-video1.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-video2.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-video3.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-video4.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-video5.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-video6.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-video7.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-videoioctl.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-vidups10.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821-vidups9.c [new file with mode: 0644]
drivers/staging/cx25821/cx25821.h [new file with mode: 0644]

diff --git a/drivers/staging/cx25821/Kconfig b/drivers/staging/cx25821/Kconfig
new file mode 100644 (file)
index 0000000..8887115
--- /dev/null
@@ -0,0 +1,34 @@
+config VIDEO_CX25821
+       tristate "Conexant cx25821 support"
+       depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT
+       select I2C_ALGOBIT
+       select VIDEO_BTCX
+       select VIDEO_TVEEPROM
+       select VIDEO_IR
+       select VIDEOBUF_DVB
+       select VIDEOBUF_DMA_SG
+       select VIDEO_CX25840
+       select VIDEO_CX2341X
+       ---help---
+         This is a video4linux driver for Conexant 25821 based
+         TV cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx25821
+         
+config VIDEO_CX25821_ALSA
+       tristate "Conexant 25821 DMA audio support"
+       depends on VIDEO_CX25821 && SND && EXPERIMENTAL
+       select SND_PCM
+       ---help---
+         This is a video4linux driver for direct (DMA) audio on
+         Conexant 25821 based capture cards using ALSA.
+
+         It only works with boards with function 01 enabled.
+         To check if your board supports, use lspci -n.
+         If supported, you should see 14f1:8801 or 14f1:8811
+         PCI device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx25821-alsa.     
+
diff --git a/drivers/staging/cx25821/Makefile b/drivers/staging/cx25821/Makefile
new file mode 100644 (file)
index 0000000..020d844
--- /dev/null
@@ -0,0 +1,15 @@
+cx25821-objs   := cx25821-core.o cx25821-cards.o cx25821-i2c.o cx25821-gpio.o                          \
+                               cx25821-medusa-video.o cx25821-video.o cx25821-video0.o cx25821-video1.o    \
+                               cx25821-video2.o cx25821-video3.o cx25821-video4.o cx25821-video5.o         \
+                               cx25821-video6.o cx25821-video7.o cx25821-vidups9.o cx25821-vidups10.o      \
+                               cx25821-audups11.o cx25821-video-upstream.o cx25821-video-upstream-ch2.o        \
+                               cx25821-audio-upstream.o cx25821-videoioctl.o
+
+obj-$(CONFIG_VIDEO_CX25821) += cx25821.o
+obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o
+
+EXTRA_CFLAGS += -Idrivers/media/video
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
+
+EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/staging/cx25821/cx25821-alsa.c b/drivers/staging/cx25821/cx25821-alsa.c
new file mode 100644 (file)
index 0000000..6b2e86a
--- /dev/null
@@ -0,0 +1,791 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>\r
+ *     Based on SAA713x ALSA driver and CX88 driver\r
+ *\r
+ *   This program is free software; you can redistribute it and/or modify\r
+ *   it under the terms of the GNU General Public License as published by\r
+ *   the Free Software Foundation, version 2\r
+ *\r
+ *   This program is distributed in the hope that it will be useful,\r
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *   GNU General Public License for more details.\r
+ *\r
+ *   You should have received a copy of the GNU General Public License\r
+ *   along with this program; if not, write to the Free Software\r
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA\r
+ *\r
+ */\r
+\r
+\r
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+
+#include <asm/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+
+#include "cx25821.h"
+#include "cx25821-reg.h"
+
+#define AUDIO_SRAM_CHANNEL     SRAM_CH08
+
+#define dprintk(level,fmt, arg...)     if (debug >= level) \
+       printk(KERN_INFO "%s/1: " fmt, chip->dev->name , ## arg)
+
+#define dprintk_core(level,fmt, arg...)        if (debug >= level) \
+       printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name , ## arg)
+
+
+/****************************************************************************
+       Data type declarations - Can be moded to a header file later
+ ****************************************************************************/
+
+
+static struct snd_card *snd_cx25821_cards[SNDRV_CARDS];
+static int devno;
+
+struct cx25821_audio_dev {
+       struct cx25821_dev           *dev;
+       struct cx25821_dmaqueue       q;
+
+       /* pci i/o */
+       struct pci_dev             *pci;
+
+       /* audio controls */
+       int                        irq;
+
+       struct snd_card            *card;
+
+       unsigned long iobase;
+       spinlock_t                 reg_lock;
+       atomic_t                           count;
+
+       unsigned int               dma_size;
+       unsigned int               period_size;
+       unsigned int               num_periods;
+
+       struct videobuf_dmabuf     *dma_risc;
+
+       struct cx25821_buffer      *buf;
+
+       struct snd_pcm_substream   *substream;
+};
+typedef struct cx25821_audio_dev snd_cx25821_card_t;
+
+
+
+/****************************************************************************
+                       Module global static vars
+ ****************************************************************************/
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
+static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled.");
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for cx25821 capture interface(s).");
+
+
+/****************************************************************************
+                               Module macros
+ ****************************************************************************/
+
+MODULE_DESCRIPTION("ALSA driver module for cx25821 based capture cards");
+MODULE_AUTHOR("Hiep Huynh");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Conexant,25821}");//"{{Conexant,23881},"
+
+static unsigned int debug;
+module_param(debug,int,0644);
+MODULE_PARM_DESC(debug,"enable debug messages");
+
+/****************************************************************************
+                       Module specific funtions
+ ****************************************************************************/
+/* Constants taken from cx88-reg.h */
+#define AUD_INT_DN_RISCI1       (1 <<  0)
+#define AUD_INT_UP_RISCI1       (1 <<  1)
+#define AUD_INT_RDS_DN_RISCI1   (1 <<  2)
+#define AUD_INT_DN_RISCI2       (1 <<  4) /* yes, 3 is skipped */
+#define AUD_INT_UP_RISCI2       (1 <<  5)
+#define AUD_INT_RDS_DN_RISCI2   (1 <<  6)
+#define AUD_INT_DN_SYNC         (1 << 12)
+#define AUD_INT_UP_SYNC         (1 << 13)
+#define AUD_INT_RDS_DN_SYNC     (1 << 14)
+#define AUD_INT_OPC_ERR         (1 << 16)
+#define AUD_INT_BER_IRQ         (1 << 20)
+#define AUD_INT_MCHG_IRQ        (1 << 21)
+#define GP_COUNT_CONTROL_RESET 0x3
+
+#define PCI_MSK_AUD_EXT   (1 <<  4)
+#define PCI_MSK_AUD_INT   (1 <<  3)
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int _cx25821_start_audio_dma(snd_cx25821_card_t *chip)
+{
+       struct cx25821_buffer   *buf = chip->buf;
+       struct cx25821_dev * dev = chip->dev;
+       struct sram_channel *audio_ch = &cx25821_sram_channels[AUDIO_SRAM_CHANNEL];
+       u32 tmp = 0;
+
+       // enable output on the GPIO 0 for the MCLK ADC (Audio)
+       cx25821_set_gpiopin_direction( chip->dev, 0, 0 );
+
+       /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
+       cx_clear(AUD_INT_DMA_CTL, FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN );
+
+       /* setup fifo + format - out channel */
+       cx25821_sram_channel_setup_audio(chip->dev, audio_ch, buf->bpl, buf->risc.dma);
+
+       /* sets bpl size */
+       cx_write(AUD_A_LNGTH, buf->bpl);
+
+       /* reset counter */
+       cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);              //GP_COUNT_CONTROL_RESET = 0x3
+       atomic_set(&chip->count, 0);
+
+    //Set the input mode to 16-bit
+    tmp = cx_read(AUD_A_CFG);
+    cx_write(AUD_A_CFG, tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE | FLD_AUD_CLK_ENABLE);
+
+       //printk(KERN_INFO "DEBUG: Start audio DMA, %d B/line, cmds_start(0x%x)= %d lines/FIFO, %d periods, %d "
+       //      "byte buffer\n", buf->bpl, audio_ch->cmds_start, cx_read(audio_ch->cmds_start + 12)>>1,
+       //      chip->num_periods, buf->bpl * chip->num_periods);
+
+
+       /* Enables corresponding bits at AUD_INT_STAT */
+       cx_write(AUD_A_INT_MSK, FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF | FLD_AUD_DST_SYNC | FLD_AUD_DST_OPC_ERR );
+
+       /* Clean any pending interrupt bits already set */
+       cx_write(AUD_A_INT_STAT, ~0);
+
+       /* enable audio irqs */
+       cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT);
+
+    // Turn on audio downstream fifo and risc enable 0x101
+    tmp = cx_read(AUD_INT_DMA_CTL);
+       cx_set(AUD_INT_DMA_CTL, tmp | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN) );
+
+       mdelay(100);
+       return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int _cx25821_stop_audio_dma(snd_cx25821_card_t *chip)
+{
+       struct cx25821_dev *dev = chip->dev;
+
+       /* stop dma */
+       cx_clear(AUD_INT_DMA_CTL,  FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN );
+
+       /* disable irqs */
+       cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
+       cx_clear(AUD_A_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |     AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
+
+       return 0;
+}
+
+#define MAX_IRQ_LOOP 50
+
+/*
+ * BOARD Specific: IRQ dma bits
+ */
+static char *cx25821_aud_irqs[32] = {
+       "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */
+       NULL,                                     /* reserved */
+       "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */
+       NULL,                                     /* reserved */
+       "dnf_of", "upf_uf", "rds_dnf_uf",         /* 8-10 */
+       NULL,                                     /* reserved */
+       "dn_sync", "up_sync", "rds_dn_sync",      /* 12-14 */
+       NULL,                                     /* reserved */
+       "opc_err", "par_err", "rip_err",          /* 16-18 */
+       "pci_abort", "ber_irq", "mchg_irq"        /* 19-21 */
+};
+
+/*
+ * BOARD Specific: Threats IRQ audio specific calls
+ */
+static void cx25821_aud_irq(snd_cx25821_card_t *chip, u32 status, u32 mask)
+{
+       struct cx25821_dev *dev = chip->dev;
+
+       if (0 == (status & mask))
+       {
+               return;
+       }
+
+       cx_write(AUD_A_INT_STAT, status);
+       if (debug > 1  ||  (status & mask & ~0xff))
+               cx25821_print_irqbits(dev->name, "irq aud",
+                                  cx25821_aud_irqs, ARRAY_SIZE(cx25821_aud_irqs),
+                                  status, mask);
+
+       /* risc op code error */
+       if (status & AUD_INT_OPC_ERR) {
+               printk(KERN_WARNING "WARNING %s/1: Audio risc op code error\n",dev->name);
+
+               cx_clear(AUD_INT_DMA_CTL, FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN );
+               cx25821_sram_channel_dump_audio(dev, &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]);
+       }
+       if (status & AUD_INT_DN_SYNC) {
+               printk(KERN_WARNING "WARNING %s: Downstream sync error!\n",dev->name);
+               cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+               return;
+       }
+
+
+       /* risc1 downstream */
+       if (status & AUD_INT_DN_RISCI1) {
+               atomic_set(&chip->count, cx_read(AUD_A_GPCNT));
+               snd_pcm_period_elapsed(chip->substream);
+       }
+}
+
+
+/*
+ * BOARD Specific: Handles IRQ calls
+ */
+static irqreturn_t cx25821_irq(int irq, void *dev_id)
+{
+       snd_cx25821_card_t *chip = dev_id;
+       struct cx25821_dev *dev = chip->dev;
+       u32 status, pci_status;
+       u32 audint_status, audint_mask;
+       int loop, handled = 0;
+       int audint_count = 0;
+
+
+       audint_status = cx_read(AUD_A_INT_STAT);
+       audint_mask   = cx_read(AUD_A_INT_MSK);
+       audint_count = cx_read(AUD_A_GPCNT);
+       status = cx_read(PCI_INT_STAT);
+
+       for (loop = 0; loop < 1; loop++)
+       {
+               status = cx_read(PCI_INT_STAT);
+               if (0 == status)
+               {
+                       status = cx_read(PCI_INT_STAT);
+                       audint_status = cx_read(AUD_A_INT_STAT);
+                       audint_mask = cx_read(AUD_A_INT_MSK);
+
+                       if (status)
+                       {
+                               handled = 1;
+                               cx_write(PCI_INT_STAT, status);
+
+                               cx25821_aud_irq(chip, audint_status, audint_mask);
+                               break;
+                       }
+                       else
+                               goto out;
+               }
+
+               handled = 1;
+               cx_write(PCI_INT_STAT, status);
+
+               cx25821_aud_irq(chip, audint_status, audint_mask);
+       }
+
+       pci_status = cx_read(PCI_INT_STAT);
+
+       if (handled)
+               cx_write(PCI_INT_STAT, pci_status);
+
+ out:
+       return IRQ_RETVAL(handled);
+}
+
+
+static int dsp_buffer_free(snd_cx25821_card_t *chip)
+{
+       BUG_ON(!chip->dma_size);
+
+       dprintk(2,"Freeing buffer\n");
+       videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc);
+       videobuf_dma_free(chip->dma_risc);
+       btcx_riscmem_free(chip->pci,&chip->buf->risc);
+       kfree(chip->buf);
+
+       chip->dma_risc = NULL;
+       chip->dma_size = 0;
+
+       return 0;
+}
+
+/****************************************************************************
+                               ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE      384
+static struct snd_pcm_hardware snd_cx25821_digital_hw = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID,
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+       .rates =                SNDRV_PCM_RATE_48000,
+       .rate_min =             48000,
+       .rate_max =             48000,
+       .channels_min = 2,
+       .channels_max = 2,
+       /* Analog audio output will be full of clicks and pops if there
+          are not exactly four lines in the SRAM FIFO buffer.  */
+       .period_bytes_min = DEFAULT_FIFO_SIZE/3,
+       .period_bytes_max = DEFAULT_FIFO_SIZE/3,
+       .periods_min = 1,
+       .periods_max = AUDIO_LINE_SIZE,
+       .buffer_bytes_max = (AUDIO_LINE_SIZE*AUDIO_LINE_SIZE),          //128*128 = 16384 = 1024 * 16
+};
+
+
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream)
+{
+       snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int err;
+       unsigned int bpl = 0;
+
+       if (!chip) {
+               printk(KERN_ERR "DEBUG: cx25821 can't find device struct."
+                               " Can't proceed with open\n");
+               return -ENODEV;
+       }
+
+       err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS);
+       if (err < 0)
+               goto _error;
+
+       chip->substream = substream;
+
+       runtime->hw = snd_cx25821_digital_hw;
+
+       if (cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size != DEFAULT_FIFO_SIZE)
+       {
+               bpl = cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 3;          //since there are 3 audio Clusters
+               bpl &= ~7; /* must be multiple of 8 */
+
+               if( bpl > AUDIO_LINE_SIZE )
+               {
+                       bpl = AUDIO_LINE_SIZE;
+               }
+               runtime->hw.period_bytes_min = bpl;
+               runtime->hw.period_bytes_max = bpl;
+       }
+
+       return 0;
+_error:
+       dprintk(1,"Error opening PCM!\n");
+       return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_cx25821_close(struct snd_pcm_substream *substream)
+{
+       return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_cx25821_hw_params(struct snd_pcm_substream * substream,
+                             struct snd_pcm_hw_params * hw_params)
+{
+       snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream);
+       struct videobuf_dmabuf *dma;
+
+       struct cx25821_buffer *buf;
+       int ret;
+
+       if (substream->runtime->dma_area) {
+               dsp_buffer_free(chip);
+               substream->runtime->dma_area = NULL;
+       }
+
+
+       chip->period_size = params_period_bytes(hw_params);
+       chip->num_periods = params_periods(hw_params);
+       chip->dma_size = chip->period_size * params_periods(hw_params);
+
+       BUG_ON(!chip->dma_size);
+       BUG_ON(chip->num_periods & (chip->num_periods-1));
+
+       buf = videobuf_sg_alloc(sizeof(*buf));
+       if (NULL == buf)
+               return -ENOMEM;
+
+
+       if( chip->period_size > AUDIO_LINE_SIZE )
+       {
+               chip->period_size = AUDIO_LINE_SIZE;
+       }
+
+
+       buf->vb.memory = V4L2_MEMORY_MMAP;
+       buf->vb.field  = V4L2_FIELD_NONE;
+       buf->vb.width  = chip->period_size;
+       buf->bpl       = chip->period_size;
+       buf->vb.height = chip->num_periods;
+       buf->vb.size   = chip->dma_size;
+
+       dma = videobuf_to_dma(&buf->vb);
+       videobuf_dma_init(dma);
+
+       ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+                       (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT));
+       if (ret < 0)
+               goto error;
+
+       ret = videobuf_sg_dma_map(&chip->pci->dev, dma);
+       if (ret < 0)
+               goto error;
+
+
+       ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist,  buf->vb.width, buf->vb.height, 1);
+       if (ret < 0)
+       {
+               printk(KERN_INFO "DEBUG: ERROR after cx25821_risc_databuffer_audio() \n");
+               goto error;
+       }
+
+
+       /* Loop back to start of program */
+       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
+       buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+       buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+
+       chip->buf = buf;
+       chip->dma_risc = dma;
+
+       substream->runtime->dma_area = chip->dma_risc->vmalloc;
+       substream->runtime->dma_bytes = chip->dma_size;
+       substream->runtime->dma_addr = 0;
+
+       return 0;
+
+error:
+       kfree(buf);
+       return ret;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx25821_hw_free(struct snd_pcm_substream * substream)
+{
+       snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream);
+
+       if (substream->runtime->dma_area) {
+               dsp_buffer_free(chip);
+               substream->runtime->dma_area = NULL;
+       }
+
+       return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_cx25821_prepare(struct snd_pcm_substream *substream)
+{
+       return 0;
+}
+
+/*
+ * trigger callback
+ */
+static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream);
+       int err = 0;
+
+       /* Local interrupts are already disabled by ALSA */
+       spin_lock(&chip->reg_lock);
+
+       switch (cmd)
+       {
+               case SNDRV_PCM_TRIGGER_START:
+                       err = _cx25821_start_audio_dma(chip);
+                       break;
+               case SNDRV_PCM_TRIGGER_STOP:
+                       err = _cx25821_stop_audio_dma(chip);
+                       break;
+               default:
+                       err = -EINVAL;
+                       break;
+       }
+
+       spin_unlock(&chip->reg_lock);
+
+       return err;
+}
+
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_cx25821_pointer(struct snd_pcm_substream *substream)
+{
+       snd_cx25821_card_t *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       u16 count;
+
+       count = atomic_read(&chip->count);
+
+       return runtime->period_size * (count & (runtime->periods-1));
+}
+
+/*
+ * page callback (needed for mmap)
+ */
+static struct page *snd_cx25821_page(struct snd_pcm_substream *substream,
+                               unsigned long offset)
+{
+       void *pageptr = substream->runtime->dma_area + offset;
+
+       return vmalloc_to_page(pageptr);
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_cx25821_pcm_ops = {
+       .open = snd_cx25821_pcm_open,
+       .close = snd_cx25821_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = snd_cx25821_hw_params,
+       .hw_free = snd_cx25821_hw_free,
+       .prepare = snd_cx25821_prepare,
+       .trigger = snd_cx25821_card_trigger,
+       .pointer = snd_cx25821_pointer,
+       .page = snd_cx25821_page,
+};
+
+
+/*
+ * ALSA create a PCM device:  Called when initializing the board. Sets up the name and hooks up
+ *  the callbacks
+ */
+static int snd_cx25821_pcm(snd_cx25821_card_t *chip, int device, char *name)
+{
+       struct snd_pcm *pcm;
+       int err;
+
+       err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
+       if (err < 0)
+       {
+               printk(KERN_INFO "ERROR: FAILED snd_pcm_new() in %s\n", __func__);
+               return err;
+       }
+       pcm->private_data = chip;
+       pcm->info_flags = 0;
+       strcpy(pcm->name, name);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx25821_pcm_ops);
+
+       return 0;
+}
+
+
+/****************************************************************************
+                       Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
+ * Only boards with eeprom and byte 1 at eeprom=1 have it
+ */
+
+static struct pci_device_id cx25821_audio_pci_tbl[] __devinitdata = {
+       {0x14f1,0x0920,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+       {0, }
+};
+MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl);
+
+/*\r
+ * Not used in the function snd_cx25821_dev_free so removing\r
+ * from the file.\r
+ */\r
+/*
+static int snd_cx25821_free(snd_cx25821_card_t *chip)
+{
+       if (chip->irq >= 0)
+               free_irq(chip->irq, chip);
+
+       cx25821_dev_unregister(chip->dev);
+       pci_disable_device(chip->pci);
+
+       return 0;
+}
+*/\r
+
+/*
+ * Component Destructor
+ */
+static void snd_cx25821_dev_free(struct snd_card * card)
+{
+       snd_cx25821_card_t *chip = card->private_data;
+
+       //snd_cx25821_free(chip);
+       snd_card_free(chip->card);
+}
+
+
+/*
+ * Alsa Constructor - Component probe
+ */
+static int cx25821_audio_initdev(struct cx25821_dev *dev)
+{
+       struct snd_card  *card;
+       snd_cx25821_card_t  *chip;
+       int              err;
+
+       if (devno >= SNDRV_CARDS)
+       {
+           printk(KERN_INFO "DEBUG ERROR: devno >= SNDRV_CARDS %s\n", __func__);
+               return (-ENODEV);
+       }
+
+       if (!enable[devno]) {
+               ++devno;
+               printk(KERN_INFO "DEBUG ERROR: !enable[devno] %s\n", __func__);
+               return (-ENOENT);
+       }
+
+       card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx25821_card_t));
+       if (!card)
+       {
+           printk(KERN_INFO "DEBUG ERROR: cannot create snd_card_new in %s\n", __func__);
+               return (-ENOMEM);
+       }
+
+       strcpy(card->driver, "cx25821");
+
+       /* Card "creation" */
+       card->private_free = snd_cx25821_dev_free;
+       chip = (snd_cx25821_card_t *) card->private_data;
+       spin_lock_init(&chip->reg_lock);
+
+       chip->dev = dev;
+       chip->card = card;
+       chip->pci = dev->pci;
+       chip->iobase = pci_resource_start(dev->pci, 0);
+
+
+       chip->irq = dev->pci->irq;
+
+       err = request_irq(dev->pci->irq, cx25821_irq,
+                         IRQF_SHARED | IRQF_DISABLED, chip->dev->name, chip);
+
+       if (err < 0) {
+               printk(KERN_ERR "ERROR %s: can't get IRQ %d for ALSA\n", chip->dev->name, dev->pci->irq);
+               goto error;
+       }
+
+
+       if ((err = snd_cx25821_pcm(chip, 0, "cx25821 Digital")) < 0)
+       {
+           printk(KERN_INFO "DEBUG ERROR: cannot create snd_cx25821_pcm %s\n", __func__);
+               goto error;
+       }
+
+       snd_card_set_dev(card, &chip->pci->dev);
+
+
+       strcpy(card->shortname, "cx25821");
+       sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name, chip->iobase, chip->irq);
+       strcpy (card->mixername, "CX25821");
+
+       printk(KERN_INFO "%s/%i: ALSA support for cx25821 boards\n", card->driver, devno);
+
+       err = snd_card_register(card);
+       if (err < 0)
+       {
+           printk(KERN_INFO "DEBUG ERROR: cannot register sound card %s\n", __func__);
+               goto error;
+       }
+
+       snd_cx25821_cards[devno] = card;
+
+       devno++;
+       return 0;
+
+error:
+       snd_card_free(card);
+       return err;
+}
+
+
+/****************************************************************************
+                               LINUX MODULE INIT
+ ****************************************************************************/
+static void cx25821_audio_fini(void)
+{
+       snd_card_free(snd_cx25821_cards[0]);
+}
+
+/*
+ * Module initializer
+ *
+ * Loops through present saa7134 cards, and assigns an ALSA device
+ * to each one
+ *
+ */
+static int cx25821_alsa_init(void)
+{
+       struct cx25821_dev *dev = NULL;
+       struct list_head *list;
+
+       list_for_each(list,&cx25821_devlist) {
+               dev = list_entry(list, struct cx25821_dev, devlist);
+               cx25821_audio_initdev(dev);
+       }
+
+       if (dev == NULL)
+               printk(KERN_INFO "cx25821 ERROR ALSA: no cx25821 cards found\n");
+
+       return 0;
+
+}
+
+late_initcall(cx25821_alsa_init);
+module_exit(cx25821_audio_fini);
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/staging/cx25821/cx25821-audio-upstream.c b/drivers/staging/cx25821/cx25821-audio-upstream.c
new file mode 100644 (file)
index 0000000..9138767
--- /dev/null
@@ -0,0 +1,825 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.com>\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+\r
+#include "cx25821-video.h"\r
+#include "cx25821-audio-upstream.h"\r
+\r
+#include <linux/fs.h> \r
+#include <linux/errno.h>\r
+#include <linux/kernel.h>\r
+#include <linux/init.h>\r
+#include <linux/module.h>\r
+#include <linux/syscalls.h>\r
+#include <linux/file.h>\r
+#include <linux/fcntl.h>\r
+#include <linux/delay.h>\r
+#include <asm/uaccess.h>\r
+\r
+\r
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");\r
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");\r
+MODULE_LICENSE("GPL");\r
+\r
+\r
+static int _intr_msk = FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF | FLD_AUD_SRC_SYNC | FLD_AUD_SRC_OPC_ERR;\r
+\r
+\r
+int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev,\r
+                                                   struct sram_channel *ch,\r
+                                                   unsigned int bpl, u32 risc)\r
+{\r
+       unsigned int i, lines;\r
+       u32 cdt;\r
+\r
+    \r
+       if (ch->cmds_start == 0) {\r
+               cx_write(ch->ptr1_reg, 0);\r
+               cx_write(ch->ptr2_reg, 0);\r
+               cx_write(ch->cnt2_reg, 0);\r
+               cx_write(ch->cnt1_reg, 0);\r
+               return 0;\r
+       } \r
+\r
+       bpl   = (bpl + 7) & ~7; /* alignment */\r
+       cdt   = ch->cdt;\r
+       lines = ch->fifo_size / bpl;\r
+    \r
+    if (lines > 3)     \r
+    {\r
+        lines = 3;\r
+    }\r
+    \r
+       BUG_ON(lines < 2);\r
+\r
+\r
+       /* write CDT */\r
+       for (i = 0; i < lines; i++) {\r
+               cx_write(cdt + 16*i, ch->fifo_start + bpl*i);\r
+               cx_write(cdt + 16*i +  4, 0);\r
+               cx_write(cdt + 16*i +  8, 0);\r
+               cx_write(cdt + 16*i + 12, 0);\r
+       }\r
+\r
+       /* write CMDS */    \r
+    cx_write(ch->cmds_start + 0, risc);         \r
+    \r
+       cx_write(ch->cmds_start +  4, 0);                       \r
+       cx_write(ch->cmds_start +  8, cdt);                     \r
+       cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW);       \r
+       cx_write(ch->cmds_start + 16, ch->ctrl_start);          \r
+                                               \r
+       //IQ size\r
+       cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW);        \r
+\r
+       for (i = 24; i < 80; i += 4)\r
+               cx_write(ch->cmds_start + i, 0);\r
+\r
+       /* fill registers */\r
+       cx_write(ch->ptr1_reg, ch->fifo_start);\r
+       cx_write(ch->ptr2_reg, cdt);\r
+       cx_write(ch->cnt2_reg, AUDIO_CDT_SIZE_QW);        \r
+       cx_write(ch->cnt1_reg, AUDIO_CLUSTER_SIZE_QW - 1);         \r
+\r
+       return 0;\r
+}\r
+\r
+\r
+static __le32 *cx25821_risc_field_upstream_audio( struct cx25821_dev *dev, __le32 *rp, \r
+                                                  dma_addr_t databuf_phys_addr,\r
+                                                  unsigned int bpl, int fifo_enable)\r
+{\r
+       unsigned int line;\r
+    struct sram_channel *sram_ch = &dev->sram_channels[dev->_audio_upstream_channel_select];\r
+    int offset = 0;\r
+                \r
+    \r
+       /* scan lines */\r
+       for (line = 0; line < LINES_PER_AUDIO_BUFFER; line++) \r
+    {          \r
+               *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); \r
+        *(rp++) = cpu_to_le32(databuf_phys_addr + offset);          \r
+               *(rp++) = cpu_to_le32(0); /* bits 63-32 */                       \r
+\r
+        // Check if we need to enable the FIFO after the first 3 lines \r
+        // For the upstream audio channel, the risc engine will enable the FIFO. \r
+        if ( fifo_enable && line == 2 )\r
+               {\r
+                       *(rp++) = RISC_WRITECR;\r
+                       *(rp++) = sram_ch->dma_ctl;\r
+                       *(rp++) = sram_ch->fld_aud_fifo_en;\r
+                       *(rp++) = 0x00000020;\r
+       }        \r
+        \r
+        offset += AUDIO_LINE_SIZE;\r
+       }\r
+         \r
+       return rp;\r
+}\r
+\r
+int cx25821_risc_buffer_upstream_audio( struct cx25821_dev *dev, \r
+                                  struct pci_dev *pci, \r
+                                  unsigned int bpl, unsigned int lines)\r
+{\r
+       __le32 *rp;\r
+    int fifo_enable = 0;\r
+    int frame = 0, i = 0;\r
+    int frame_size = AUDIO_DATA_BUF_SZ;\r
+    int databuf_offset = 0;\r
+    int risc_flag = RISC_CNT_INC;\r
+    dma_addr_t   risc_phys_jump_addr;\r
+\r
+        \r
+       /* Virtual address of Risc buffer program */\r
+       rp = dev->_risc_virt_addr;\r
+    \r
+       /* sync instruction */\r
+    *(rp++) = cpu_to_le32(RISC_RESYNC | AUDIO_SYNC_LINE);    \r
+    \r
+    \r
+    for( frame = 0; frame < NUM_AUDIO_FRAMES; frame++ )\r
+    {        \r
+        databuf_offset = frame_size * frame;        \r
+                \r
+        if( frame == 0 )\r
+        {\r
+            fifo_enable = 1;\r
+            risc_flag = RISC_CNT_RESET;   \r
+        }\r
+        else\r
+        {\r
+            fifo_enable = 0;\r
+            risc_flag = RISC_CNT_INC;\r
+        }\r
+        \r
+        //Calculate physical jump address \r
+        if( (frame+1) == NUM_AUDIO_FRAMES )\r
+        {\r
+            risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE;        \r
+        }\r
+        else\r
+        {\r
+            risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE + AUDIO_RISC_DMA_BUF_SIZE*(frame+1);        \r
+        }\r
+        \r
+        rp = cx25821_risc_field_upstream_audio(dev, rp, dev->_audiodata_buf_phys_addr+databuf_offset, bpl, fifo_enable);       \r
+         \r
+        \r
+        if( USE_RISC_NOOP_AUDIO )\r
+        {\r
+            for( i = 0; i < NUM_NO_OPS; i++ )\r
+            {\r
+                *(rp++) = cpu_to_le32(RISC_NOOP);\r
+            }\r
+        }\r
+        \r
+\r
+        // Loop to (Nth)FrameRISC or to Start of Risc program & generate IRQ \r
+        *(rp++)  = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag);      \r
+        *(rp++)  = cpu_to_le32(risc_phys_jump_addr);            \r
+        *(rp++)  = cpu_to_le32(0);  \r
+\r
+        //Recalculate virtual address based on frame index \r
+        rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE/4 + (AUDIO_RISC_DMA_BUF_SIZE*(frame+1)/4 ) ;         \r
+    }\r
+    \r
+       return 0;\r
+}\r
+\r
+\r
+void cx25821_free_memory_audio(struct cx25821_dev *dev)\r
+{        \r
+       if (dev->_risc_virt_addr) \r
+    {\r
+               pci_free_consistent(dev->pci, dev->_audiorisc_size, dev->_risc_virt_addr, dev->_risc_phys_addr);\r
+               dev->_risc_virt_addr = NULL;\r
+       }\r
+    \r
+    if (dev->_audiodata_buf_virt_addr) \r
+    {\r
+               pci_free_consistent(dev->pci, dev->_audiodata_buf_size, dev->_audiodata_buf_virt_addr, dev->_audiodata_buf_phys_addr);\r
+               dev->_audiodata_buf_virt_addr = NULL;\r
+       }\r
+}\r
+\r
+void cx25821_stop_upstream_audio(struct cx25821_dev *dev)\r
+{    \r
+    struct sram_channel *sram_ch = &dev->sram_channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B];  \r
+    u32 tmp = 0;\r
+    \r
+    if( !dev->_audio_is_running )\r
+    {\r
+        printk("cx25821: No audio file is currently running so return!\n");\r
+        return;\r
+    }\r
+        \r
+    //Disable RISC interrupts\r
+    cx_write( sram_ch->int_msk, 0 );\r
+    \r
+    //Turn OFF risc and fifo enable in AUD_DMA_CNTRL\r
+    tmp = cx_read( sram_ch->dma_ctl );\r
+    cx_write( sram_ch->dma_ctl, tmp & ~(sram_ch->fld_aud_fifo_en | sram_ch->fld_aud_risc_en) ); \r
+\r
+    //Clear data buffer memory\r
+    if( dev->_audiodata_buf_virt_addr )\r
+        memset( dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size ); \r
+                \r
+    dev->_audio_is_running       = 0;\r
+    dev->_is_first_audio_frame   = 0;\r
+    dev->_audioframe_count       = 0;\r
+    dev->_audiofile_status       = END_OF_FILE;  \r
+    \r
+    if( dev->_irq_audio_queues )\r
+    {\r
+        kfree(dev->_irq_audio_queues); \r
+        dev->_irq_audio_queues = NULL; \r
+    }        \r
+    \r
+    if( dev->_audiofilename != NULL )\r
+        kfree(dev->_audiofilename);  \r
+}\r
+\r
+\r
+void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev)\r
+{\r
+    if( dev->_audio_is_running )\r
+    {\r
+        cx25821_stop_upstream_audio(dev);\r
+    }\r
+\r
+    cx25821_free_memory_audio(dev);\r
+}\r
+\r
+\r
+int cx25821_get_audio_data(struct cx25821_dev *dev, struct sram_channel *sram_ch )\r
+{\r
+    struct file * myfile;    \r
+    int frame_index_temp = dev->_audioframe_index;\r
+    int i = 0;\r
+    int line_size = AUDIO_LINE_SIZE;  \r
+    int frame_size = AUDIO_DATA_BUF_SZ;\r
+    int frame_offset = frame_size * frame_index_temp;           \r
+    ssize_t vfs_read_retval = 0;\r
+    char mybuf[line_size];      \r
+    loff_t file_offset = dev->_audioframe_count * frame_size; \r
+    loff_t pos;        \r
+    mm_segment_t old_fs;\r
+\r
+    \r
+    if( dev->_audiofile_status == END_OF_FILE )   \r
+        return 0;\r
+        \r
+    myfile = filp_open( dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0 );\r
+    \r
+    \r
+    if (IS_ERR(myfile)) \r
+    {\r
+        const int open_errno = -PTR_ERR(myfile);\r
+        printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_audiofilename, open_errno);\r
+        return PTR_ERR(myfile);\r
+    } \r
+    else \r
+    {   \r
+        if( !(myfile->f_op) )\r
+        {            \r
+            printk("%s: File has no file operations registered!\n", __func__);\r
+            filp_close(myfile, NULL);\r
+            return -EIO;\r
+        }\r
+        \r
+        \r
+        if( !myfile->f_op->read )       \r
+        {            \r
+            printk("%s: File has no READ operations registered! \n", __func__);\r
+            filp_close(myfile, NULL);\r
+            return -EIO;\r
+        }\r
+        \r
+        pos = myfile->f_pos;            \r
+        old_fs = get_fs();  \r
+        set_fs(KERNEL_DS);\r
+                \r
+              \r
+        for( i = 0; i < dev->_audio_lines_count; i++ )\r
+        {\r
+            pos = file_offset;    \r
+            \r
+            vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos);     \r
+            \r
+            \r
+            if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_audiodata_buf_virt_addr != NULL )   \r
+            {\r
+                memcpy( (void*)(dev->_audiodata_buf_virt_addr+frame_offset/4), mybuf, vfs_read_retval);      \r
+            }            \r
+            \r
+            file_offset += vfs_read_retval;\r
+            frame_offset += vfs_read_retval;\r
+\r
+            if( vfs_read_retval < line_size )\r
+            {      \r
+                printk(KERN_INFO "Done: exit %s() since no more bytes to read from Audio file.\n", __func__ );\r
+                break;\r
+            }      \r
+        }\r
+        \r
+        if( i > 0 )         \r
+            dev->_audioframe_count++;           \r
+\r
+        dev->_audiofile_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;      \r
+\r
+        \r
+        set_fs(old_fs);                 \r
+        filp_close(myfile, NULL);          \r
+    }\r
+    \r
+    return 0;\r
+}\r
+\r
+static void cx25821_audioups_handler(struct work_struct *work)\r
+{\r
+       struct cx25821_dev *dev = container_of(work, struct cx25821_dev, _audio_work_entry); \r
+       \r
+    if( !dev )\r
+    {\r
+        printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ );\r
+        return;\r
+    }\r
+  \r
+    cx25821_get_audio_data( dev, &dev->sram_channels[dev->_audio_upstream_channel_select] );\r
+}\r
+\r
+int cx25821_openfile_audio(struct cx25821_dev *dev, struct sram_channel *sram_ch)\r
+{\r
+    struct file * myfile;    \r
+    int i = 0, j = 0;\r
+    int line_size = AUDIO_LINE_SIZE;   \r
+    ssize_t vfs_read_retval = 0;\r
+    char mybuf[line_size];\r
+    loff_t pos;\r
+    loff_t offset = (unsigned long)0;\r
+    mm_segment_t old_fs;\r
+        \r
+\r
+    myfile = filp_open( dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0 );\r
+    \r
+    \r
+    if (IS_ERR(myfile)) \r
+    {\r
+        const int open_errno = -PTR_ERR(myfile);\r
+        printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_audiofilename, open_errno);\r
+        return PTR_ERR(myfile);\r
+    } \r
+    else \r
+    {\r
+        if( !(myfile->f_op) )\r
+        {            \r
+            printk("%s: File has no file operations registered! \n", __func__);\r
+            filp_close(myfile, NULL);\r
+            return -EIO;\r
+        }\r
+        \r
+        \r
+        if( !myfile->f_op->read )\r
+        {            \r
+            printk("%s: File has no READ operations registered! \n", __func__);\r
+            filp_close(myfile, NULL);\r
+            return -EIO;\r
+        }\r
+        \r
+        pos = myfile->f_pos;\r
+        old_fs = get_fs();  \r
+        set_fs(KERNEL_DS);\r
+                \r
+        \r
+        for( j = 0; j < NUM_AUDIO_FRAMES; j++ )       \r
+        {          \r
+            for( i = 0; i < dev->_audio_lines_count; i++ )\r
+            {\r
+                pos = offset;\r
+\r
+                vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos);                \r
+                \r
+                \r
+                if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_audiodata_buf_virt_addr != NULL )   \r
+                { \r
+                    memcpy( (void*)(dev->_audiodata_buf_virt_addr+offset/4), mybuf, vfs_read_retval);   \r
+                }                \r
+                \r
+                offset += vfs_read_retval;\r
+\r
+                if( vfs_read_retval < line_size )\r
+                {      \r
+                    printk(KERN_INFO "Done: exit %s() since no more bytes to read from Audio file.\n", __func__ );\r
+                    break;\r
+                }      \r
+            }\r
+            \r
+            if( i > 0 )     \r
+            {\r
+                dev->_audioframe_count++;\r
+            }            \r
+            \r
+            if( vfs_read_retval < line_size )\r
+            {\r
+                break;\r
+            }            \r
+        }\r
+        \r
+        dev->_audiofile_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;   \r
+            \r
+        set_fs(old_fs);        \r
+        myfile->f_pos = 0;\r
+        filp_close(myfile, NULL);         \r
+    }\r
+    \r
+    return 0;\r
+}\r
+\r
+static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev,\r
+                                                            struct sram_channel *sram_ch,\r
+                                                 int bpl)\r
+{\r
+       int ret = 0;\r
+       dma_addr_t dma_addr;\r
+       dma_addr_t data_dma_addr;       \r
+        \r
+\r
+    cx25821_free_memory_audio(dev);     \r
+    \r
+    dev->_risc_virt_addr       = pci_alloc_consistent(dev->pci, dev->audio_upstream_riscbuf_size, &dma_addr);\r
+    dev->_risc_virt_start_addr = dev->_risc_virt_addr;      \r
+    dev->_risc_phys_start_addr = dma_addr;        \r
+    dev->_risc_phys_addr       = dma_addr;\r
+    dev->_audiorisc_size       = dev->audio_upstream_riscbuf_size;\r
+       \r
+   \r
+    if (!dev->_risc_virt_addr)\r
+    {\r
+        printk("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning.\n");\r
+               return -ENOMEM;\r
+    }\r
+  \r
+    //Clear out memory at address\r
+    memset( dev->_risc_virt_addr, 0, dev->_audiorisc_size );\r
+\r
+    \r
+    //For Audio Data buffer allocation  \r
+    dev->_audiodata_buf_virt_addr = pci_alloc_consistent(dev->pci, dev->audio_upstream_databuf_size, &data_dma_addr);\r
+    dev->_audiodata_buf_phys_addr = data_dma_addr;\r
+    dev->_audiodata_buf_size      = dev->audio_upstream_databuf_size;\r
+       \r
+    if (!dev->_audiodata_buf_virt_addr)\r
+    {        \r
+        printk("cx25821 ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning. \n");\r
+               return -ENOMEM;\r
+    }\r
+  \r
+    //Clear out memory at address\r
+    memset( dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size );\r
+    \r
+   \r
+    ret = cx25821_openfile_audio(dev, sram_ch);     \r
+    if( ret < 0 )\r
+        return ret;\r
+                                      \r
+    \r
+    //Creating RISC programs\r
+    ret = cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl, dev->_audio_lines_count );                                \r
+       if (ret < 0)\r
+       {\r
+               printk(KERN_DEBUG "cx25821 ERROR creating audio upstream RISC programs! \n");\r
+               goto error;\r
+       }\r
+    \r
+       return 0;\r
+\r
+error:\r
+       return ret;\r
+}\r
+\r
+int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, u32 status)\r
+{\r
+       int i = 0;\r
+    u32 int_msk_tmp;\r
+    struct sram_channel *channel = &dev->sram_channels[chan_num];\r
+    dma_addr_t   risc_phys_jump_addr;\r
+    __le32 * rp;\r
+\r
+\r
+    if (status & FLD_AUD_SRC_RISCI1)      \r
+    {\r
+           //Get interrupt_index of the program that interrupted\r
+        u32 prog_cnt = cx_read( channel->gpcnt );\r
+    \r
+        //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers\r
+        cx_write(channel->int_msk, 0);  \r
+        cx_write(channel->int_stat, cx_read(channel->int_stat) );\r
+    \r
+               spin_lock(&dev->slock);     \r
+            \r
+             \r
+        while(prog_cnt != dev->_last_index_irq)\r
+        {            \r
+            //Update _last_index_irq\r
+            if(dev->_last_index_irq < (NUMBER_OF_PROGRAMS-1))\r
+            {\r
+                dev->_last_index_irq++;\r
+            }\r
+            else\r
+            {\r
+                dev->_last_index_irq = 0;\r
+            }\r
+\r
+            dev->_audioframe_index = dev->_last_index_irq;\r
+            \r
+            queue_work(dev->_irq_audio_queues, &dev->_audio_work_entry);        \r
+        }\r
+\r
+    \r
+        if ( dev->_is_first_audio_frame )\r
+        {\r
+            dev->_is_first_audio_frame = 0;           \r
+            \r
+            if( dev->_risc_virt_start_addr != NULL )\r
+            {\r
+                risc_phys_jump_addr = dev->_risc_phys_start_addr + RISC_SYNC_INSTRUCTION_SIZE + AUDIO_RISC_DMA_BUF_SIZE;        \r
+                \r
+                rp = cx25821_risc_field_upstream_audio(dev, dev->_risc_virt_start_addr+1, dev->_audiodata_buf_phys_addr, AUDIO_LINE_SIZE, FIFO_DISABLE);      \r
+\r
+                if( USE_RISC_NOOP_AUDIO )\r
+                {\r
+                    for( i = 0; i < NUM_NO_OPS; i++ )\r
+                    {\r
+                        *(rp++) = cpu_to_le32(RISC_NOOP);\r
+                    }\r
+                }\r
+        \r
+                // Jump to 2nd Audio Frame\r
+                *(rp++)  = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_RESET);      \r
+                *(rp++)  = cpu_to_le32(risc_phys_jump_addr);            \r
+                *(rp++)  = cpu_to_le32(0); \r
+            }\r
+        }\r
+        \r
+               spin_unlock(&dev->slock);      \r
+       }\r
+    else\r
+    {\r
+        if(status & FLD_AUD_SRC_OF)\r
+            printk("%s: Audio Received Overflow Error Interrupt!\n", __func__);\r
+\r
+        if(status & FLD_AUD_SRC_SYNC)\r
+            printk("%s: Audio Received Sync Error Interrupt!\n", __func__);\r
+\r
+        if(status & FLD_AUD_SRC_OPC_ERR)\r
+            printk("%s: Audio Received OpCode Error Interrupt!\n", __func__);    \r
+            \r
+        // Read and write back the interrupt status register to clear our bits\r
+        cx_write(channel->int_stat, cx_read(channel->int_stat) );   \r
+    }\r
+     \r
+        \r
+    if( dev->_audiofile_status == END_OF_FILE )\r
+    {                       \r
+        printk("cx25821: EOF Channel Audio Framecount = %d\n", dev->_audioframe_count );\r
+        return -1;\r
+    }\r
+    \r
+    //ElSE, set the interrupt mask register, re-enable irq. \r
+    int_msk_tmp = cx_read( channel->int_msk );              \r
+    cx_write( channel->int_msk, int_msk_tmp |= _intr_msk ); \r
+               \r
+    return 0;\r
+}\r
+\r
+static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id)\r
+{\r
+       struct cx25821_dev *dev = dev_id;\r
+       u32 msk_stat, audio_status;\r
+       int handled = 0;    \r
+    struct sram_channel *sram_ch;\r
+    \r
+    \r
+    if( !dev )\r
+        return -1;\r
+        \r
+\r
+    sram_ch = &dev->sram_channels[dev->_audio_upstream_channel_select];     \r
+\r
+    msk_stat   = cx_read(sram_ch->int_mstat);     \r
+    audio_status = cx_read(sram_ch->int_stat); \r
+    \r
+    // Only deal with our interrupt\r
+    if(audio_status)\r
+    {\r
+        handled = cx25821_audio_upstream_irq(dev, dev->_audio_upstream_channel_select, audio_status);\r
+    }\r
+    \r
+    \r
+    if( handled < 0 )\r
+    {    \r
+        cx25821_stop_upstream_audio(dev);\r
+    }\r
+    else\r
+    {\r
+        handled += handled;    \r
+    }   \r
+\r
+       return IRQ_RETVAL(handled);\r
+}\r
+\r
+\r
+static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, struct sram_channel *sram_ch)\r
+{\r
+    int count = 0;\r
+       u32 tmp;\r
+    \r
+    do\r
+    {\r
+        //Wait 10 microsecond before checking to see if the FIFO is turned ON.\r
+        udelay(10);\r
+\r
+        tmp = cx_read( sram_ch->dma_ctl );\r
+        \r
+        if(count++ > 1000) //10 millisecond timeout         \r
+        {\r
+            printk("cx25821 ERROR: %s() fifo is NOT turned on. Timeout!\n", __func__);\r
+            return;\r
+        }\r
+        \r
+    } while( !(tmp & sram_ch->fld_aud_fifo_en) );\r
+            \r
+}\r
+\r
+\r
+int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,\r
+                                                    struct sram_channel *sram_ch)\r
+{\r
+    u32 tmp = 0;\r
+    int err = 0;\r
+    \r
+    \r
+    // Set the physical start address of the RISC program in the initial program counter(IPC) member of the CMDS.\r
+    cx_write(sram_ch->cmds_start + 0, dev->_risc_phys_addr);\r
+    cx_write(sram_ch->cmds_start +  4, 0); /* Risc IPC High 64 bits 63-32 */\r
+\r
+    \r
+       /* reset counter */\r
+       cx_write(sram_ch->gpcnt_ctl, 3); \r
+    \r
+    //Set the line length      (It looks like we do not need to set the line length)\r
+       cx_write(sram_ch->aud_length, AUDIO_LINE_SIZE & FLD_AUD_DST_LN_LNGTH); \r
+\r
+    //Set the input mode to 16-bit\r
+    tmp = cx_read( sram_ch->aud_cfg );\r
+       tmp |= FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE | FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | FLD_AUD_SONY_MODE;\r
+    cx_write( sram_ch->aud_cfg, tmp );\r
+    \r
+    // Read and write back the interrupt status register to clear it\r
+    tmp = cx_read( sram_ch->int_stat);\r
+    cx_write( sram_ch->int_stat, tmp);\r
+\r
+    // Clear our bits from the interrupt status register.  \r
+    cx_write( sram_ch->int_stat, _intr_msk );       \r
+\r
+    \r
+    //Set the interrupt mask register, enable irq.  \r
+    cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));\r
+    tmp = cx_read( sram_ch->int_msk );\r
+    cx_write( sram_ch->int_msk, tmp |= _intr_msk );    \r
+    \r
+    \r
+    err = request_irq(dev->pci->irq, cx25821_upstream_irq_audio, IRQF_SHARED | IRQF_DISABLED, dev->name, dev);\r
+       if (err < 0) \r
+       {\r
+               printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq);\r
+               goto fail_irq;\r
+       } \r
+    \r
+    \r
+    // Start the DMA  engine\r
+    tmp = cx_read( sram_ch->dma_ctl );\r
+    cx_set( sram_ch->dma_ctl, tmp | sram_ch->fld_aud_risc_en );  \r
+\r
+    dev->_audio_is_running = 1; \r
+    dev->_is_first_audio_frame = 1;          \r
+    \r
+    // The fifo_en bit turns on by the first Risc program\r
+    cx25821_wait_fifo_enable(dev, sram_ch);          \r
+\r
+       return 0;\r
+    \r
+\r
+fail_irq:\r
+       cx25821_dev_unregister(dev);  \r
+    return err;\r
+}\r
+\r
+\r
+int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)\r
+{\r
+    struct sram_channel *sram_ch; \r
+    int retval = 0;\r
+    int err = 0;    \r
+    int str_length = 0;\r
+    \r
+    if( dev->_audio_is_running )\r
+    {\r
+        printk("Audio Channel is still running so return!\n");\r
+        return 0;\r
+    }\r
+        \r
+    dev->_audio_upstream_channel_select = channel_select;      \r
+    sram_ch = &dev->sram_channels[channel_select];   \r
+    \r
+    //Work queue\r
+       INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler);\r
+       dev->_irq_audio_queues = create_singlethread_workqueue("cx25821_audioworkqueue");   \r
+\r
+       if(!dev->_irq_audio_queues)\r
+    {\r
+        printk("cx25821 ERROR: create_singlethread_workqueue() for Audio FAILED!\n");\r
+               return -ENOMEM;\r
+    }\r
+         \r
+    \r
+    dev->_last_index_irq     = 0;        \r
+    dev->_audio_is_running   = 0;    \r
+    dev->_audioframe_count   = 0;\r
+    dev->_audiofile_status   = RESET_STATUS;  \r
+    dev->_audio_lines_count  = LINES_PER_AUDIO_BUFFER; \r
+    _line_size          = AUDIO_LINE_SIZE; \r
+\r
+        \r
+    if( dev->input_audiofilename )\r
+    {\r
+        str_length = strlen(dev->input_audiofilename);\r
+        dev->_audiofilename = (char *) kmalloc(str_length + 1, GFP_KERNEL);        \r
+        \r
+        if( !dev->_audiofilename )\r
+            goto error;\r
+            \r
+        memcpy(dev->_audiofilename, dev->input_audiofilename, str_length + 1);  \r
+\r
+        //Default if filename is empty string\r
+        if( strcmp(dev->input_audiofilename,"") == 0)        \r
+        {\r
+            dev->_audiofilename = "/root/audioGOOD.wav";    \r
+        }         \r
+    }\r
+    else\r
+    {\r
+        str_length = strlen(_defaultAudioName);       \r
+        dev->_audiofilename = (char *) kmalloc(str_length + 1, GFP_KERNEL);        \r
+        \r
+        if( !dev->_audiofilename )\r
+            goto error;\r
+            \r
+        memcpy(dev->_audiofilename, _defaultAudioName, str_length + 1);\r
+    }  \r
+     \r
+    \r
+    retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch, _line_size, 0);      \r
+\r
+    dev->audio_upstream_riscbuf_size = AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS + RISC_SYNC_INSTRUCTION_SIZE;      \r
+    dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS;       \r
+\r
+     \r
+    //Allocating buffers and prepare RISC program\r
+    retval = cx25821_audio_upstream_buffer_prepare(dev, sram_ch, _line_size);\r
+       if (retval < 0) \r
+       {\r
+               printk(KERN_ERR "%s: Failed to set up Audio upstream buffers!\n", dev->name);\r
+               goto error;\r
+       }\r
+    \r
+    //Start RISC engine \r
+    cx25821_start_audio_dma_upstream(dev, sram_ch);                                     \r
+    \r
+    return 0;\r
+    \r
+error:\r
+       cx25821_dev_unregister(dev);\r
+    \r
+    return err;\r
+}\r
+       
diff --git a/drivers/staging/cx25821/cx25821-audio-upstream.h b/drivers/staging/cx25821/cx25821-audio-upstream.h
new file mode 100644 (file)
index 0000000..7bb136b
--- /dev/null
@@ -0,0 +1,62 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.com>\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+#include <linux/mutex.h>\r
+#include <linux/workqueue.h>\r
+\r
+\r
+#define NUM_AUDIO_PROGS       8\r
+#define NUM_AUDIO_FRAMES      8\r
+#define END_OF_FILE           0\r
+#define IN_PROGRESS           1\r
+#define RESET_STATUS          -1\r
+#define FIFO_DISABLE          0\r
+#define FIFO_ENABLE           1\r
+#define NUM_NO_OPS            4\r
+\r
+\r
+#define RISC_READ_INSTRUCTION_SIZE      12\r
+#define RISC_JUMP_INSTRUCTION_SIZE      12\r
+#define RISC_WRITECR_INSTRUCTION_SIZE   16\r
+#define RISC_SYNC_INSTRUCTION_SIZE      4\r
+#define DWORD_SIZE                      4\r
+#define AUDIO_SYNC_LINE                 4\r
+\r
+\r
+#define LINES_PER_AUDIO_BUFFER      15\r
+#define AUDIO_LINE_SIZE             128\r
+#define AUDIO_DATA_BUF_SZ           (AUDIO_LINE_SIZE * LINES_PER_AUDIO_BUFFER)\r
+\r
+#define USE_RISC_NOOP_AUDIO   1\r
+\r
+#ifdef USE_RISC_NOOP_AUDIO                \r
+#define AUDIO_RISC_DMA_BUF_SIZE    ( LINES_PER_AUDIO_BUFFER*RISC_READ_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE + RISC_JUMP_INSTRUCTION_SIZE)\r
+#endif\r
+\r
+\r
+#ifndef USE_RISC_NOOP_AUDIO\r
+#define AUDIO_RISC_DMA_BUF_SIZE    ( LINES_PER_AUDIO_BUFFER*RISC_READ_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + RISC_JUMP_INSTRUCTION_SIZE)\r
+#endif\r
+\r
+static int _line_size;        \r
+char * _defaultAudioName = "/root/audioGOOD.wav";   \r
+    \r
diff --git a/drivers/staging/cx25821/cx25821-audio.h b/drivers/staging/cx25821/cx25821-audio.h
new file mode 100644 (file)
index 0000000..1e13518
--- /dev/null
@@ -0,0 +1,60 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+#ifndef __CX25821_AUDIO_H__\r
+#define __CX25821_AUDIO_H__\r
+\r
+\r
+#define USE_RISC_NOOP               1\r
+#define LINES_PER_BUFFER            15\r
+#define AUDIO_LINE_SIZE             128\r
+\r
+//Number of buffer programs to use at once.\r
+#define NUMBER_OF_PROGRAMS  8\r
+\r
+//Max size of the RISC program for a buffer. - worst case is 2 writes per line\r
+// Space is also added for the 4 no-op instructions added on the end.\r
+\r
+#ifndef USE_RISC_NOOP\r
+#define MAX_BUFFER_PROGRAM_SIZE     \\r
+    (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE*4)\r
+#endif\r
+\r
+// MAE 12 July 2005 Try to use NOOP RISC instruction instead\r
+#ifdef USE_RISC_NOOP\r
+#define MAX_BUFFER_PROGRAM_SIZE     \\r
+    (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_NOOP_INSTRUCTION_SIZE*4)\r
+#endif\r
+\r
+\r
+//Sizes of various instructions in bytes.  Used when adding instructions.\r
+#define RISC_WRITE_INSTRUCTION_SIZE 12\r
+#define RISC_JUMP_INSTRUCTION_SIZE  12\r
+#define RISC_SKIP_INSTRUCTION_SIZE  4\r
+#define RISC_SYNC_INSTRUCTION_SIZE  4\r
+#define RISC_WRITECR_INSTRUCTION_SIZE  16\r
+#define RISC_NOOP_INSTRUCTION_SIZE 4\r
+\r
+#define MAX_AUDIO_DMA_BUFFER_SIZE (MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + RISC_SYNC_INSTRUCTION_SIZE)\r
+\r
+#endif\r
+\r
diff --git a/drivers/staging/cx25821/cx25821-audups11.c b/drivers/staging/cx25821/cx25821-audups11.c
new file mode 100644 (file)
index 0000000..a8e4dce
--- /dev/null
@@ -0,0 +1,441 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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 "cx25821-video.h"
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+    struct cx25821_buffer   *buf = container_of(vb, struct cx25821_buffer, vb);
+    struct cx25821_buffer   *prev;
+    struct cx25821_fh       *fh   = vq->priv_data;
+    struct cx25821_dev      *dev  = fh->dev;
+    struct cx25821_dmaqueue *q    = &dev->vidq[SRAM_CH11];
+
+    /* add jump to stopper */
+    buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+    buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+    buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+    dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+    if (!list_empty(&q->queued)) {
+        list_add_tail(&buf->vb.queue, &q->queued);
+        buf->vb.state = VIDEOBUF_QUEUED;
+        dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i);
+
+    } else if (list_empty(&q->active)) {
+        list_add_tail(&buf->vb.queue, &q->active);
+        cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH11]);
+        buf->vb.state = VIDEOBUF_ACTIVE;
+        buf->count    = q->count++;
+        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+        dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+                                buf, buf->vb. i, buf->count, q->count);
+    } else {
+        prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+        if (prev->vb.width  == buf->vb.width  &&
+            prev->vb.height == buf->vb.height &&
+            prev->fmt       == buf->fmt) {
+            list_add_tail(&buf->vb.queue, &q->active);
+            buf->vb.state = VIDEOBUF_ACTIVE;
+            buf->count    = q->count++;
+            prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+            /* 64 bit bits 63-32 */
+            prev->risc.jmp[2] = cpu_to_le32(0);
+            dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",  buf, buf->vb.i, buf->count);
+
+        } else {
+            list_add_tail(&buf->vb.queue, &q->queued);
+            buf->vb.state = VIDEOBUF_QUEUED;
+            dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i);
+        }
+    }
+
+    if (list_empty(&q->active))
+    {
+       dprintk(2, "active queue empty!\n");
+    }
+}
+
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+    .buf_setup    = buffer_setup,
+    .buf_prepare  = buffer_prepare,
+    .buf_queue    = buffer_queue,
+    .buf_release  = buffer_release,
+};
+
+
+static int video_open(struct file *file)
+{
+    int minor = video_devdata(file)->minor;
+    struct cx25821_dev *h, *dev = NULL;
+    struct cx25821_fh *fh;
+    struct list_head *list;
+    enum v4l2_buf_type type = 0;
+
+    lock_kernel();
+    list_for_each(list, &cx25821_devlist)
+    {
+        h = list_entry(list, struct cx25821_dev, devlist);
+
+        if (h->video_dev[SRAM_CH11] && h->video_dev[SRAM_CH11]->minor == minor)
+        {
+            dev  = h;
+            type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        }
+    }
+
+    if (NULL == dev) {
+        unlock_kernel();
+        return -ENODEV;
+    }
+
+    printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+    /* allocate + initialize per filehandle data */
+    fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+    if (NULL == fh) {
+        unlock_kernel();
+        return -ENOMEM;
+    }
+
+    file->private_data = fh;
+    fh->dev      = dev;
+    fh->type     = type;
+    fh->width    = 720;
+
+    if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+        fh->height = 576;
+    else
+        fh->height = 480;
+        
+    dev->channel_opened = 10;
+    fh->fmt             = format_by_fourcc(V4L2_PIX_FMT_YUYV);
+
+    v4l2_prio_open(&dev->prio,&fh->prio);
+
+    videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+                &dev->pci->dev, &dev->slock,
+                V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                V4L2_FIELD_INTERLACED,
+                sizeof(struct cx25821_buffer),
+                fh);
+
+    dprintk(1, "post videobuf_queue_init()\n");
+    unlock_kernel();
+
+    return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+    struct cx25821_fh *fh = file->private_data;
+
+    switch (fh->type)
+    {
+        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+            if (res_locked(fh->dev, RESOURCE_VIDEO11))
+                return -EBUSY;
+
+            return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK);
+
+        default:
+            BUG();
+            return 0;
+    }
+}
+
+static unsigned int video_poll(struct file *file, struct poll_table_struct *wait)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_buffer *buf;
+
+    if (res_check(fh, RESOURCE_VIDEO11)) {
+        /* streaming capture */
+        if (list_empty(&fh->vidq.stream))
+            return POLLERR;
+        buf = list_entry(fh->vidq.stream.next,
+            struct cx25821_buffer, vb.stream);
+    } else {
+        /* read() capture */
+        buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+        if (NULL == buf)
+            return POLLERR;
+    }
+
+    poll_wait(file, &buf->vb.done, wait);
+    if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)
+        return POLLIN|POLLRDNORM;
+    return 0;
+}
+
+
+static int video_release(struct file *file)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev;
+
+    //stop the risc engine and fifo
+    //cx_write(channel11->dma_ctl, 0); 
+
+    /* stop video capture */
+    if (res_check(fh, RESOURCE_VIDEO11)) {
+        videobuf_queue_cancel(&fh->vidq);
+        res_free(dev, fh, RESOURCE_VIDEO11);
+    }
+
+    if (fh->vidq.read_buf) {
+        buffer_release(&fh->vidq, fh->vidq.read_buf);
+        kfree(fh->vidq.read_buf);
+    }
+
+    videobuf_mmap_free(&fh->vidq);
+
+    v4l2_prio_close(&dev->prio,&fh->prio);
+
+    file->private_data = NULL;
+    kfree(fh);
+
+    return 0;
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+
+    if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(i != fh->type))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO11))))
+    {
+        return -EBUSY;
+    }
+
+    return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+    int err, res;
+
+    if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+        return -EINVAL;
+    if (i != fh->type)
+        return -EINVAL;
+
+    res = get_resource(fh, RESOURCE_VIDEO11);
+    err = videobuf_streamoff(get_queue(fh));
+    if (err < 0)
+        return err;
+    res_free(dev, fh, res);
+    return 0;
+}
+
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    int err;
+
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    dprintk(2, "%s()\n", __func__);
+    err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+    if (0 != err)
+        return err;
+    fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+    fh->width      = f->fmt.pix.width;
+    fh->height     = f->fmt.pix.height;
+    fh->vidq.field = f->fmt.pix.field;
+    dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field);
+    cx25821_call_all(dev, video, s_fmt, f);
+    return 0;
+}
+
+static long video_ioctl_upstream11(struct file *file, unsigned int cmd, unsigned long arg)   
+{   
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev;
+    int command = 0;
+    struct upstream_user_struct *data_from_user;
+
+    
+    data_from_user = (struct upstream_user_struct *)arg;
+    
+    if( !data_from_user )
+    {
+        printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__);
+        return 0;
+    }
+    
+    command = data_from_user->command;
+    
+    if( command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO )
+    {
+        return 0;
+    }
+        
+        
+    dev->input_filename      = data_from_user->input_filename;
+    dev->input_audiofilename = data_from_user->input_filename;
+    dev->vid_stdname         = data_from_user->vid_stdname;
+    dev->pixel_format        = data_from_user->pixel_format;
+    dev->channel_select      = data_from_user->channel_select;
+    dev->command             = data_from_user->command;
+
+   
+    switch(command)
+    {           
+        case UPSTREAM_START_AUDIO:
+            cx25821_start_upstream_audio(dev, data_from_user);
+            break;
+
+        case UPSTREAM_STOP_AUDIO:
+            cx25821_stop_upstream_audio(dev);
+            break;            
+    }
+       
+    return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+    struct cx25821_fh *fh = priv;
+    return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_log_status (struct file *file, void *priv)
+{
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    char name[32 + 2];
+
+    snprintf(name, sizeof(name), "%s/2", dev->name);
+    printk(KERN_INFO "%s/2: ============  START LOG STATUS  ============\n",
+              dev->name);
+    cx25821_call_all(dev, core, log_status);
+    printk(KERN_INFO "%s/2: =============  END LOG STATUS  =============\n",
+              dev->name);
+    return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+    int err;
+
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+    return 0;
+}
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+    .owner         = THIS_MODULE,
+    .open          = video_open,
+    .release       = video_release,
+    .read          = video_read,
+    .poll          = video_poll,
+    .mmap          = video_mmap,
+    .ioctl         = video_ioctl_upstream11,  
+};
+
+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_reqbufs       = vidioc_reqbufs,
+    .vidioc_querybuf      = vidioc_querybuf,
+    .vidioc_qbuf          = vidioc_qbuf,
+    .vidioc_dqbuf         = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+    .vidioc_s_std         = vidioc_s_std,
+    .vidioc_querystd      = vidioc_querystd,
+#endif
+    .vidioc_cropcap       = vidioc_cropcap,
+    .vidioc_s_crop        = vidioc_s_crop,
+    .vidioc_g_crop        = vidioc_g_crop,
+    .vidioc_enum_input    = vidioc_enum_input,
+    .vidioc_g_input       = vidioc_g_input,
+    .vidioc_s_input       = vidioc_s_input,
+    .vidioc_g_ctrl        = vidioc_g_ctrl,
+    .vidioc_s_ctrl        = vidioc_s_ctrl,
+    .vidioc_queryctrl    = vidioc_queryctrl,
+    .vidioc_streamon      = vidioc_streamon,
+    .vidioc_streamoff     = vidioc_streamoff,
+    .vidioc_log_status    = vidioc_log_status,
+    .vidioc_g_priority   = vidioc_g_priority,
+    .vidioc_s_priority   = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+    .vidiocgmbuf          = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+    .vidioc_g_tuner       = vidioc_g_tuner,
+    .vidioc_s_tuner       = vidioc_s_tuner,
+    .vidioc_g_frequency   = vidioc_g_frequency,
+    .vidioc_s_frequency   = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+    .vidioc_g_register    = vidioc_g_register,
+    .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template11 = {
+    .name                 = "cx25821-audioupstream",
+    .fops                 = &video_fops,
+    .minor                = -1,
+    .ioctl_ops            = &video_ioctl_ops,
+    .tvnorms              = CX25821_NORMS,
+    .current_norm         = V4L2_STD_NTSC_M,
+};
+
+
+
diff --git a/drivers/staging/cx25821/cx25821-biffuncs.h b/drivers/staging/cx25821/cx25821-biffuncs.h
new file mode 100644 (file)
index 0000000..a5c0535
--- /dev/null
@@ -0,0 +1,45 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+#ifndef _BITFUNCS_H\r
+#define _BITFUNCS_H\r
+\r
+#define SetBit(Bit)  (1 << Bit)\r
+\r
+inline u8 getBit(u32 sample, u8 index)\r
+{ \r
+    return (u8) ((sample >> index) & 1);\r
+}\r
+\r
+inline u32 clearBitAtPos(u32 value, u8 bit)\r
+{\r
+       return value & ~(1 << bit);\r
+}\r
+\r
+inline u32 setBitAtPos(u32 sample, u8 bit)\r
+{\r
+       sample |= (1 << bit);\r
+    return sample;\r
+\r
+}\r
+\r
+#endif
diff --git a/drivers/staging/cx25821/cx25821-cards.c b/drivers/staging/cx25821/cx25821-cards.c
new file mode 100644 (file)
index 0000000..eaaa567
--- /dev/null
@@ -0,0 +1,72 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>\r
+ *     Based on Steven Toth <stoth@linuxtv.org> cx23885 driver\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <media/cx25840.h>
+
+#include "cx25821.h"
+#include "tuner-xc2028.h"
+
+// board config info                                                  
+
+struct cx25821_board cx25821_boards[] = {
+       [UNKNOWN_BOARD] = {
+               .name           = "UNKNOWN/GENERIC",
+               // Ensure safe default for unknown boards 
+               .clk_freq       = 0,
+       },
+
+       [CX25821_BOARD] = {
+               .name               = "CX25821",
+               .portb              = CX25821_RAW,
+               .portc              = CX25821_264,\r
+        .input[0].type  = CX25821_VMUX_COMPOSITE,
+       },      
+
+};
+
+const unsigned int cx25821_bcount = ARRAY_SIZE(cx25821_boards);
+
+struct cx25821_subid cx25821_subids[]={
+    {
+               .subvendor = 0x14f1,
+               .subdevice = 0x0920,
+               .card      = CX25821_BOARD,
+    },
+};
+
+
+void cx25821_card_setup(struct cx25821_dev *dev)
+{
+       static u8 eeprom[256];
+
+       if (dev->i2c_bus[0].i2c_rc == 0) 
+       {
+               dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
+               tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom));
+       }
+}
+
diff --git a/drivers/staging/cx25821/cx25821-core.c b/drivers/staging/cx25821/cx25821-core.c
new file mode 100644 (file)
index 0000000..adca7af
--- /dev/null
@@ -0,0 +1,1565 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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/i2c.h>
+#include "cx25821.h"
+#include "cx25821-sram.h"
+#include "cx25821-video.h"
+
+MODULE_DESCRIPTION("Driver for Athena cards");
+MODULE_AUTHOR("Shu Lin - Hiep Huynh");
+MODULE_LICENSE("GPL");
+
+struct list_head cx25821_devlist;
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+static unsigned int card[]  = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+module_param_array(card,  int, NULL, 0444);
+MODULE_PARM_DESC(card, "card type");
+
+
+static unsigned int cx25821_devcount = 0;
+
+static DEFINE_MUTEX(devlist);
+LIST_HEAD(cx25821_devlist);
+
+
+struct sram_channel cx25821_sram_channels[] = {
+    [SRAM_CH00] = {
+        .i          = SRAM_CH00,
+        .name       = "VID A",
+        .cmds_start = VID_A_DOWN_CMDS,
+        .ctrl_start = VID_A_IQ,
+        .cdt        = VID_A_CDT,
+        .fifo_start = VID_A_DOWN_CLUSTER_1, 
+        .fifo_size  = (VID_CLUSTER_SIZE<<2), 
+        .ptr1_reg   = DMA1_PTR1,
+        .ptr2_reg   = DMA1_PTR2,
+        .cnt1_reg   = DMA1_CNT1,
+        .cnt2_reg   = DMA1_CNT2,
+        .int_msk    = VID_A_INT_MSK,
+        .int_stat   = VID_A_INT_STAT,
+        .int_mstat  = VID_A_INT_MSTAT,
+        .dma_ctl    = VID_DST_A_DMA_CTL,
+        .gpcnt_ctl  = VID_DST_A_GPCNT_CTL,
+        .gpcnt      = VID_DST_A_GPCNT,
+        .vip_ctl    = VID_DST_A_VIP_CTL,
+        .pix_frmt   = VID_DST_A_PIX_FRMT,   
+    },
+
+    [SRAM_CH01] = {
+        .i          = SRAM_CH01,
+        .name       = "VID B",
+        .cmds_start = VID_B_DOWN_CMDS,
+        .ctrl_start = VID_B_IQ, 
+        .cdt        = VID_B_CDT, 
+        .fifo_start = VID_B_DOWN_CLUSTER_1, 
+        .fifo_size  = (VID_CLUSTER_SIZE<<2), 
+        .ptr1_reg   = DMA2_PTR1,
+        .ptr2_reg   = DMA2_PTR2,
+        .cnt1_reg   = DMA2_CNT1,
+        .cnt2_reg   = DMA2_CNT2,
+                .int_msk    = VID_B_INT_MSK,
+        .int_stat   = VID_B_INT_STAT,
+        .int_mstat  = VID_B_INT_MSTAT,
+        .dma_ctl    = VID_DST_B_DMA_CTL,
+        .gpcnt_ctl  = VID_DST_B_GPCNT_CTL,
+        .gpcnt      = VID_DST_B_GPCNT,
+        .vip_ctl    = VID_DST_B_VIP_CTL,
+        .pix_frmt   = VID_DST_B_PIX_FRMT,
+    },
+    
+    [SRAM_CH02] = {
+        .i              = SRAM_CH02,
+        .name           = "VID C",
+        .cmds_start     = VID_C_DOWN_CMDS,
+        .ctrl_start     = VID_C_IQ,
+        .cdt            = VID_C_CDT,
+        .fifo_start     = VID_C_DOWN_CLUSTER_1,
+        .fifo_size      = (VID_CLUSTER_SIZE<<2),  
+        .ptr1_reg       = DMA3_PTR1,
+        .ptr2_reg       = DMA3_PTR2,
+        .cnt1_reg       = DMA3_CNT1,
+        .cnt2_reg       = DMA3_CNT2,
+        .int_msk        = VID_C_INT_MSK,
+        .int_stat       = VID_C_INT_STAT,
+        .int_mstat      = VID_C_INT_MSTAT,
+        .dma_ctl        = VID_DST_C_DMA_CTL,
+        .gpcnt_ctl      = VID_DST_C_GPCNT_CTL,
+        .gpcnt          = VID_DST_C_GPCNT,
+        .vip_ctl        = VID_DST_C_VIP_CTL,
+        .pix_frmt       = VID_DST_C_PIX_FRMT,
+    },
+    
+    [SRAM_CH03] = {
+        .i              = SRAM_CH03,
+        .name           = "VID D",
+        .cmds_start     = VID_D_DOWN_CMDS,
+        .ctrl_start     = VID_D_IQ,
+        .cdt            = VID_D_CDT,
+        .fifo_start     = VID_D_DOWN_CLUSTER_1,
+        .fifo_size      = (VID_CLUSTER_SIZE<<2), 
+        .ptr1_reg       = DMA4_PTR1,
+        .ptr2_reg       = DMA4_PTR2,
+        .cnt1_reg       = DMA4_CNT1,
+        .cnt2_reg       = DMA4_CNT2,
+        .int_msk        = VID_D_INT_MSK,
+        .int_stat       = VID_D_INT_STAT,
+        .int_mstat      = VID_D_INT_MSTAT,
+        .dma_ctl        = VID_DST_D_DMA_CTL,
+        .gpcnt_ctl      = VID_DST_D_GPCNT_CTL,
+        .gpcnt          = VID_DST_D_GPCNT,
+        .vip_ctl        = VID_DST_D_VIP_CTL,
+        .pix_frmt       = VID_DST_D_PIX_FRMT,
+    },
+    
+    [SRAM_CH04] = {
+        .i              = SRAM_CH04,
+        .name           = "VID E",
+        .cmds_start     = VID_E_DOWN_CMDS,
+        .ctrl_start     = VID_E_IQ,
+        .cdt            = VID_E_CDT,
+        .fifo_start     = VID_E_DOWN_CLUSTER_1,
+        .fifo_size      = (VID_CLUSTER_SIZE<<2), 
+        .ptr1_reg       = DMA5_PTR1,
+        .ptr2_reg       = DMA5_PTR2,
+        .cnt1_reg       = DMA5_CNT1,
+        .cnt2_reg       = DMA5_CNT2,
+        .int_msk        = VID_E_INT_MSK,
+        .int_stat       = VID_E_INT_STAT,
+        .int_mstat      = VID_E_INT_MSTAT,
+        .dma_ctl        = VID_DST_E_DMA_CTL,
+        .gpcnt_ctl      = VID_DST_E_GPCNT_CTL,
+        .gpcnt          = VID_DST_E_GPCNT,
+        .vip_ctl        = VID_DST_E_VIP_CTL,
+        .pix_frmt       = VID_DST_E_PIX_FRMT,
+    },
+    
+    [SRAM_CH05] = {
+        .i              = SRAM_CH05,
+        .name           = "VID F",
+        .cmds_start     = VID_F_DOWN_CMDS,
+        .ctrl_start     = VID_F_IQ,
+        .cdt            = VID_F_CDT,
+        .fifo_start     = VID_F_DOWN_CLUSTER_1,
+        .fifo_size      = (VID_CLUSTER_SIZE<<2), 
+        .ptr1_reg       = DMA6_PTR1,
+        .ptr2_reg       = DMA6_PTR2,
+        .cnt1_reg       = DMA6_CNT1,
+        .cnt2_reg       = DMA6_CNT2,
+        .int_msk        = VID_F_INT_MSK,
+        .int_stat       = VID_F_INT_STAT,
+        .int_mstat      = VID_F_INT_MSTAT,
+        .dma_ctl        = VID_DST_F_DMA_CTL,
+        .gpcnt_ctl      = VID_DST_F_GPCNT_CTL,
+        .gpcnt          = VID_DST_F_GPCNT,
+        .vip_ctl        = VID_DST_F_VIP_CTL,
+        .pix_frmt       = VID_DST_F_PIX_FRMT,
+    },
+    
+    [SRAM_CH06] = {
+        .i              = SRAM_CH06,
+        .name           = "VID G",
+        .cmds_start     = VID_G_DOWN_CMDS,
+        .ctrl_start     = VID_G_IQ,
+        .cdt            = VID_G_CDT,
+        .fifo_start     = VID_G_DOWN_CLUSTER_1,
+        .fifo_size      = (VID_CLUSTER_SIZE<<2), 
+        .ptr1_reg       = DMA7_PTR1,
+        .ptr2_reg       = DMA7_PTR2,
+        .cnt1_reg       = DMA7_CNT1,
+        .cnt2_reg       = DMA7_CNT2,
+        .int_msk        = VID_G_INT_MSK,
+        .int_stat       = VID_G_INT_STAT,
+        .int_mstat      = VID_G_INT_MSTAT,
+        .dma_ctl        = VID_DST_G_DMA_CTL,
+        .gpcnt_ctl      = VID_DST_G_GPCNT_CTL,
+        .gpcnt          = VID_DST_G_GPCNT,
+        .vip_ctl        = VID_DST_G_VIP_CTL,
+        .pix_frmt       = VID_DST_G_PIX_FRMT,
+    },
+    
+    [SRAM_CH07] = {
+        .i              = SRAM_CH07,
+        .name           = "VID H",
+        .cmds_start     = VID_H_DOWN_CMDS,
+        .ctrl_start     = VID_H_IQ,
+        .cdt            = VID_H_CDT,
+        .fifo_start     = VID_H_DOWN_CLUSTER_1,
+        .fifo_size      = (VID_CLUSTER_SIZE<<2), 
+        .ptr1_reg       = DMA8_PTR1,
+        .ptr2_reg       = DMA8_PTR2,
+        .cnt1_reg       = DMA8_CNT1,
+        .cnt2_reg       = DMA8_CNT2,
+        .int_msk        = VID_H_INT_MSK,
+        .int_stat       = VID_H_INT_STAT,
+        .int_mstat      = VID_H_INT_MSTAT,
+        .dma_ctl        = VID_DST_H_DMA_CTL,
+        .gpcnt_ctl      = VID_DST_H_GPCNT_CTL,
+        .gpcnt          = VID_DST_H_GPCNT,
+        .vip_ctl        = VID_DST_H_VIP_CTL,
+        .pix_frmt       = VID_DST_H_PIX_FRMT,
+    },
+    
+    [SRAM_CH08] = {
+        .name       = "audio from",
+        .cmds_start = AUD_A_DOWN_CMDS,          
+        .ctrl_start = AUD_A_IQ,                 
+        .cdt        = AUD_A_CDT,        
+        .fifo_start = AUD_A_DOWN_CLUSTER_1, 
+        .fifo_size  = AUDIO_CLUSTER_SIZE * 3,       
+        .ptr1_reg   = DMA17_PTR1,                   
+        .ptr2_reg   = DMA17_PTR2,
+        .cnt1_reg   = DMA17_CNT1,
+        .cnt2_reg   = DMA17_CNT2,
+    },  
+    
+    [SRAM_CH09] = {
+        .i              = SRAM_CH09,
+        .name           = "VID Upstream I",
+        .cmds_start     = VID_I_UP_CMDS,
+        .ctrl_start     = VID_I_IQ,
+        .cdt            = VID_I_CDT,
+        .fifo_start     = VID_I_UP_CLUSTER_1,
+        .fifo_size      = (VID_CLUSTER_SIZE<<2),        
+        .ptr1_reg       = DMA15_PTR1,
+        .ptr2_reg       = DMA15_PTR2,
+        .cnt1_reg       = DMA15_CNT1,
+        .cnt2_reg       = DMA15_CNT2,
+        .int_msk        = VID_I_INT_MSK,
+        .int_stat       = VID_I_INT_STAT,
+        .int_mstat      = VID_I_INT_MSTAT,
+        .dma_ctl        = VID_SRC_I_DMA_CTL,
+        .gpcnt_ctl      = VID_SRC_I_GPCNT_CTL,
+        .gpcnt          = VID_SRC_I_GPCNT,
+        
+        .vid_fmt_ctl    = VID_SRC_I_FMT_CTL,
+        .vid_active_ctl1= VID_SRC_I_ACTIVE_CTL1,
+        .vid_active_ctl2= VID_SRC_I_ACTIVE_CTL2,
+        .vid_cdt_size   = VID_SRC_I_CDT_SZ,
+        .irq_bit        = 8,
+    },    
+
+    [SRAM_CH10] = {
+        .i              = SRAM_CH10,
+        .name           = "VID Upstream J",
+        .cmds_start     = VID_J_UP_CMDS,
+        .ctrl_start     = VID_J_IQ,
+        .cdt            = VID_J_CDT,
+        .fifo_start     = VID_J_UP_CLUSTER_1,
+        .fifo_size      = (VID_CLUSTER_SIZE<<2), 
+        .ptr1_reg       = DMA16_PTR1,
+        .ptr2_reg       = DMA16_PTR2,
+        .cnt1_reg       = DMA16_CNT1,
+        .cnt2_reg       = DMA16_CNT2,
+        .int_msk        = VID_J_INT_MSK,
+        .int_stat       = VID_J_INT_STAT,
+        .int_mstat      = VID_J_INT_MSTAT,
+        .dma_ctl        = VID_SRC_J_DMA_CTL,
+        .gpcnt_ctl      = VID_SRC_J_GPCNT_CTL,
+        .gpcnt          = VID_SRC_J_GPCNT,
+                                
+        .vid_fmt_ctl    = VID_SRC_J_FMT_CTL,
+        .vid_active_ctl1= VID_SRC_J_ACTIVE_CTL1,
+        .vid_active_ctl2= VID_SRC_J_ACTIVE_CTL2,
+        .vid_cdt_size   = VID_SRC_J_CDT_SZ,
+        .irq_bit        = 9,
+    },
+
+
+    [SRAM_CH11] = {
+        .i              = SRAM_CH11,
+        .name           = "Audio Upstream Channel B",
+        .cmds_start     = AUD_B_UP_CMDS,
+        .ctrl_start     = AUD_B_IQ,
+        .cdt            = AUD_B_CDT,
+        .fifo_start     = AUD_B_UP_CLUSTER_1,
+        .fifo_size      = (AUDIO_CLUSTER_SIZE*3), 
+        .ptr1_reg       = DMA22_PTR1,
+        .ptr2_reg       = DMA22_PTR2,
+        .cnt1_reg       = DMA22_CNT1,
+        .cnt2_reg       = DMA22_CNT2,
+        .int_msk        = AUD_B_INT_MSK,
+        .int_stat       = AUD_B_INT_STAT,
+        .int_mstat      = AUD_B_INT_MSTAT,
+        .dma_ctl        = AUD_INT_DMA_CTL,
+        .gpcnt_ctl      = AUD_B_GPCNT_CTL,
+        .gpcnt          = AUD_B_GPCNT,
+        .aud_length     = AUD_B_LNGTH,
+        .aud_cfg        = AUD_B_CFG,
+        .fld_aud_fifo_en    = FLD_AUD_SRC_B_FIFO_EN,
+        .fld_aud_risc_en    = FLD_AUD_SRC_B_RISC_EN,
+        .irq_bit        = 11,
+    },    
+};
+
+
+struct sram_channel *channel0 = &cx25821_sram_channels[SRAM_CH00];
+struct sram_channel *channel1 = &cx25821_sram_channels[SRAM_CH01];
+struct sram_channel *channel2 = &cx25821_sram_channels[SRAM_CH02];
+struct sram_channel *channel3 = &cx25821_sram_channels[SRAM_CH03];
+struct sram_channel *channel4 = &cx25821_sram_channels[SRAM_CH04];
+struct sram_channel *channel5 = &cx25821_sram_channels[SRAM_CH05];
+struct sram_channel *channel6 = &cx25821_sram_channels[SRAM_CH06];
+struct sram_channel *channel7 = &cx25821_sram_channels[SRAM_CH07];
+struct sram_channel *channel9 = &cx25821_sram_channels[SRAM_CH09];  
+struct sram_channel *channel10 = &cx25821_sram_channels[SRAM_CH10];
+struct sram_channel *channel11 = &cx25821_sram_channels[SRAM_CH11];
+
+struct cx25821_dmaqueue mpegq;
+
+static int cx25821_risc_decode(u32 risc)
+{
+    static char *instr[16] = {
+        [RISC_SYNC    >> 28] = "sync",
+        [RISC_WRITE   >> 28] = "write",
+        [RISC_WRITEC  >> 28] = "writec",
+        [RISC_READ    >> 28] = "read",
+        [RISC_READC   >> 28] = "readc",
+        [RISC_JUMP    >> 28] = "jump",
+        [RISC_SKIP    >> 28] = "skip",
+        [RISC_WRITERM >> 28] = "writerm",
+        [RISC_WRITECM >> 28] = "writecm",
+        [RISC_WRITECR >> 28] = "writecr",
+    };
+    static int incr[16] = {
+        [RISC_WRITE   >> 28] = 3,
+        [RISC_JUMP    >> 28] = 3,
+        [RISC_SKIP    >> 28] = 1,
+        [RISC_SYNC    >> 28] = 1,
+        [RISC_WRITERM >> 28] = 3,
+        [RISC_WRITECM >> 28] = 3,
+        [RISC_WRITECR >> 28] = 4,
+    };
+    static char *bits[] = {
+        "12",   "13",   "14",   "resync",
+        "cnt0", "cnt1", "18",   "19",
+        "20",   "21",   "22",   "23",
+        "irq1", "irq2", "eol",  "sol",
+    };
+    int i;
+
+    printk("0x%08x [ %s", risc, instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
+    for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--)
+        {
+        if (risc & (1 << (i + 12)))
+            printk(" %s", bits[i]);
+        }
+    printk(" count=%d ]\n", risc & 0xfff);
+    return incr[risc >> 28] ? incr[risc >> 28] : 1;
+}
+
+static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
+{
+    struct cx25821_i2c *bus = i2c_adap->algo_data;
+    struct cx25821_dev *dev = bus->dev;
+    return cx_read(bus->reg_stat) & 0x01;
+}
+
+
+void cx_i2c_read_print(struct cx25821_dev *dev, u32 reg, const char* reg_string)
+{
+    int tmp = 0;
+    u32 value = 0;
+    
+    value = cx25821_i2c_read(&dev->i2c_bus[0], reg, &tmp);
+}
+
+static void cx25821_registers_init(struct cx25821_dev *dev)
+{
+    u32 tmp;
+    
+    // enable RUN_RISC in Pecos
+    cx_write( DEV_CNTRL2, 0x20 );
+    
+    // Set the master PCI interrupt masks to enable video, audio, MBIF, and GPIO interrupts
+    // I2C interrupt masking is handled by the I2C objects themselves.
+    cx_write( PCI_INT_MSK, 0x2001FFFF );
+
+    tmp = cx_read( RDR_TLCTL0 );
+    tmp &= ~FLD_CFG_RCB_CK_EN; // Clear the RCB_CK_EN bit
+    cx_write( RDR_TLCTL0, tmp);
+
+    // PLL-A setting for the Audio Master Clock
+    cx_write( PLL_A_INT_FRAC, 0x9807A58B );
+
+    // PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1
+    cx_write( PLL_A_POST_STAT_BIST, 0x8000019C);
+    
+    // clear reset bit [31]
+    tmp = cx_read( PLL_A_INT_FRAC );
+    cx_write( PLL_A_INT_FRAC, tmp & 0x7FFFFFFF);
+
+    // PLL-B setting for Mobilygen Host Bus Interface
+    cx_write( PLL_B_INT_FRAC, 0x9883A86F);
+
+    // PLL_B_POST = 0xD, PLL_B_OUT_TO_PIN = 0x0
+    cx_write( PLL_B_POST_STAT_BIST, 0x8000018D);
+
+    // clear reset bit [31]
+    tmp = cx_read( PLL_B_INT_FRAC );
+    cx_write( PLL_B_INT_FRAC, tmp & 0x7FFFFFFF);
+
+    // PLL-C setting for video upstream channel
+    cx_write( PLL_C_INT_FRAC, 0x96A0EA3F);
+
+    // PLL_C_POST = 0x3, PLL_C_OUT_TO_PIN = 0x0
+    cx_write( PLL_C_POST_STAT_BIST, 0x80000103);
+
+    // clear reset bit [31]
+    tmp = cx_read( PLL_C_INT_FRAC );
+    cx_write( PLL_C_INT_FRAC, tmp & 0x7FFFFFFF);
+
+    // PLL-D setting for audio upstream channel
+    cx_write( PLL_D_INT_FRAC, 0x98757F5B);
+
+    // PLL_D_POST = 0x13, PLL_D_OUT_TO_PIN = 0x0
+    cx_write( PLL_D_POST_STAT_BIST, 0x80000113);
+
+    // clear reset bit [31]
+    tmp = cx_read( PLL_D_INT_FRAC );
+    cx_write( PLL_D_INT_FRAC, tmp & 0x7FFFFFFF);
+
+    
+    // This selects the PLL C clock source for the video upstream channel I and J
+    tmp = cx_read( VID_CH_CLK_SEL );
+    cx_write( VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000);
+
+    
+    // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C
+    //select 656/VIP DST for downstream Channel A - C
+    tmp = cx_read( VID_CH_MODE_SEL );
+    //cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+    cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+
+    
+    // enables 656 port I and J as output
+    tmp = cx_read( CLK_RST );
+    tmp |= FLD_USE_ALT_PLL_REF;  // use external ALT_PLL_REF pin as its reference clock instead
+    cx_write( CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE) );
+    
+    mdelay(100);
+}
+
+
+int cx25821_sram_channel_setup(struct cx25821_dev *dev,
+                   struct sram_channel *ch,
+                   unsigned int bpl, u32 risc)
+{
+    unsigned int i, lines;
+    u32 cdt;
+
+    if (ch->cmds_start == 0) {
+        cx_write(ch->ptr1_reg, 0);
+        cx_write(ch->ptr2_reg, 0);
+        cx_write(ch->cnt2_reg, 0);
+        cx_write(ch->cnt1_reg, 0);
+        return 0;
+    } 
+
+    bpl   = (bpl + 7) & ~7; /* alignment */
+    cdt   = ch->cdt;
+    lines = ch->fifo_size / bpl;
+    
+    if (lines > 4)  
+    {
+        lines = 4;
+    }
+    
+    BUG_ON(lines < 2);
+
+    cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+    cx_write(8 + 4, 8);
+    cx_write(8 + 8, 0);
+
+    /* write CDT */
+    for (i = 0; i < lines; i++) {
+        cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
+        cx_write(cdt + 16*i +  4, 0);
+        cx_write(cdt + 16*i +  8, 0);
+        cx_write(cdt + 16*i + 12, 0);
+    }
+
+    //init the first cdt buffer
+    for(i=0; i<128; i++)
+        cx_write(ch->fifo_start+4*i, i);
+
+    /* write CMDS */
+    if (ch->jumponly)
+    {       
+        cx_write(ch->cmds_start + 0, 8);
+    }
+    else
+    {       
+        cx_write(ch->cmds_start + 0, risc);
+    }
+    
+    cx_write(ch->cmds_start +  4, 0); /* 64 bits 63-32 */
+    cx_write(ch->cmds_start +  8, cdt);             
+    cx_write(ch->cmds_start + 12, (lines*16) >> 3); 
+    cx_write(ch->cmds_start + 16, ch->ctrl_start);  
+                                               
+    if (ch->jumponly)
+        cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
+    else
+        cx_write(ch->cmds_start + 20, 64 >> 2);
+
+    for (i = 24; i < 80; i += 4)
+        cx_write(ch->cmds_start + i, 0);
+
+    /* fill registers */
+    cx_write(ch->ptr1_reg, ch->fifo_start);
+    cx_write(ch->ptr2_reg, cdt);
+    cx_write(ch->cnt2_reg, (lines*16) >> 3);
+    cx_write(ch->cnt1_reg, (bpl >> 3) - 1);         
+
+    return 0;
+}
+
+int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev,
+                   struct sram_channel *ch,
+                   unsigned int bpl, u32 risc)
+{
+    unsigned int i, lines;
+    u32 cdt;
+
+
+    if (ch->cmds_start == 0) {
+        cx_write(ch->ptr1_reg, 0);
+        cx_write(ch->ptr2_reg, 0);
+        cx_write(ch->cnt2_reg, 0);
+        cx_write(ch->cnt1_reg, 0);
+        return 0;
+    }
+
+    bpl   = (bpl + 7) & ~7; /* alignment */
+    cdt   = ch->cdt;
+    lines = ch->fifo_size / bpl;
+        
+    if (lines > 3)  
+    {   
+        lines = 3;      //for AUDIO
+    }
+    
+    BUG_ON(lines < 2);
+    
+
+    cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+    cx_write(8 + 4, 8);
+    cx_write(8 + 8, 0);
+
+    /* write CDT */
+    for (i = 0; i < lines; i++) {
+        cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
+        cx_write(cdt + 16*i +  4, 0);
+        cx_write(cdt + 16*i +  8, 0);
+        cx_write(cdt + 16*i + 12, 0);
+    }
+
+    /* write CMDS */
+    if (ch->jumponly)
+    {       
+        cx_write(ch->cmds_start + 0, 8);
+    }
+    else
+    {       
+        cx_write(ch->cmds_start + 0, risc);
+    }
+    
+    cx_write(ch->cmds_start +  4, 0); /* 64 bits 63-32 */
+    cx_write(ch->cmds_start +  8, cdt);             
+    cx_write(ch->cmds_start + 12, (lines*16) >> 3); 
+    cx_write(ch->cmds_start + 16, ch->ctrl_start);  
+
+    //IQ size
+    if (ch->jumponly)
+    {       
+        cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
+    }
+    else
+    {       
+        cx_write(ch->cmds_start + 20, 64 >> 2);
+    }
+
+    //zero out
+    for (i = 24; i < 80; i += 4)
+        cx_write(ch->cmds_start + i, 0);
+
+    /* fill registers */
+    cx_write(ch->ptr1_reg, ch->fifo_start);
+    cx_write(ch->ptr2_reg, cdt);                
+    cx_write(ch->cnt2_reg, (lines*16) >> 3);    
+    cx_write(ch->cnt1_reg, (bpl >> 3) - 1);         
+    
+    return 0;
+}
+
+
+void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch)
+{
+    static char *name[] = {
+        "init risc lo",
+        "init risc hi",
+        "cdt base",
+        "cdt size",
+        "iq base",
+        "iq size",
+        "risc pc lo",
+        "risc pc hi",
+        "iq wr ptr",
+        "iq rd ptr",
+        "cdt current",
+        "pci target lo",
+        "pci target hi",
+        "line / byte",
+    };
+    u32 risc;
+    unsigned int i, j, n;
+    printk(KERN_WARNING "%s: %s - dma channel status dump\n", dev->name, ch->name);
+    for (i = 0; i < ARRAY_SIZE(name); i++)
+        printk(KERN_WARNING "cmds + 0x%2x:   %-15s: 0x%08x\n", i*4, name[i],
+               cx_read(ch->cmds_start + 4*i));
+
+    j=i*4;
+    for (i = 0; i < 4; ) {
+        risc = cx_read(ch->cmds_start + 4 * (i + 14));
+        printk(KERN_WARNING "cmds + 0x%2x:   risc%d: ", j+i*4, i);
+        i +=cx25821_risc_decode(risc);
+    }
+
+    for (i = 0; i < (64 >> 2); i += n) {
+        risc = cx_read(ch->ctrl_start + 4 * i);
+        /* No consideration for bits 63-32 */
+
+        printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i*4, ch->ctrl_start + 4 * i, i);
+        n = cx25821_risc_decode(risc);
+        for (j = 1; j < n; j++) {
+            risc = cx_read(ch->ctrl_start + 4 * (i + j));
+            printk(KERN_WARNING "ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n", 4*(i+j), i+j, risc, j);
+        }
+    }
+
+    printk(KERN_WARNING "        :   fifo: 0x%08x -> 0x%x\n",  ch->fifo_start, ch->fifo_start+ch->fifo_size);
+    printk(KERN_WARNING "        :   ctrl: 0x%08x -> 0x%x\n", ch->ctrl_start, ch->ctrl_start + 6*16);
+    printk(KERN_WARNING "        :   ptr1_reg: 0x%08x\n",   cx_read(ch->ptr1_reg));
+    printk(KERN_WARNING "        :   ptr2_reg: 0x%08x\n",   cx_read(ch->ptr2_reg));
+    printk(KERN_WARNING "        :   cnt1_reg: 0x%08x\n",   cx_read(ch->cnt1_reg));
+    printk(KERN_WARNING "        :   cnt2_reg: 0x%08x\n",   cx_read(ch->cnt2_reg));
+}
+
+void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, struct sram_channel *ch)
+{
+    static char *name[] = {
+        "init risc lo",
+        "init risc hi",
+        "cdt base",
+        "cdt size",
+        "iq base",
+        "iq size",
+        "risc pc lo",
+        "risc pc hi",
+        "iq wr ptr",
+        "iq rd ptr",
+        "cdt current",
+        "pci target lo",
+        "pci target hi",
+        "line / byte",
+    };
+    
+        u32 risc, value, tmp;
+    unsigned int i, j, n;
+
+
+    printk(KERN_INFO "\n%s: %s - dma Audio channel status dump\n", dev->name, ch->name);
+    
+    for (i = 0; i < ARRAY_SIZE(name); i++)
+        printk(KERN_INFO "%s: cmds + 0x%2x:   %-15s: 0x%08x\n", dev->name, i*4, name[i], cx_read(ch->cmds_start + 4*i));
+
+
+    j=i*4;      
+    for (i = 0; i < 4; ) {
+        risc = cx_read(ch->cmds_start + 4 * (i + 14));
+        printk(KERN_WARNING "cmds + 0x%2x:   risc%d: ", j+i*4, i);
+        i += cx25821_risc_decode(risc);
+    }
+    
+    for (i = 0; i < (64 >> 2); i += n) {
+        risc = cx_read(ch->ctrl_start + 4 * i);
+        /* No consideration for bits 63-32 */
+
+        printk(KERN_WARNING "ctrl + 0x%2x (0x%08x): iq %x: ", i*4, ch->ctrl_start + 4 * i, i);
+        n = cx25821_risc_decode(risc);
+        
+        for (j = 1; j < n; j++) {
+            risc = cx_read(ch->ctrl_start + 4 * (i + j));
+            printk(KERN_WARNING "ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n", 4*(i+j), i+j, risc, j);
+        }
+    }
+
+    printk(KERN_WARNING "        :   fifo: 0x%08x -> 0x%x\n",  ch->fifo_start, ch->fifo_start+ch->fifo_size);
+    printk(KERN_WARNING "        :   ctrl: 0x%08x -> 0x%x\n", ch->ctrl_start, ch->ctrl_start + 6*16);
+    printk(KERN_WARNING "        :   ptr1_reg: 0x%08x\n",   cx_read(ch->ptr1_reg));
+    printk(KERN_WARNING "        :   ptr2_reg: 0x%08x\n",   cx_read(ch->ptr2_reg));
+    printk(KERN_WARNING "        :   cnt1_reg: 0x%08x\n",   cx_read(ch->cnt1_reg));
+    printk(KERN_WARNING "        :   cnt2_reg: 0x%08x\n",   cx_read(ch->cnt2_reg));
+    
+    for( i=0; i < 4; i++)
+    {
+        risc = cx_read(ch->cmds_start + 56 + (i*4));
+        printk(KERN_WARNING "instruction %d = 0x%x\n", i, risc);
+    }
+
+    //read data from the first cdt buffer
+    risc = cx_read(AUD_A_CDT);      
+    printk(KERN_WARNING "\nread cdt loc=0x%x\n", risc);
+    for(i=0; i<8; i++)
+    {
+        n =  cx_read(risc+i*4);
+        printk(KERN_WARNING "0x%x ", n);
+    }   
+    printk(KERN_WARNING "\n\n");
+    
+    
+    value = cx_read(CLK_RST);
+    CX25821_INFO(" CLK_RST = 0x%x \n\n", value);
+
+    value = cx_read(PLL_A_POST_STAT_BIST);
+    CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x \n\n", value);
+    value = cx_read(PLL_A_INT_FRAC);
+    CX25821_INFO(" PLL_A_INT_FRAC = 0x%x \n\n", value);
+   
+    value = cx_read(PLL_B_POST_STAT_BIST);
+    CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x \n\n", value);
+    value = cx_read(PLL_B_INT_FRAC);
+    CX25821_INFO(" PLL_B_INT_FRAC = 0x%x \n\n", value);
+   
+    value = cx_read(PLL_C_POST_STAT_BIST);
+    CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x \n\n", value);
+    value = cx_read(PLL_C_INT_FRAC);
+    CX25821_INFO(" PLL_C_INT_FRAC = 0x%x \n\n", value);
+   
+    value = cx_read(PLL_D_POST_STAT_BIST);
+    CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x \n\n", value);
+    value = cx_read(PLL_D_INT_FRAC);
+    CX25821_INFO(" PLL_D_INT_FRAC = 0x%x \n\n", value);
+       
+    value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
+    CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x \n\n", value);
+}
+
+static void cx25821_shutdown(struct cx25821_dev *dev)
+{
+    int i;
+
+    /* disable RISC controller */
+    cx_write(DEV_CNTRL2, 0);
+
+    /* Disable Video A/B activity */
+    for(i=0; i<VID_CHANNEL_NUM; i++)
+    {
+        cx_write(dev->sram_channels[i].dma_ctl, 0);
+        cx_write(dev->sram_channels[i].int_msk, 0);
+    }
+
+    for( i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++)      
+    {
+        cx_write(dev->sram_channels[i].dma_ctl, 0);
+        cx_write(dev->sram_channels[i].int_msk, 0);
+    }
+    
+    /* Disable Audio activity */
+    cx_write(AUD_INT_DMA_CTL, 0);
+
+    /* Disable Serial port */
+    cx_write(UART_CTL, 0);
+
+    /* Disable Interrupts */
+    cx_write(PCI_INT_MSK, 0);
+    cx_write(AUD_A_INT_MSK, 0);
+}
+
+void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select, u32 format)
+{        
+    struct sram_channel *ch;    
+    if( channel_select <= 7 && channel_select >= 0 )
+    {
+        ch = &cx25821_sram_channels[channel_select];
+        cx_write(ch->pix_frmt, format);
+        dev->pixel_formats[channel_select] = format;
+    }
+}
+
+static void cx25821_set_vip_mode(struct cx25821_dev *dev, struct sram_channel *ch)
+{
+    cx_write(ch->pix_frmt,   PIXEL_FRMT_422);
+    cx_write(ch->vip_ctl, PIXEL_ENGINE_VIP1);
+}
+
+static void cx25821_initialize(struct cx25821_dev *dev)
+{
+    int i;
+
+    dprintk(1, "%s()\n", __func__);
+    
+    cx25821_shutdown(dev);
+    cx_write(PCI_INT_STAT,   0xffffffff);
+    for(i=0; i<VID_CHANNEL_NUM; i++)
+        cx_write(dev->sram_channels[i].int_stat, 0xffffffff);
+
+
+    cx_write(AUD_A_INT_STAT, 0xffffffff);
+    cx_write(AUD_B_INT_STAT, 0xffffffff);
+    cx_write(AUD_C_INT_STAT, 0xffffffff);
+    cx_write(AUD_D_INT_STAT, 0xffffffff);
+    cx_write(AUD_E_INT_STAT, 0xffffffff);
+
+    cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000);
+    cx_write(PAD_CTRL, 0x12);       //for I2C   
+    cx25821_registers_init(dev);    //init Pecos registers
+    mdelay(100);
+    
+    
+    for(i=0; i<VID_CHANNEL_NUM; i++)
+    {
+        cx25821_set_vip_mode(dev, &dev->sram_channels[i]);
+        cx25821_sram_channel_setup(dev, &dev->sram_channels[i], 1440, 0);
+        dev->pixel_formats[i]     = PIXEL_FRMT_422;
+        dev->use_cif_resolution[i]  = FALSE;
+    }
+
+    //Probably only affect Downstream
+    for( i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++)      
+    {
+        cx25821_set_vip_mode(dev, &dev->sram_channels[i]);
+    }
+    
+    cx25821_sram_channel_setup_audio(dev, &dev->sram_channels[SRAM_CH08], 128, 0);      
+
+    cx25821_gpio_init(dev);
+}
+
+static int get_resources(struct cx25821_dev *dev)
+{
+    if (request_mem_region(pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0), dev->name))
+        return 0;
+
+    printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
+           dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
+
+    return -EBUSY;
+}
+
+
+static void cx25821_dev_checkrevision(struct cx25821_dev *dev)
+{
+    dev->hwrevision = cx_read(RDR_CFG2) & 0xff; 
+
+    printk(KERN_INFO "%s() Hardware revision = 0x%02x\n", __func__, dev->hwrevision);
+}
+
+static void cx25821_iounmap(struct cx25821_dev *dev)
+{
+    if (dev == NULL)
+        return;
+
+    /* Releasing IO memory */
+    if (dev->lmmio != NULL) 
+    {
+        CX25821_INFO("Releasing lmmio.\n");
+        iounmap(dev->lmmio);
+        dev->lmmio = NULL;
+    }
+}
+
+
+static int cx25821_dev_setup(struct cx25821_dev *dev)
+{       
+    int io_size = 0, i;
+        
+    struct video_device *video_template[] = {
+                        &cx25821_video_template0,
+                        &cx25821_video_template1,
+                        &cx25821_video_template2,
+                        &cx25821_video_template3,
+                        &cx25821_video_template4,
+                        &cx25821_video_template5,
+                        &cx25821_video_template6,
+                        &cx25821_video_template7,
+                        &cx25821_video_template9,       
+                        &cx25821_video_template10,
+                        &cx25821_video_template11,  
+                        &cx25821_videoioctl_template,    
+                        };
+
+    printk(KERN_INFO "\n***********************************\n");
+    printk(KERN_INFO "cx25821 set up\n");
+    printk(KERN_INFO "***********************************\n\n");
+    
+    mutex_init(&dev->lock);
+
+    atomic_inc(&dev->refcount);
+
+    dev->nr = ++cx25821_devcount;
+    sprintf(dev->name, "cx25821[%d]", dev->nr);
+
+    mutex_lock(&devlist);
+    list_add_tail(&dev->devlist, &cx25821_devlist);
+    mutex_unlock(&devlist);
+
+    strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown");
+    strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821");
+        
+    
+    if( dev->pci->device != 0x8210 )
+    {
+        printk(KERN_INFO "%s() Exiting. Incorrect Hardware device = 0x%02x\n",
+            __func__, dev->pci->device);
+        return -1;
+    }
+    else
+    {   
+        printk(KERN_INFO "Athena Hardware device = 0x%02x\n", dev->pci->device);
+    }
+    
+    /* Apply a sensible clock frequency for the PCIe bridge */
+    dev->clk_freq = 28000000;
+    dev->sram_channels = cx25821_sram_channels;
+
+    if(dev->nr > 1)
+    {
+        CX25821_INFO("dev->nr > 1!");
+    }
+
+    /* board config */
+    dev->board = 1; //card[dev->nr];  
+    dev->_max_num_decoders = MAX_DECODERS;
+
+
+    dev->pci_bus  = dev->pci->bus->number;
+    dev->pci_slot = PCI_SLOT(dev->pci->devfn);
+    dev->pci_irqmask = 0x001f00;
+
+    /* External Master 1 Bus */
+    dev->i2c_bus[0].nr = 0;
+    dev->i2c_bus[0].dev = dev;
+    dev->i2c_bus[0].reg_stat  = I2C1_STAT;
+    dev->i2c_bus[0].reg_ctrl  = I2C1_CTRL;
+    dev->i2c_bus[0].reg_addr  = I2C1_ADDR;
+    dev->i2c_bus[0].reg_rdata = I2C1_RDATA;
+    dev->i2c_bus[0].reg_wdata = I2C1_WDATA;
+    dev->i2c_bus[0].i2c_period = (0x07 << 24); /* 1.95MHz */
+
+
+
+    if (get_resources(dev) < 0) 
+    {
+        printk(KERN_ERR "%s No more PCIe resources for "
+               "subsystem: %04x:%04x\n",
+               dev->name, dev->pci->subsystem_vendor,
+               dev->pci->subsystem_device);
+
+        cx25821_devcount--;
+        return -ENODEV;
+    }
+
+    /* PCIe stuff */    
+    dev->base_io_addr = pci_resource_start(dev->pci, 0);
+    io_size           = pci_resource_len(dev->pci, 0);
+        
+    if (!dev->base_io_addr) {
+        CX25821_ERR("No PCI Memory resources, exiting!\n");
+        return -ENODEV;
+    }
+    
+    dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0));
+
+    if (!dev->lmmio) {
+        CX25821_ERR("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n");
+        cx25821_iounmap(dev);
+        return -ENOMEM;
+    }
+    
+
+    dev->bmmio = (u8 __iomem *)dev->lmmio;
+
+    printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+           dev->name, dev->pci->subsystem_vendor,
+           dev->pci->subsystem_device, cx25821_boards[dev->board].name,
+           dev->board, card[dev->nr] == dev->board ?
+           "insmod option" : "autodetected");
+
+    /* init hardware */
+    cx25821_initialize(dev);
+    
+    cx25821_i2c_register(&dev->i2c_bus[0]);
+//  cx25821_i2c_register(&dev->i2c_bus[1]);
+//  cx25821_i2c_register(&dev->i2c_bus[2]);
+
+    CX25821_INFO("i2c register! bus->i2c_rc = %d\n", dev->i2c_bus[0].i2c_rc);
+
+    cx25821_card_setup(dev);    
+    medusa_video_init(dev);
+    
+    for(i = 0; i < VID_CHANNEL_NUM; i++)
+    {
+        if (cx25821_video_register(dev, i, video_template[i]) < 0) {
+            printk(KERN_ERR "%s() Failed to register analog video adapters on VID channel %d\n", __func__, i);
+        }
+    }
+        
+    
+    for(i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++)
+    {
+        //Since we don't have template8 for Audio Downstream
+        if (cx25821_video_register(dev, i, video_template[i-1]) < 0) {
+            printk(KERN_ERR "%s() Failed to register analog video adapters for Upstream channel %d.\n", __func__, i);
+        }
+    }
+    // register IOCTL device 
+    dev->ioctl_dev = cx25821_vdev_init(dev, dev->pci, video_template[VIDEO_IOCTL_CH], "video");
+    
+    if( video_register_device(dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0 )
+    {        
+        cx25821_videoioctl_unregister(dev);
+        printk(KERN_ERR "%s() Failed to register video adapter for IOCTL so releasing.\n", __func__);
+    }
+         
+    cx25821_dev_checkrevision(dev);
+    CX25821_INFO("cx25821 setup done!\n");
+    
+    return 0;
+}  
+
+
+void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, struct upstream_user_struct *up_data)
+{
+    dev->_isNTSC = !strcmp(dev->vid_stdname,"NTSC") ? 1 : 0;             
+    
+    dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;  
+    medusa_set_videostandard(dev);
+    
+    cx25821_vidupstream_init_ch1(dev, dev->channel_select, dev->pixel_format);      
+}
+
+
+void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, struct upstream_user_struct *up_data)
+{
+    dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2,"NTSC") ? 1 : 0;            
+
+    dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; 
+    medusa_set_videostandard(dev);  
+    
+    cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2, dev->pixel_format_ch2);      
+}
+
+
+void cx25821_start_upstream_audio(struct cx25821_dev *dev, struct upstream_user_struct *up_data)
+{
+    cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B);        
+}
+  
+void cx25821_dev_unregister(struct cx25821_dev *dev)
+{
+    int i;
+
+    if (!dev->base_io_addr) 
+        return;
+        
+    cx25821_free_mem_upstream_ch1(dev);
+    cx25821_free_mem_upstream_ch2(dev);         
+    cx25821_free_mem_upstream_audio(dev);       
+    
+    release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0));
+
+    if (!atomic_dec_and_test(&dev->refcount))
+        return;
+
+    for(i=0; i < VID_CHANNEL_NUM; i++)
+        cx25821_video_unregister(dev, i);
+
+    
+    for(i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++)
+    {
+        cx25821_video_unregister(dev, i);
+    }
+    
+    cx25821_videoioctl_unregister(dev);
+    
+    cx25821_i2c_unregister( &dev->i2c_bus[0] );
+    cx25821_iounmap(dev);
+}
+
+
+
+static __le32 *cx25821_risc_field(__le32 *rp, struct scatterlist *sglist,
+                   unsigned int offset, u32 sync_line,
+                   unsigned int bpl, unsigned int padding,
+                   unsigned int lines)
+{
+    struct scatterlist *sg;
+    unsigned int line, todo;
+
+    /* sync instruction */
+    if (sync_line != NO_SYNC_LINE)
+    {
+        *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);    
+    }
+
+    /* scan lines */
+    sg = sglist;
+    for (line = 0; line < lines; line++) {
+        while (offset && offset >= sg_dma_len(sg)) {
+            offset -= sg_dma_len(sg);
+            sg++;
+        }
+        if (bpl <= sg_dma_len(sg)-offset) {            
+            /* fits into current chunk */
+            *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); 
+            *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);   
+            *(rp++) = cpu_to_le32(0); /* bits 63-32 */      
+            offset += bpl;
+        } else {
+            /* scanline needs to be split */
+            todo = bpl;
+            *(rp++) = cpu_to_le32(RISC_WRITE|RISC_SOL|(sg_dma_len(sg)-offset)); 
+            *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);           
+            *(rp++) = cpu_to_le32(0); /* bits 63-32 */              
+            todo -= (sg_dma_len(sg)-offset);
+            offset = 0;
+            sg++;
+            while (todo > sg_dma_len(sg)) {
+                *(rp++) = cpu_to_le32(RISC_WRITE|sg_dma_len(sg));       
+                *(rp++) = cpu_to_le32(sg_dma_address(sg));          
+                *(rp++) = cpu_to_le32(0); /* bits 63-32 */          
+                todo -= sg_dma_len(sg);
+                sg++;
+            }
+            *(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
+            *(rp++) = cpu_to_le32(sg_dma_address(sg));              
+            *(rp++) = cpu_to_le32(0); /* bits 63-32 */              
+            offset += todo;
+        }
+
+        offset += padding;
+    }
+
+    return rp;
+}
+
+int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+            struct scatterlist *sglist, unsigned int top_offset,
+            unsigned int bottom_offset, unsigned int bpl,
+            unsigned int padding, unsigned int lines)
+{
+    u32 instructions;
+        u32  fields;
+    __le32 *rp;
+    int rc;
+
+    fields = 0;
+    if (UNSET != top_offset)
+        fields++;
+    if (UNSET != bottom_offset)
+        fields++;
+
+    /* estimate risc mem: worst case is one write per page border +
+       one write per scan line + syncs + jump (all 2 dwords).  Padding
+       can cause next bpl to start close to a page border.  First DMA
+       region may be smaller than PAGE_SIZE */
+    /* write and jump need and extra dword */
+    instructions  = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
+    instructions += 2;
+    rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+
+    if (rc < 0)
+        return rc;
+
+    /* write risc instructions */
+    rp = risc->cpu;
+       
+    if (UNSET != top_offset)
+    {
+        rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding, lines);
+    }
+
+    if (UNSET != bottom_offset)
+    {
+        rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl, padding, lines);  
+    }
+
+    /* save pointer to jmp instruction address */
+    risc->jmp = rp;
+    BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+
+    return 0;
+}
+
+
+static __le32* cx25821_risc_field_audio(__le32 *rp, struct scatterlist *sglist,
+                   unsigned int offset, u32 sync_line,
+                   unsigned int bpl, unsigned int padding,
+                   unsigned int lines, unsigned int lpi)
+{
+    struct scatterlist *sg;
+    unsigned int line, todo, sol;
+
+    /* sync instruction */
+    if (sync_line != NO_SYNC_LINE)
+        *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+    /* scan lines */
+    sg = sglist;
+    for (line = 0; line < lines; line++) {
+        while (offset && offset >= sg_dma_len(sg)) {
+            offset -= sg_dma_len(sg);
+            sg++;
+        }
+
+        if (lpi && line > 0 && !(line % lpi))
+            sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
+        else
+            sol = RISC_SOL;
+
+        if (bpl <= sg_dma_len(sg)-offset) {
+            /* fits into current chunk */
+            *(rp++) = cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
+            *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
+            *(rp++)=cpu_to_le32(0); /* bits 63-32 */
+            offset+=bpl;
+        } else {
+            /* scanline needs to be split */
+            todo = bpl;
+            *(rp++) = cpu_to_le32(RISC_WRITE|sol|
+                        (sg_dma_len(sg)-offset));
+            *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
+            *(rp++)=cpu_to_le32(0); /* bits 63-32 */
+            todo -= (sg_dma_len(sg)-offset);
+            offset = 0;
+            sg++;
+            while (todo > sg_dma_len(sg)) {
+                *(rp++)=cpu_to_le32(RISC_WRITE|
+                            sg_dma_len(sg));
+                *(rp++)=cpu_to_le32(sg_dma_address(sg));
+                *(rp++)=cpu_to_le32(0); /* bits 63-32 */
+                todo -= sg_dma_len(sg);
+                sg++;
+            }
+            *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
+            *(rp++)=cpu_to_le32(sg_dma_address(sg));
+            *(rp++)=cpu_to_le32(0); /* bits 63-32 */
+            offset += todo;
+        }
+        offset += padding;
+    }
+
+    return rp;
+}
+
+int cx25821_risc_databuffer_audio(struct pci_dev *pci,
+                            struct btcx_riscmem *risc,
+                            struct scatterlist *sglist,
+                            unsigned int bpl,
+                            unsigned int lines,
+                            unsigned int lpi)
+{
+    u32 instructions;
+    __le32 *rp;
+    int rc;
+
+    /* estimate risc mem: worst case is one write per page border +
+       one write per scan line + syncs + jump (all 2 dwords).  Here
+       there is no padding and no sync.  First DMA region may be smaller
+       than PAGE_SIZE */
+    /* Jump and write need an extra dword */
+    instructions  = 1 + (bpl * lines) / PAGE_SIZE + lines;
+    instructions += 1;
+
+    if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 0)
+        return rc;
+
+
+    /* write risc instructions */
+    rp = risc->cpu;
+    rp = cx25821_risc_field_audio(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi);
+    
+    /* save pointer to jmp instruction address */
+    risc->jmp = rp;
+    BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
+    return 0;
+}
+
+
+int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,u32 reg, u32 mask, u32 value)
+{
+    __le32 *rp;
+    int rc;
+
+    rc = btcx_riscmem_alloc(pci, risc, 4*16);
+
+    if (rc < 0)
+        return rc;
+
+    /* write risc instructions */
+    rp = risc->cpu;
+
+    *(rp++) = cpu_to_le32(RISC_WRITECR  | RISC_IRQ1);   
+    *(rp++) = cpu_to_le32(reg);                 
+    *(rp++) = cpu_to_le32(value);                   
+    *(rp++) = cpu_to_le32(mask);                    
+    *(rp++) = cpu_to_le32(RISC_JUMP); 
+    *(rp++) = cpu_to_le32(risc->dma);               
+    *(rp++) = cpu_to_le32(0); /* bits 63-32 */          
+    return 0;
+}
+
+void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf)
+{
+    struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+
+    BUG_ON(in_interrupt());
+    videobuf_waiton(&buf->vb, 0, 0);
+    videobuf_dma_unmap(q, dma);
+    videobuf_dma_free(dma);
+    btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+    buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+
+static irqreturn_t cx25821_irq(int irq, void *dev_id)
+{
+    struct cx25821_dev *dev = dev_id;
+    u32 pci_status, pci_mask;
+    u32 vid_status;
+    int i, handled = 0;
+    u32 mask[8] = {1, 2, 4, 8, 16, 32, 64, 128};
+
+    pci_status = cx_read(PCI_INT_STAT);
+    pci_mask = cx_read(PCI_INT_MSK);
+
+    
+    if (pci_status == 0) 
+        goto out;
+
+    for(i = 0; i < VID_CHANNEL_NUM; i++)
+    {
+        if(pci_status & mask[i])
+        {
+            vid_status = cx_read(dev->sram_channels[i].int_stat); 
+
+            if(vid_status)
+                handled += cx25821_video_irq(dev, i, vid_status);
+
+            cx_write(PCI_INT_STAT, mask[i]);
+        }
+    }
+    
+out:
+    return IRQ_RETVAL(handled);
+}
+
+void cx25821_print_irqbits(char *name, char *tag, char **strings,
+                           int len, u32 bits, u32 mask)
+{
+    unsigned int i;
+
+    printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
+    
+    for (i = 0; i < len; i++) {
+        if (!(bits & (1 << i)))
+            continue;
+        if (strings[i])
+            printk(" %s", strings[i]);
+        else
+            printk(" %d", i);
+        if (!(mask & (1 << i)))
+            continue;
+        printk("*");
+    }
+    printk("\n");
+}
+
+struct cx25821_dev* cx25821_dev_get(struct pci_dev *pci)
+{
+    struct cx25821_dev *dev = pci_get_drvdata(pci); 
+    return dev;
+}
+
+static int __devinit cx25821_initdev(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
+{
+    struct cx25821_dev *dev;        
+    int err = 0;
+
+    dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+    if (NULL == dev)
+        return -ENOMEM;
+        
+    
+    err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
+    if (err < 0)
+        goto fail_free;
+        
+    /* pci init */
+    dev->pci = pci_dev;
+    if (pci_enable_device(pci_dev)) 
+    {
+        err = -EIO;
+
+        printk(KERN_INFO "pci enable failed! ");
+
+        goto fail_unregister_device;
+    }
+
+    printk(KERN_INFO "cx25821 Athena pci enable ! \n");
+
+    if (cx25821_dev_setup(dev) < 0) 
+    {
+        err = -EINVAL;
+        goto fail_unregister_device;
+    }
+
+    /* print pci info */
+    pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
+    pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
+    printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
+           "latency: %d, mmio: 0x%llx\n", dev->name,
+           pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
+           dev->pci_lat,
+           (unsigned long long)dev->base_io_addr );
+           
+
+    pci_set_master(pci_dev);
+    if (!pci_dma_supported(pci_dev, 0xffffffff)) 
+    {
+        printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
+        err = -EIO;
+        goto fail_irq;
+    }
+
+    err = request_irq(pci_dev->irq, cx25821_irq, IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
+
+    if (err < 0) 
+    {
+        printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name, pci_dev->irq);
+        goto fail_irq;
+    }
+
+    return 0;
+
+fail_irq:
+    printk(KERN_INFO "cx25821 cx25821_initdev() can't get IRQ ! \n");
+    cx25821_dev_unregister(dev);
+    
+fail_unregister_device:     
+    v4l2_device_unregister(&dev->v4l2_dev);
+    
+fail_free:
+    kfree(dev);
+    return err;
+}
+
+static void __devexit cx25821_finidev(struct pci_dev *pci_dev)
+{
+    struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+    struct cx25821_dev *dev      = get_cx25821(v4l2_dev);
+    
+    cx25821_shutdown(dev);      
+    pci_disable_device(pci_dev);
+
+    /* unregister stuff */
+    if( pci_dev->irq )      
+        free_irq(pci_dev->irq, dev);
+        
+        
+    mutex_lock(&devlist);
+    list_del(&dev->devlist);
+    mutex_unlock(&devlist);
+
+    cx25821_dev_unregister(dev);
+    v4l2_device_unregister(v4l2_dev);       
+    kfree(dev);
+}
+
+static struct pci_device_id cx25821_pci_tbl[] = {
+    {
+        /* CX25821 Athena*/
+        .vendor       = 0x14f1,
+        .device       = 0x8210,
+        .subvendor    = 0x14f1,
+        .subdevice    = 0x0920,
+    }, 
+    {
+        /* --- end of list --- */
+    }
+};
+
+MODULE_DEVICE_TABLE(pci, cx25821_pci_tbl);
+
+static struct pci_driver cx25821_pci_driver = 
+{
+    .name     = "cx25821",
+    .id_table = cx25821_pci_tbl,
+    .probe    = cx25821_initdev,
+    .remove   = __devexit_p(cx25821_finidev),
+    /* TODO */
+    .suspend  = NULL,
+    .resume   = NULL,
+};
+
+static int cx25821_init(void)
+{
+    INIT_LIST_HEAD(&cx25821_devlist);       
+    printk(KERN_INFO "cx25821 driver version %d.%d.%d loaded\n",
+           (CX25821_VERSION_CODE >> 16) & 0xff,
+           (CX25821_VERSION_CODE >>  8) & 0xff,
+            CX25821_VERSION_CODE & 0xff);
+    return pci_register_driver(&cx25821_pci_driver);
+}
+
+static void cx25821_fini(void)
+{
+    pci_unregister_driver(&cx25821_pci_driver);
+}
+
+
+EXPORT_SYMBOL(cx25821_devlist);
+EXPORT_SYMBOL(cx25821_sram_channels);
+EXPORT_SYMBOL(cx25821_print_irqbits);
+EXPORT_SYMBOL(cx25821_dev_get);
+EXPORT_SYMBOL(cx25821_dev_unregister);
+EXPORT_SYMBOL(cx25821_sram_channel_setup);
+EXPORT_SYMBOL(cx25821_sram_channel_dump);
+EXPORT_SYMBOL(cx25821_sram_channel_setup_audio);
+EXPORT_SYMBOL(cx25821_sram_channel_dump_audio);
+EXPORT_SYMBOL(cx25821_risc_databuffer_audio);
+EXPORT_SYMBOL(cx25821_set_gpiopin_direction);
+
+module_init(cx25821_init);
+module_exit(cx25821_fini);
+
diff --git a/drivers/staging/cx25821/cx25821-gpio.c b/drivers/staging/cx25821/cx25821-gpio.c
new file mode 100644 (file)
index 0000000..aa029fe
--- /dev/null
@@ -0,0 +1,116 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+#include "cx25821.h"
+
+
+/********************* GPIO stuffs *********************/
+void cx25821_set_gpiopin_direction( struct cx25821_dev *dev,
+                                    int    pin_number,
+                                    int    pin_logic_value)
+{
+    int  bit = pin_number;
+    u32 gpio_oe_reg = GPIO_LO_OE;
+       u32 gpio_register = 0;
+    u32 value = 0;
+       
+    // Check for valid pinNumber
+    if ( pin_number >= 47 )
+        return;
+
+
+    if ( pin_number > 31 )
+       {
+           bit = pin_number - 31;
+           gpio_oe_reg = GPIO_HI_OE;
+       }
+
+    // Here we will make sure that the GPIOs 0 and 1 are output. keep the rest as is
+    gpio_register = cx_read( gpio_oe_reg );
+       
+    if (pin_logic_value == 1)
+    {
+        value = gpio_register | Set_GPIO_Bit(bit) ;
+    }
+    else
+    {
+        value = gpio_register & Clear_GPIO_Bit(bit) ;
+    }
+
+    cx_write( gpio_oe_reg, value );
+}
+
+static void cx25821_set_gpiopin_logicvalue( struct cx25821_dev *dev,
+                                            int    pin_number,
+                                            int    pin_logic_value)
+{    
+    int bit      = pin_number;
+    u32 gpio_reg = GPIO_LO;
+       u32 value    = 0;
+       
+       
+       // Check for valid pinNumber
+    if (pin_number >= 47)
+        return;
+       
+    cx25821_set_gpiopin_direction(dev, pin_number, 0);  // change to output direction
+
+
+    if ( pin_number > 31 )
+       {
+           bit      = pin_number - 31;
+           gpio_reg = GPIO_HI;
+       }
+
+    value = cx_read( gpio_reg );
+   
+   
+    if (pin_logic_value == 0)
+    {
+        value &= Clear_GPIO_Bit(bit);
+    }
+    else
+    {
+        value |= Set_GPIO_Bit(bit);
+    }
+
+    cx_write( gpio_reg, value);
+}
+
+void cx25821_gpio_init(struct cx25821_dev *dev)
+{
+       if( dev == NULL )
+       {
+           return;
+       }
+               
+       switch (dev->board) 
+       {
+               case CX25821_BOARD_CONEXANT_ATHENA10:   
+               default:                
+                 //set GPIO 5 to select the path for Medusa/Athena
+                       cx25821_set_gpiopin_logicvalue(dev, 5, 1);  
+                       mdelay(20);
+                       break;
+       }
+       
+}
diff --git a/drivers/staging/cx25821/cx25821-gpio.h b/drivers/staging/cx25821/cx25821-gpio.h
new file mode 100644 (file)
index 0000000..2dd938d
--- /dev/null
@@ -0,0 +1,3 @@
+
+void cx25821_gpio_init(struct athena_dev *dev);
+
diff --git a/drivers/staging/cx25821/cx25821-i2c.c b/drivers/staging/cx25821/cx25821-i2c.c
new file mode 100644 (file)
index 0000000..16303f8
--- /dev/null
@@ -0,0 +1,437 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>\r
+ *     Based on Steven Toth <stoth@linuxtv.org> cx23885 driver\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+#include "cx25821.h"
+#include <linux/i2c.h>
+
+
+static unsigned int i2c_debug;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+static unsigned int i2c_scan=0;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+#define dprintk(level, fmt, arg...)\
+       do { if (i2c_debug >= level)\
+               printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+       } while (0)
+
+#define I2C_WAIT_DELAY 32
+#define I2C_WAIT_RETRY 64
+
+#define I2C_EXTEND  (1 << 3)
+#define I2C_NOSTOP  (1 << 4)
+
+
+static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
+{
+       struct cx25821_i2c *bus = i2c_adap->algo_data;
+       struct cx25821_dev *dev = bus->dev;
+       return cx_read(bus->reg_stat) & 0x01;
+}
+
+static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
+{
+       struct cx25821_i2c *bus = i2c_adap->algo_data;
+       struct cx25821_dev *dev = bus->dev;
+       return cx_read(bus->reg_stat) & 0x02 ? 1 : 0;
+}
+
+static int i2c_wait_done(struct i2c_adapter *i2c_adap)
+{
+       int count;
+
+       for (count = 0; count < I2C_WAIT_RETRY; count++) {
+               if (!i2c_is_busy(i2c_adap))
+                       break;
+               udelay(I2C_WAIT_DELAY);
+       }
+
+       if (I2C_WAIT_RETRY == count)
+               return 0;
+
+       return 1;
+}
+
+static int i2c_sendbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg, int joined_rlen)
+{
+       struct cx25821_i2c *bus = i2c_adap->algo_data;
+       struct cx25821_dev *dev = bus->dev;
+       u32 wdata, addr, ctrl;
+       int retval, cnt;
+
+       if (joined_rlen)
+               dprintk(1,  "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__, msg->len, joined_rlen);
+       else
+               dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
+
+       /* Deal with i2c probe functions with zero payload */
+       if (msg->len == 0) 
+       {
+               cx_write(bus->reg_addr, msg->addr << 25);
+               cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2));
+
+               if (!i2c_wait_done(i2c_adap))
+                       return -EIO;
+
+               if (!i2c_slave_did_ack(i2c_adap))
+                       return -EIO;
+
+               dprintk(1, "%s() returns 0\n", __func__);
+               return 0;
+       }
+
+       /* dev, reg + first byte */
+       addr = (msg->addr << 25) | msg->buf[0];
+       wdata = msg->buf[0];
+   
+       ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+       if (msg->len > 1)
+               ctrl |= I2C_NOSTOP | I2C_EXTEND;
+       else if (joined_rlen)
+               ctrl |= I2C_NOSTOP;
+
+       cx_write(bus->reg_addr, addr);
+       cx_write(bus->reg_wdata, wdata);
+       cx_write(bus->reg_ctrl, ctrl);
+
+       retval = i2c_wait_done(i2c_adap);
+       if (retval < 0)
+               goto err;
+
+       if (retval == 0)
+               goto eio;
+
+       if (i2c_debug) 
+       {
+               if (!(ctrl & I2C_NOSTOP))
+                       printk(" >\n");
+       }
+
+       for (cnt = 1; cnt < msg->len; cnt++) {
+               /* following bytes */
+               wdata = msg->buf[cnt];
+               ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+               if (cnt < msg->len - 1)
+                       ctrl |= I2C_NOSTOP | I2C_EXTEND;
+               else if (joined_rlen)
+                       ctrl |= I2C_NOSTOP;
+
+               cx_write(bus->reg_addr, addr);
+               cx_write(bus->reg_wdata, wdata);
+               cx_write(bus->reg_ctrl, ctrl);
+
+               retval = i2c_wait_done(i2c_adap);
+               if (retval < 0)
+                       goto err;
+
+               if (retval == 0)
+                       goto eio;
+
+               if (i2c_debug) 
+               {
+                       dprintk(1, " %02x", msg->buf[cnt]);
+                       if (!(ctrl & I2C_NOSTOP))
+                               dprintk(1, " >\n");
+               }
+       }
+       return msg->len;
+
+ eio:
+       retval = -EIO;
+ err:
+       if (i2c_debug)
+               printk(KERN_ERR " ERR: %d\n", retval);
+       return retval;
+}
+
+static int i2c_readbytes(struct i2c_adapter *i2c_adap, const struct i2c_msg *msg, int joined)
+{
+       struct cx25821_i2c *bus = i2c_adap->algo_data;
+       struct cx25821_dev *dev = bus->dev;
+       u32 ctrl, cnt;
+       int retval;
+
+
+       if (i2c_debug && !joined)
+               dprintk(1, "6-%s(msg->len=%d)\n", __func__, msg->len);
+
+       /* Deal with i2c probe functions with zero payload */
+       if (msg->len == 0) {
+               cx_write(bus->reg_addr, msg->addr << 25);
+               cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1);
+               if (!i2c_wait_done(i2c_adap))
+                       return -EIO;
+               if (!i2c_slave_did_ack(i2c_adap))
+                       return -EIO;
+
+
+               dprintk(1, "%s() returns 0\n", __func__);
+               return 0;
+       }
+
+       if (i2c_debug) {
+               if (joined)
+                       dprintk(1, " R");
+               else
+                       dprintk(1, " <R %02x", (msg->addr << 1) + 1);
+       }
+
+       for (cnt = 0; cnt < msg->len; cnt++) {
+
+               ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
+
+               if (cnt < msg->len - 1)
+                       ctrl |= I2C_NOSTOP | I2C_EXTEND;
+
+
+               cx_write(bus->reg_addr, msg->addr << 25);
+               cx_write(bus->reg_ctrl, ctrl);
+
+               retval = i2c_wait_done(i2c_adap);
+               if (retval < 0)
+                       goto err;
+               if (retval == 0)
+                       goto eio;
+               msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
+
+               if (i2c_debug) {
+                       dprintk(1, " %02x", msg->buf[cnt]);
+                       if (!(ctrl & I2C_NOSTOP))
+                               dprintk(1, " >\n");
+               }
+       }
+
+       return msg->len;
+ eio:
+       retval = -EIO;
+ err:
+       if (i2c_debug)
+               printk(KERN_ERR " ERR: %d\n", retval);
+       return retval;
+}
+
+static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
+{
+       struct cx25821_i2c *bus = i2c_adap->algo_data;
+       struct cx25821_dev *dev = bus->dev;
+       int i, retval = 0;
+
+       dprintk(1, "%s(num = %d)\n", __func__, num);
+
+       for (i = 0 ; i < num; i++) 
+       {
+               dprintk(1, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
+                       __func__, num, msgs[i].addr, msgs[i].len);
+
+               if (msgs[i].flags & I2C_M_RD) 
+               {
+                       /* read */
+                       retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
+               } 
+               else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
+                          msgs[i].addr == msgs[i + 1].addr) 
+           {
+                       /* write then read from same address */
+                       retval = i2c_sendbytes(i2c_adap, &msgs[i], msgs[i + 1].len);
+
+                       if (retval < 0)
+                               goto err;
+                       i++;
+                       retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
+               } 
+               else 
+               {
+                       /* write */
+                       retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
+               }
+               
+               if (retval < 0)
+                       goto err;
+       }
+       return num;
+
+ err:
+       return retval;
+}\r
+
+
+static u32 cx25821_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL | 
+               I2C_FUNC_I2C |
+               I2C_FUNC_SMBUS_WORD_DATA | 
+               I2C_FUNC_SMBUS_READ_WORD_DATA |
+               I2C_FUNC_SMBUS_WRITE_WORD_DATA;
+}
+
+static struct i2c_algorithm cx25821_i2c_algo_template = {
+       .master_xfer    = i2c_xfer,
+       .functionality  = cx25821_functionality,
+};
+
+
+static struct i2c_adapter cx25821_i2c_adap_template = {
+       .name              = "cx25821",
+       .owner             = THIS_MODULE,
+       .id                = I2C_HW_B_CX25821,
+       .algo              = &cx25821_i2c_algo_template,\r
+};
+
+static struct i2c_client cx25821_i2c_client_template = {
+       .name   = "cx25821 internal",
+};
+
+/* init + register i2c algo-bit adapter */
+int cx25821_i2c_register(struct cx25821_i2c *bus)
+{
+       struct cx25821_dev *dev = bus->dev;
+
+       dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
+
+       memcpy(&bus->i2c_adap, &cx25821_i2c_adap_template,
+              sizeof(bus->i2c_adap));
+       memcpy(&bus->i2c_algo, &cx25821_i2c_algo_template,
+              sizeof(bus->i2c_algo));
+       memcpy(&bus->i2c_client, &cx25821_i2c_client_template,
+              sizeof(bus->i2c_client));
+
+       bus->i2c_adap.dev.parent = &dev->pci->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;\r
+       i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
+       i2c_add_adapter(&bus->i2c_adap);
+
+       bus->i2c_client.adapter = &bus->i2c_adap;
+
+    //set up the I2c
+    bus->i2c_client.addr = (0x88>>1);
+        
+       return bus->i2c_rc;
+}
+
+int cx25821_i2c_unregister(struct cx25821_i2c *bus)
+{
+       i2c_del_adapter(&bus->i2c_adap);
+       return 0;
+}
+
+void cx25821_av_clk(struct cx25821_dev *dev, int enable)
+{
+       /* write 0 to bus 2 addr 0x144 via i2x_xfer() */
+       char buffer[3];
+       struct i2c_msg msg;
+       dprintk(1, "%s(enabled = %d)\n", __func__, enable);
+
+       /* Register 0x144 */
+       buffer[0] = 0x01;
+       buffer[1] = 0x44;
+       if (enable == 1)
+               buffer[2] = 0x05;
+       else
+               buffer[2] = 0x00;
+
+       msg.addr = 0x44;
+       msg.flags = I2C_M_TEN;
+       msg.len = 3;
+       msg.buf = buffer;
+
+       i2c_xfer(&dev->i2c_bus[0].i2c_adap, &msg, 1);
+}
+
+
+int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value)
+{
+    struct i2c_client *client = &bus->i2c_client;
+    int retval = 0;
+    int v = 0;
+    u8 addr[2] = {0, 0};
+    u8 buf[4] = {0,0,0,0};
+       
+    struct i2c_msg msgs[2]={
+          {
+             .addr = client->addr,
+             .flags = 0,
+             .len = 2,
+             .buf = addr,
+          }, {
+             .addr = client->addr,
+             .flags = I2C_M_RD,
+             .len = 4,
+             .buf = buf,
+          }
+    };
+
+
+    addr[0] = (reg_addr>>8);
+    addr[1] = (reg_addr & 0xff);
+    msgs[0].addr = 0x44;
+    msgs[1].addr = 0x44;
+
+    retval = i2c_xfer(client->adapter, msgs, 2);
+
+    v = (buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0];
+    *value = v;
+
+    return v; 
+}
+
+
+int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value)
+{
+    struct i2c_client *client = &bus->i2c_client;
+    int retval = 0; 
+    u8 buf[6] = {0, 0, 0, 0, 0, 0};
+
+    struct i2c_msg msgs[1]={
+          {
+             .addr = client->addr,
+             .flags = 0,
+             .len = 6,
+             .buf = buf,
+          }
+    };
+
+
+    buf[0] = reg_addr>>8;
+    buf[1] = reg_addr & 0xff;
+    buf[5] = (value>>24) & 0xff;
+    buf[4] = (value>>16) & 0xff;
+    buf[3] = (value>>8) & 0xff;
+    buf[2] = value & 0xff;
+    client->flags = 0;
+    msgs[0].addr = 0x44;
+
+    retval = i2c_xfer(client->adapter, msgs, 1);
+
+    return retval;
+}
+
diff --git a/drivers/staging/cx25821/cx25821-medusa-defines.h b/drivers/staging/cx25821/cx25821-medusa-defines.h
new file mode 100644 (file)
index 0000000..75161e4
--- /dev/null
@@ -0,0 +1,51 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+#ifndef _MEDUSA_DEF_H_\r
+#define _MEDUSA_DEF_H_
+\r
+// Video deocder that we supported\r
+#define VDEC_A         0\r
+#define VDEC_B         1\r
+#define VDEC_C         2\r
+#define VDEC_D         3\r
+#define VDEC_E         4\r
+#define VDEC_F         5\r
+#define VDEC_G         6\r
+#define VDEC_H         7\r
+\r
+//#define AUTO_SWITCH_BIT[]  = { 8, 9, 10, 11, 12, 13, 14, 15 };
+\r
+// The following bit position enables automatic source switching for decoder A-H.\r
+// Display index per camera.\r
+//#define VDEC_INDEX[] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7};
+\r
+// Select input bit to video decoder A-H.\r
+//#define CH_SRC_SEL_BIT[] = {24, 25, 26, 27, 28, 29, 30, 31};
+\r
+// end of display sequence\r
+#define END_OF_SEQ                                     0xF;\r
+\r
+// registry string size\r
+#define MAX_REGISTRY_SZ                                        40;\r
+\r
+#endif
diff --git a/drivers/staging/cx25821/cx25821-medusa-reg.h b/drivers/staging/cx25821/cx25821-medusa-reg.h
new file mode 100644 (file)
index 0000000..b877cd2
--- /dev/null
@@ -0,0 +1,456 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+#ifndef __MEDUSA_REGISTERS__\r
+#define __MEDUSA_REGISTERS__\r
+\r
+// Serial Slave Registers\r
+#define        HOST_REGISTER1                          0x0000\r
+#define        HOST_REGISTER2                          0x0001\r
+\r
+// Chip Configuration Registers\r
+#define        CHIP_CTRL                                       0x0100\r
+#define        AFE_AB_CTRL                                     0x0104\r
+#define        AFE_CD_CTRL                                     0x0108\r
+#define        AFE_EF_CTRL                                     0x010C\r
+#define        AFE_GH_CTRL                                     0x0110\r
+#define        DENC_AB_CTRL                            0x0114\r
+#define        BYP_AB_CTRL                                     0x0118\r
+#define        MON_A_CTRL                                      0x011C\r
+#define        DISP_SEQ_A                                      0x0120\r
+#define        DISP_SEQ_B                                      0x0124\r
+#define        DISP_AB_CNT                                     0x0128\r
+#define        DISP_CD_CNT                                     0x012C\r
+#define        DISP_EF_CNT                                     0x0130\r
+#define        DISP_GH_CNT                                     0x0134\r
+#define        DISP_IJ_CNT                                     0x0138\r
+#define        PIN_OE_CTRL                                     0x013C\r
+#define        PIN_SPD_CTRL                            0x0140\r
+#define        PIN_SPD_CTRL2                           0x0144\r
+#define        IRQ_STAT_CTRL                           0x0148\r
+#define        POWER_CTRL_AB                           0x014C\r
+#define        POWER_CTRL_CD                           0x0150\r
+#define        POWER_CTRL_EF                           0x0154\r
+#define        POWER_CTRL_GH                           0x0158\r
+#define        TUNE_CTRL                                       0x015C\r
+#define        BIAS_CTRL                                       0x0160\r
+#define        AFE_AB_DIAG_CTRL                        0x0164\r
+#define        AFE_CD_DIAG_CTRL                        0x0168\r
+#define        AFE_EF_DIAG_CTRL                        0x016C\r
+#define        AFE_GH_DIAG_CTRL                        0x0170\r
+#define        PLL_AB_DIAG_CTRL                        0x0174\r
+#define        PLL_CD_DIAG_CTRL                        0x0178\r
+#define        PLL_EF_DIAG_CTRL                        0x017C\r
+#define        PLL_GH_DIAG_CTRL                        0x0180\r
+#define        TEST_CTRL                                       0x0184\r
+#define        BIST_STAT                                       0x0188\r
+#define        BIST_STAT2                                      0x018C\r
+#define        BIST_VID_PLL_AB_STAT            0x0190\r
+#define        BIST_VID_PLL_CD_STAT            0x0194\r
+#define        BIST_VID_PLL_EF_STAT            0x0198\r
+#define        BIST_VID_PLL_GH_STAT            0x019C\r
+#define        DLL_DIAG_CTRL                           0x01A0\r
+#define        DEV_CH_ID_CTRL                          0x01A4\r
+#define        ABIST_CTRL_STATUS                       0x01A8\r
+#define        ABIST_FREQ                                      0x01AC\r
+#define        ABIST_GOERT_SHIFT                       0x01B0\r
+#define        ABIST_COEF12                            0x01B4\r
+#define        ABIST_COEF34                            0x01B8\r
+#define        ABIST_COEF56                            0x01BC\r
+#define        ABIST_COEF7_SNR                         0x01C0\r
+#define        ABIST_ADC_CAL                           0x01C4\r
+#define        ABIST_BIN1_VGA0                         0x01C8\r
+#define        ABIST_BIN2_VGA1                         0x01CC\r
+#define        ABIST_BIN3_VGA2                         0x01D0\r
+#define        ABIST_BIN4_VGA3                         0x01D4\r
+#define        ABIST_BIN5_VGA4                         0x01D8\r
+#define        ABIST_BIN6_VGA5                         0x01DC\r
+#define        ABIST_BIN7_VGA6                         0x0x1E0\r
+#define        ABIST_CLAMP_A                           0x0x1E4\r
+#define        ABIST_CLAMP_B                           0x0x1E8\r
+#define        ABIST_CLAMP_C                           0x01EC\r
+#define        ABIST_CLAMP_D                           0x01F0\r
+#define        ABIST_CLAMP_E                           0x01F4\r
+#define        ABIST_CLAMP_F                           0x01F8\r
+\r
+//             Digital Video Encoder A Registers\r
+#define        DENC_A_REG_1                                    0x0200\r
+#define        DENC_A_REG_2                                    0x0204\r
+#define        DENC_A_REG_3                                    0x0208\r
+#define        DENC_A_REG_4                                    0x020C\r
+#define        DENC_A_REG_5                                    0x0210\r
+#define        DENC_A_REG_6                                    0x0214\r
+#define        DENC_A_REG_7                                    0x0218\r
+#define        DENC_A_REG_8                                    0x021C\r
+\r
+//     Digital Video Encoder B Registers\r
+#define        DENC_B_REG_1                                    0x0300\r
+#define        DENC_B_REG_2                                    0x0304\r
+#define        DENC_B_REG_3                                    0x0308\r
+#define        DENC_B_REG_4                                    0x030C\r
+#define        DENC_B_REG_5                                    0x0310\r
+#define        DENC_B_REG_6                                    0x0314\r
+#define        DENC_B_REG_7                                    0x0318\r
+#define        DENC_B_REG_8                                    0x031C\r
+\r
+//             Video Decoder A Registers\r
+#define        MODE_CTRL                                               0x1000\r
+#define        OUT_CTRL1                                               0x1004\r
+#define        OUT_CTRL_NS                                             0x1008\r
+#define        GEN_STAT                                                0x100C\r
+#define        INT_STAT_MASK                                   0x1010\r
+#define        LUMA_CTRL                                               0x1014\r
+#define        CHROMA_CTRL                                             0x1018\r
+#define        CRUSH_CTRL                                              0x101C\r
+#define        HORIZ_TIM_CTRL                                  0x1020\r
+#define        VERT_TIM_CTRL                                   0x1024\r
+#define        MISC_TIM_CTRL                                   0x1028\r
+#define        FIELD_COUNT                                             0x102C\r
+#define        HSCALE_CTRL                                             0x1030\r
+#define        VSCALE_CTRL                                             0x1034\r
+#define        MAN_VGA_CTRL                                    0x1038\r
+#define        MAN_AGC_CTRL                                    0x103C\r
+#define        DFE_CTRL1                                               0x1040\r
+#define        DFE_CTRL2                                               0x1044\r
+#define        DFE_CTRL3                                               0x1048\r
+#define        PLL_CTRL                                                0x104C\r
+#define        PLL_CTRL_FAST                                   0x1050\r
+#define        HTL_CTRL                                                0x1054\r
+#define        SRC_CFG                                                 0x1058\r
+#define        SC_STEP_SIZE                                    0x105C\r
+#define        SC_CONVERGE_CTRL                                0x1060\r
+#define        SC_LOOP_CTRL                                    0x1064\r
+#define        COMB_2D_HFS_CFG                                 0x1068\r
+#define        COMB_2D_HFD_CFG                                 0x106C\r
+#define        COMB_2D_LF_CFG                                  0x1070\r
+#define        COMB_2D_BLEND                                   0x1074\r
+#define        COMB_MISC_CTRL                                  0x1078\r
+#define        COMB_FLAT_THRESH_CTRL                   0x107C\r
+#define        COMB_TEST                                               0x1080\r
+#define        BP_MISC_CTRL                                    0x1084\r
+#define        VCR_DET_CTRL                                    0x1088\r
+#define        NOISE_DET_CTRL                                  0x108C\r
+#define        COMB_FLAT_NOISE_CTRL                    0x1090\r
+#define        VERSION                                                 0x11F8\r
+#define        SOFT_RST_CTRL                                   0x11FC\r
+\r
+//     Video Decoder B Registers\r
+#define        VDEC_B_MODE_CTRL                                0x1200\r
+#define        VDEC_B_OUT_CTRL1                                0x1204\r
+#define        VDEC_B_OUT_CTRL_NS                              0x1208\r
+#define        VDEC_B_GEN_STAT                                 0x120C\r
+#define        VDEC_B_INT_STAT_MASK                    0x1210\r
+#define        VDEC_B_LUMA_CTRL                                0x1214\r
+#define        VDEC_B_CHROMA_CTRL                              0x1218\r
+#define        VDEC_B_CRUSH_CTRL                               0x121C\r
+#define        VDEC_B_HORIZ_TIM_CTRL                   0x1220\r
+#define        VDEC_B_VERT_TIM_CTRL                    0x1224\r
+#define        VDEC_B_MISC_TIM_CTRL                    0x1228\r
+#define        VDEC_B_FIELD_COUNT                              0x122C\r
+#define        VDEC_B_HSCALE_CTRL                              0x1230\r
+#define        VDEC_B_VSCALE_CTRL                              0x1234\r
+#define        VDEC_B_MAN_VGA_CTRL                             0x1238\r
+#define        VDEC_B_MAN_AGC_CTRL                             0x123C\r
+#define        VDEC_B_DFE_CTRL1                                0x1240\r
+#define        VDEC_B_DFE_CTRL2                                0x1244\r
+#define        VDEC_B_DFE_CTRL3                                0x1248\r
+#define        VDEC_B_PLL_CTRL                                 0x124C\r
+#define        VDEC_B_PLL_CTRL_FAST                    0x1250\r
+#define        VDEC_B_HTL_CTRL                                 0x1254\r
+#define        VDEC_B_SRC_CFG                                  0x1258\r
+#define        VDEC_B_SC_STEP_SIZE                             0x125C\r
+#define        VDEC_B_SC_CONVERGE_CTRL                 0x1260\r
+#define        VDEC_B_SC_LOOP_CTRL                             0x1264\r
+#define        VDEC_B_COMB_2D_HFS_CFG                  0x1268\r
+#define        VDEC_B_COMB_2D_HFD_CFG                  0x126C\r
+#define        VDEC_B_COMB_2D_LF_CFG                   0x1270\r
+#define        VDEC_B_COMB_2D_BLEND                    0x1274\r
+#define        VDEC_B_COMB_MISC_CTRL                   0x1278\r
+#define        VDEC_B_COMB_FLAT_THRESH_CTRL    0x127C\r
+#define        VDEC_B_COMB_TEST                                0x1280\r
+#define        VDEC_B_BP_MISC_CTRL                             0x1284\r
+#define        VDEC_B_VCR_DET_CTRL                             0x1288\r
+#define        VDEC_B_NOISE_DET_CTRL                   0x128C\r
+#define        VDEC_B_COMB_FLAT_NOISE_CTRL             0x1290\r
+#define        VDEC_B_VERSION                                  0x13F8\r
+#define        VDEC_B_SOFT_RST_CTRL                    0x13FC\r
+\r
+// Video Decoder C Registers\r
+#define        VDEC_C_MODE_CTRL                                0x1400\r
+#define        VDEC_C_OUT_CTRL1                                0x1404\r
+#define        VDEC_C_OUT_CTRL_NS                              0x1408\r
+#define        VDEC_C_GEN_STAT                                 0x140C\r
+#define        VDEC_C_INT_STAT_MASK                    0x1410\r
+#define VDEC_C_LUMA_CTRL                               0x1414\r
+#define VDEC_C_CHROMA_CTRL                             0x1418\r
+#define        VDEC_C_CRUSH_CTRL                               0x141C\r
+#define        VDEC_C_HORIZ_TIM_CTRL                   0x1420\r
+#define        VDEC_C_VERT_TIM_CTRL                    0x1424\r
+#define        VDEC_C_MISC_TIM_CTRL                    0x1428\r
+#define        VDEC_C_FIELD_COUNT                              0x142C\r
+#define        VDEC_C_HSCALE_CTRL                              0x1430\r
+#define        VDEC_C_VSCALE_CTRL                              0x1434\r
+#define        VDEC_C_MAN_VGA_CTRL                             0x1438\r
+#define        VDEC_C_MAN_AGC_CTRL                             0x143C\r
+#define        VDEC_C_DFE_CTRL1                                0x1440\r
+#define        VDEC_C_DFE_CTRL2                                0x1444\r
+#define        VDEC_C_DFE_CTRL3                                0x1448\r
+#define        VDEC_C_PLL_CTRL                                 0x144C\r
+#define        VDEC_C_PLL_CTRL_FAST                    0x1450\r
+#define        VDEC_C_HTL_CTRL                                 0x1454\r
+#define        VDEC_C_SRC_CFG                                  0x1458\r
+#define        VDEC_C_SC_STEP_SIZE                             0x145C\r
+#define        VDEC_C_SC_CONVERGE_CTRL                 0x1460\r
+#define        VDEC_C_SC_LOOP_CTRL                             0x1464\r
+#define        VDEC_C_COMB_2D_HFS_CFG                  0x1468\r
+#define        VDEC_C_COMB_2D_HFD_CFG                  0x146C\r
+#define        VDEC_C_COMB_2D_LF_CFG                   0x1470\r
+#define        VDEC_C_COMB_2D_BLEND                    0x1474\r
+#define        VDEC_C_COMB_MISC_CTRL                   0x1478\r
+#define        VDEC_C_COMB_FLAT_THRESH_CTRL    0x147C\r
+#define        VDEC_C_COMB_TEST                                0x1480\r
+#define        VDEC_C_BP_MISC_CTRL                             0x1484\r
+#define        VDEC_C_VCR_DET_CTRL                             0x1488\r
+#define        VDEC_C_NOISE_DET_CTRL                   0x148C\r
+#define        VDEC_C_COMB_FLAT_NOISE_CTRL             0x1490\r
+#define        VDEC_C_VERSION                                  0x15F8\r
+#define        VDEC_C_SOFT_RST_CTRL                    0x15FC\r
+\r
+// Video Decoder D Registers\r
+#define VDEC_D_MODE_CTRL                               0x1600\r
+#define VDEC_D_OUT_CTRL1                               0x1604\r
+#define VDEC_D_OUT_CTRL_NS                             0x1608\r
+#define VDEC_D_GEN_STAT                                        0x160C\r
+#define VDEC_D_INT_STAT_MASK                   0x1610\r
+#define VDEC_D_LUMA_CTRL                               0x1614\r
+#define VDEC_D_CHROMA_CTRL                             0x1618\r
+#define VDEC_D_CRUSH_CTRL                              0x161C\r
+#define VDEC_D_HORIZ_TIM_CTRL                  0x1620\r
+#define VDEC_D_VERT_TIM_CTRL                   0x1624\r
+#define VDEC_D_MISC_TIM_CTRL                   0x1628\r
+#define VDEC_D_FIELD_COUNT                             0x162C\r
+#define VDEC_D_HSCALE_CTRL                             0x1630\r
+#define VDEC_D_VSCALE_CTRL                             0x1634\r
+#define VDEC_D_MAN_VGA_CTRL                            0x1638\r
+#define VDEC_D_MAN_AGC_CTRL                            0x163C\r
+#define VDEC_D_DFE_CTRL1                               0x1640\r
+#define VDEC_D_DFE_CTRL2                               0x1644\r
+#define VDEC_D_DFE_CTRL3                               0x1648\r
+#define VDEC_D_PLL_CTRL                                        0x164C\r
+#define VDEC_D_PLL_CTRL_FAST                   0x1650\r
+#define VDEC_D_HTL_CTRL                                        0x1654\r
+#define VDEC_D_SRC_CFG                                 0x1658\r
+#define VDEC_D_SC_STEP_SIZE                            0x165C\r
+#define VDEC_D_SC_CONVERGE_CTRL                        0x1660\r
+#define VDEC_D_SC_LOOP_CTRL                            0x1664\r
+#define VDEC_D_COMB_2D_HFS_CFG                 0x1668\r
+#define VDEC_D_COMB_2D_HFD_CFG                 0x166C\r
+#define VDEC_D_COMB_2D_LF_CFG                  0x1670\r
+#define VDEC_D_COMB_2D_BLEND                   0x1674\r
+#define VDEC_D_COMB_MISC_CTRL                  0x1678\r
+#define VDEC_D_COMB_FLAT_THRESH_CTRL   0x167C\r
+#define VDEC_D_COMB_TEST                               0x1680\r
+#define VDEC_D_BP_MISC_CTRL                            0x1684\r
+#define VDEC_D_VCR_DET_CTRL                            0x1688\r
+#define VDEC_D_NOISE_DET_CTRL                  0x168C\r
+#define VDEC_D_COMB_FLAT_NOISE_CTRL            0x1690\r
+#define VDEC_D_VERSION                                 0x17F8\r
+#define VDEC_D_SOFT_RST_CTRL                   0x17FC\r
+\r
+// Video Decoder E Registers\r
+#define        VDEC_E_MODE_CTRL                                0x1800\r
+#define        VDEC_E_OUT_CTRL1                                0x1804\r
+#define        VDEC_E_OUT_CTRL_NS                              0x1808\r
+#define        VDEC_E_GEN_STAT                                 0x180C\r
+#define        VDEC_E_INT_STAT_MASK                    0x1810\r
+#define        VDEC_E_LUMA_CTRL                                0x1814\r
+#define        VDEC_E_CHROMA_CTRL                              0x1818\r
+#define        VDEC_E_CRUSH_CTRL                               0x181C\r
+#define        VDEC_E_HORIZ_TIM_CTRL                   0x1820\r
+#define        VDEC_E_VERT_TIM_CTRL                    0x1824\r
+#define        VDEC_E_MISC_TIM_CTRL                    0x1828\r
+#define        VDEC_E_FIELD_COUNT                              0x182C\r
+#define        VDEC_E_HSCALE_CTRL                              0x1830\r
+#define        VDEC_E_VSCALE_CTRL                              0x1834\r
+#define        VDEC_E_MAN_VGA_CTRL                             0x1838\r
+#define        VDEC_E_MAN_AGC_CTRL                             0x183C\r
+#define        VDEC_E_DFE_CTRL1                                0x1840\r
+#define        VDEC_E_DFE_CTRL2                                0x1844\r
+#define        VDEC_E_DFE_CTRL3                                0x1848\r
+#define        VDEC_E_PLL_CTRL                                 0x184C\r
+#define        VDEC_E_PLL_CTRL_FAST                    0x1850\r
+#define        VDEC_E_HTL_CTRL                                 0x1854\r
+#define        VDEC_E_SRC_CFG                                  0x1858\r
+#define        VDEC_E_SC_STEP_SIZE                             0x185C\r
+#define        VDEC_E_SC_CONVERGE_CTRL                 0x1860\r
+#define        VDEC_E_SC_LOOP_CTRL                             0x1864\r
+#define        VDEC_E_COMB_2D_HFS_CFG                  0x1868\r
+#define        VDEC_E_COMB_2D_HFD_CFG                  0x186C\r
+#define        VDEC_E_COMB_2D_LF_CFG                   0x1870\r
+#define        VDEC_E_COMB_2D_BLEND                    0x1874\r
+#define        VDEC_E_COMB_MISC_CTRL                   0x1878\r
+#define        VDEC_E_COMB_FLAT_THRESH_CTRL    0x187C\r
+#define        VDEC_E_COMB_TEST                                0x1880\r
+#define        VDEC_E_BP_MISC_CTRL                             0x1884\r
+#define        VDEC_E_VCR_DET_CTRL                             0x1888\r
+#define        VDEC_E_NOISE_DET_CTRL                   0x188C\r
+#define        VDEC_E_COMB_FLAT_NOISE_CTRL             0x1890\r
+#define        VDEC_E_VERSION                                  0x19F8\r
+#define        VDEC_E_SOFT_RST_CTRL                    0x19FC\r
+\r
+// Video Decoder F Registers\r
+#define        VDEC_F_MODE_CTRL                                0x1A00\r
+#define        VDEC_F_OUT_CTRL1                                0x1A04\r
+#define        VDEC_F_OUT_CTRL_NS                              0x1A08\r
+#define        VDEC_F_GEN_STAT                                 0x1A0C\r
+#define        VDEC_F_INT_STAT_MASK                    0x1A10\r
+#define        VDEC_F_LUMA_CTRL                                0x1A14\r
+#define        VDEC_F_CHROMA_CTRL                              0x1A18\r
+#define        VDEC_F_CRUSH_CTRL                               0x1A1C\r
+#define        VDEC_F_HORIZ_TIM_CTRL                   0x1A20\r
+#define        VDEC_F_VERT_TIM_CTRL                    0x1A24\r
+#define        VDEC_F_MISC_TIM_CTRL                    0x1A28\r
+#define        VDEC_F_FIELD_COUNT                              0x1A2C\r
+#define        VDEC_F_HSCALE_CTRL                              0x1A30\r
+#define        VDEC_F_VSCALE_CTRL                              0x1A34\r
+#define        VDEC_F_MAN_VGA_CTRL                             0x1A38\r
+#define        VDEC_F_MAN_AGC_CTRL                             0x1A3C\r
+#define        VDEC_F_DFE_CTRL1                                0x1A40\r
+#define        VDEC_F_DFE_CTRL2                                0x1A44\r
+#define        VDEC_F_DFE_CTRL3                                0x1A48\r
+#define        VDEC_F_PLL_CTRL                                 0x1A4C\r
+#define        VDEC_F_PLL_CTRL_FAST                    0x1A50\r
+#define        VDEC_F_HTL_CTRL                                 0x1A54\r
+#define        VDEC_F_SRC_CFG                                  0x1A58\r
+#define        VDEC_F_SC_STEP_SIZE                             0x1A5C\r
+#define        VDEC_F_SC_CONVERGE_CTRL                 0x1A60\r
+#define        VDEC_F_SC_LOOP_CTRL                             0x1A64\r
+#define        VDEC_F_COMB_2D_HFS_CFG                  0x1A68\r
+#define        VDEC_F_COMB_2D_HFD_CFG                  0x1A6C\r
+#define        VDEC_F_COMB_2D_LF_CFG                   0x1A70\r
+#define        VDEC_F_COMB_2D_BLEND                    0x1A74\r
+#define        VDEC_F_COMB_MISC_CTRL                   0x1A78\r
+#define        VDEC_F_COMB_FLAT_THRESH_CTRL    0x1A7C\r
+#define        VDEC_F_COMB_TEST                                0x1A80\r
+#define        VDEC_F_BP_MISC_CTRL                             0x1A84\r
+#define        VDEC_F_VCR_DET_CTRL                             0x1A88\r
+#define        VDEC_F_NOISE_DET_CTRL                   0x1A8C\r
+#define        VDEC_F_COMB_FLAT_NOISE_CTRL             0x1A90\r
+#define        VDEC_F_VERSION                                  0x1BF8\r
+#define        VDEC_F_SOFT_RST_CTRL                    0x1BFC\r
+\r
+// Video Decoder G Registers\r
+#define        VDEC_G_MODE_CTRL                                0x1C00\r
+#define        VDEC_G_OUT_CTRL1                                0x1C04\r
+#define        VDEC_G_OUT_CTRL_NS                              0x1C08\r
+#define        VDEC_G_GEN_STAT                                 0x1C0C\r
+#define        VDEC_G_INT_STAT_MASK                    0x1C10\r
+#define        VDEC_G_LUMA_CTRL                                0x1C14\r
+#define        VDEC_G_CHROMA_CTRL                              0x1C18\r
+#define        VDEC_G_CRUSH_CTRL                               0x1C1C\r
+#define        VDEC_G_HORIZ_TIM_CTRL                   0x1C20\r
+#define        VDEC_G_VERT_TIM_CTRL                    0x1C24\r
+#define        VDEC_G_MISC_TIM_CTRL                    0x1C28\r
+#define        VDEC_G_FIELD_COUNT                              0x1C2C\r
+#define        VDEC_G_HSCALE_CTRL                              0x1C30\r
+#define        VDEC_G_VSCALE_CTRL                              0x1C34\r
+#define        VDEC_G_MAN_VGA_CTRL                             0x1C38\r
+#define        VDEC_G_MAN_AGC_CTRL                             0x1C3C\r
+#define        VDEC_G_DFE_CTRL1                                0x1C40\r
+#define        VDEC_G_DFE_CTRL2                                0x1C44\r
+#define        VDEC_G_DFE_CTRL3                                0x1C48\r
+#define        VDEC_G_PLL_CTRL                                 0x1C4C\r
+#define        VDEC_G_PLL_CTRL_FAST                    0x1C50\r
+#define        VDEC_G_HTL_CTRL                                 0x1C54\r
+#define        VDEC_G_SRC_CFG                                  0x1C58\r
+#define        VDEC_G_SC_STEP_SIZE                             0x1C5C\r
+#define        VDEC_G_SC_CONVERGE_CTRL                 0x1C60\r
+#define        VDEC_G_SC_LOOP_CTRL                             0x1C64\r
+#define        VDEC_G_COMB_2D_HFS_CFG                  0x1C68\r
+#define        VDEC_G_COMB_2D_HFD_CFG                  0x1C6C\r
+#define        VDEC_G_COMB_2D_LF_CFG                   0x1C70\r
+#define        VDEC_G_COMB_2D_BLEND                    0x1C74\r
+#define        VDEC_G_COMB_MISC_CTRL                   0x1C78\r
+#define        VDEC_G_COMB_FLAT_THRESH_CTRL    0x1C7C\r
+#define        VDEC_G_COMB_TEST                                0x1C80\r
+#define        VDEC_G_BP_MISC_CTRL                             0x1C84\r
+#define        VDEC_G_VCR_DET_CTRL                             0x1C88\r
+#define        VDEC_G_NOISE_DET_CTRL                   0x1C8C\r
+#define        VDEC_G_COMB_FLAT_NOISE_CTRL             0x1C90\r
+#define        VDEC_G_VERSION                                  0x1DF8\r
+#define        VDEC_G_SOFT_RST_CTRL                    0x1DFC\r
+\r
+//             Video Decoder H Registers\r
+#define        VDEC_H_MODE_CTRL                                0x1E00\r
+#define        VDEC_H_OUT_CTRL1                                0x1E04\r
+#define        VDEC_H_OUT_CTRL_NS                              0x1E08\r
+#define        VDEC_H_GEN_STAT                                 0x1E0C\r
+#define        VDEC_H_INT_STAT_MASK                    0x1E1E\r
+#define        VDEC_H_LUMA_CTRL                                0x1E14\r
+#define        VDEC_H_CHROMA_CTRL                              0x1E18\r
+#define        VDEC_H_CRUSH_CTRL                               0x1E1C\r
+#define        VDEC_H_HORIZ_TIM_CTRL                   0x1E20\r
+#define        VDEC_H_VERT_TIM_CTRL                    0x1E24\r
+#define        VDEC_H_MISC_TIM_CTRL                    0x1E28\r
+#define        VDEC_H_FIELD_COUNT                              0x1E2C\r
+#define        VDEC_H_HSCALE_CTRL                              0x1E30\r
+#define        VDEC_H_VSCALE_CTRL                              0x1E34\r
+#define        VDEC_H_MAN_VGA_CTRL                             0x1E38\r
+#define        VDEC_H_MAN_AGC_CTRL                             0x1E3C\r
+#define        VDEC_H_DFE_CTRL1                                0x1E40\r
+#define        VDEC_H_DFE_CTRL2                                0x1E44\r
+#define        VDEC_H_DFE_CTRL3                                0x1E48\r
+#define        VDEC_H_PLL_CTRL                                 0x1E4C\r
+#define        VDEC_H_PLL_CTRL_FAST                    0x1E50\r
+#define        VDEC_H_HTL_CTRL                                 0x1E54\r
+#define        VDEC_H_SRC_CFG                                  0x1E58\r
+#define        VDEC_H_SC_STEP_SIZE                             0x1E5C\r
+#define        VDEC_H_SC_CONVERGE_CTRL                 0x1E60\r
+#define        VDEC_H_SC_LOOP_CTRL                             0x1E64\r
+#define        VDEC_H_COMB_2D_HFS_CFG                  0x1E68\r
+#define        VDEC_H_COMB_2D_HFD_CFG                  0x1E6C\r
+#define        VDEC_H_COMB_2D_LF_CFG                   0x1E70\r
+#define        VDEC_H_COMB_2D_BLEND                    0x1E74\r
+#define        VDEC_H_COMB_MISC_CTRL                   0x1E78\r
+#define        VDEC_H_COMB_FLAT_THRESH_CTRL    0x1E7C\r
+#define        VDEC_H_COMB_TEST                                0x1E80\r
+#define        VDEC_H_BP_MISC_CTRL                             0x1E84\r
+#define        VDEC_H_VCR_DET_CTRL                             0x1E88\r
+#define        VDEC_H_NOISE_DET_CTRL                   0x1E8C\r
+#define        VDEC_H_COMB_FLAT_NOISE_CTRL             0x1E90\r
+#define        VDEC_H_VERSION                                  0x1FF8\r
+#define        VDEC_H_SOFT_RST_CTRL                    0x1FFC\r
+\r
+//*****************************************************************************\r
+// LUMA_CTRL register fields           \r
+#define VDEC_A_BRITE_CTRL                              0x1014\r
+#define VDEC_A_CNTRST_CTRL                     0x1015\r
+#define VDEC_A_PEAK_SEL                        0x1016\r
+\r
+//*****************************************************************************\r
+// CHROMA_CTRL register fields      \r
+#define VDEC_A_USAT_CTRL                       0x1018\r
+#define VDEC_A_VSAT_CTRL                       0x1019\r
+#define VDEC_A_HUE_CTRL                        0x101A\r
+\r
+\r
+#endif
diff --git a/drivers/staging/cx25821/cx25821-medusa-video.c b/drivers/staging/cx25821/cx25821-medusa-video.c
new file mode 100644 (file)
index 0000000..6225f10
--- /dev/null
@@ -0,0 +1,769 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 "cx25821.h"
+#include "cx25821-medusa-video.h"
+#include "cx25821-biffuncs.h"
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+//medusa_enable_bluefield_output()
+//
+// Enable the generation of blue filed output if no video
+//
+static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel, int enable)
+{
+    int ret_val = 1;
+    u32 value = 0;
+    u32 tmp = 0;
+    int out_ctrl = OUT_CTRL1;
+    int out_ctrl_ns = OUT_CTRL_NS;
+
+        
+    switch (channel)
+    {
+        default:
+        case VDEC_A: 
+            break;
+        case VDEC_B: 
+            out_ctrl = VDEC_B_OUT_CTRL1;
+            out_ctrl_ns = VDEC_B_OUT_CTRL_NS;
+            break;
+        case VDEC_C:
+            out_ctrl = VDEC_C_OUT_CTRL1;
+            out_ctrl_ns = VDEC_C_OUT_CTRL_NS;
+            break;
+        case VDEC_D:
+            out_ctrl = VDEC_D_OUT_CTRL1;
+            out_ctrl_ns = VDEC_D_OUT_CTRL_NS;
+            break;
+        case VDEC_E:
+            out_ctrl = VDEC_E_OUT_CTRL1;
+            out_ctrl_ns = VDEC_E_OUT_CTRL_NS;
+            return;
+        case VDEC_F:
+            out_ctrl = VDEC_F_OUT_CTRL1;
+            out_ctrl_ns = VDEC_F_OUT_CTRL_NS;
+            return;
+        case VDEC_G:
+            out_ctrl = VDEC_G_OUT_CTRL1;
+            out_ctrl_ns = VDEC_G_OUT_CTRL_NS;
+            return;
+        case VDEC_H: 
+            out_ctrl = VDEC_H_OUT_CTRL1;
+            out_ctrl_ns = VDEC_H_OUT_CTRL_NS;
+            return;
+    }
+
+    value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp);
+    value &= 0xFFFFFF7F;        // clear BLUE_FIELD_EN
+    if (enable)
+        value |= 0x00000080;    // set BLUE_FIELD_EN    
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value);
+
+    value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp);
+    value &= 0xFFFFFF7F;
+    if (enable)
+        value |= 0x00000080;    // set BLUE_FIELD_EN    
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value);
+}
+
+
+static int medusa_initialize_ntsc(struct cx25821_dev *dev)
+{
+    int ret_val = 0;
+    int i = 0;
+    u32 value = 0;
+    u32 tmp = 0;
+
+    mutex_lock(&dev->lock);
+
+    
+    for (i=0; i < MAX_DECODERS; i++)
+    {
+        // set video format NTSC-M
+        value = cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), &tmp);
+        value &= 0xFFFFFFF0;
+        value |= 0x10001;     // enable the fast locking mode bit[16]
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), value);
+        
+        // resolution NTSC 720x480 
+        value = cx25821_i2c_read(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), &tmp);
+        value &= 0x00C00C00;
+        value |= 0x612D0074;
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), value);
+        
+        value = cx25821_i2c_read(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), &tmp);
+        value &= 0x00C00C00;
+        value |= 0x1C1E001A;        // vblank_cnt + 2 to get camera ID
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), value);
+
+        // chroma subcarrier step size
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], SC_STEP_SIZE+(0x200*i), 0x43E00000);
+        
+        // enable VIP optional active
+        value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), &tmp);
+        value &= 0xFFFBFFFF;
+        value |= 0x00040000;        
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), value);
+
+        // enable VIP optional active (VIP_OPT_AL) for direct output.
+        value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), &tmp);
+        value &= 0xFFFBFFFF;
+        value |= 0x00040000;        
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), value);
+
+        // clear VPRES_VERT_EN bit, fixes the chroma run away problem
+        // when the input switching rate < 16 fields
+        // 
+        value = cx25821_i2c_read(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), &tmp);
+        value = setBitAtPos(value, 14);    // disable special play detection
+        value = clearBitAtPos(value, 15);  
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), value);
+
+        // set vbi_gate_en to 0 
+        value = cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), &tmp);
+        value = clearBitAtPos(value, 29);
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), value);
+        
+        // Enable the generation of blue field output if no video
+        medusa_enable_bluefield_output(dev, i, 1);
+    }
+
+
+    for (i=0; i < MAX_ENCODERS; i++)
+    {
+        // NTSC hclock 
+        value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), &tmp);
+        value &= 0xF000FC00;
+        value |= 0x06B402D0;
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), value);
+
+        // burst begin and burst end
+        value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), &tmp);
+        value &= 0xFF000000;
+        value |= 0x007E9054;
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), value);
+
+        value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), &tmp);
+        value &= 0xFC00FE00;
+        value |= 0x00EC00F0;
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), value);
+
+        // set NTSC vblank, no phase alternation, 7.5 IRE pedestal
+        value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), &tmp);
+        value &= 0x00FCFFFF;
+        value |= 0x13020000;    
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), value);
+
+        value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), &tmp);
+        value &= 0xFFFF0000;
+        value |= 0x0000E575;
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), value);
+
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_6+(0x100*i), 0x009A89C1);
+
+        // Subcarrier Increment
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_7+(0x100*i), 0x21F07C1F);
+    }
+
+
+    //set picture resolutions
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);  //0 - 720
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);  //0 - 480
+
+    // set Bypass input format to NTSC 525 lines
+    value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+    value |= 0x00080200;
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+    mutex_unlock(&dev->lock);
+
+    return ret_val;
+}
+
+
+static int medusa_PALCombInit(struct cx25821_dev *dev, int dec)
+{
+    int ret_val = -1;
+    u32 value = 0, tmp = 0;
+   
+    // Setup for 2D threshold
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG+(0x200*dec), 0x20002861);
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG+(0x200*dec), 0x20002861); 
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG+(0x200*dec), 0x200A1023); 
+   
+    // Setup flat chroma and luma thresholds 
+    value = cx25821_i2c_read(&dev->i2c_bus[0], COMB_FLAT_THRESH_CTRL+(0x200*dec), &tmp);
+    value &= 0x06230000;        
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_FLAT_THRESH_CTRL+(0x200*dec), value);
+      
+    // set comb 2D blend 
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND+(0x200*dec), 0x210F0F0F);
+   
+    // COMB MISC CONTROL  
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL+(0x200*dec), 0x41120A7F);
+    
+    return ret_val;
+}
+
+
+static int medusa_initialize_pal(struct cx25821_dev *dev)
+{
+    int ret_val = 0;
+    int i = 0;
+    u32 value = 0;
+    u32 tmp = 0;
+
+    mutex_lock(&dev->lock);
+    
+    for (i=0; i < MAX_DECODERS; i++)
+    {
+        // set video format PAL-BDGHI       
+        value = cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), &tmp);
+        value &= 0xFFFFFFF0;
+        value |= 0x10004;     // enable the fast locking mode bit[16]
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL+(0x200*i), value);
+        
+        
+        // resolution PAL 720x576       
+        value = cx25821_i2c_read(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), &tmp);
+        value &= 0x00C00C00;
+        value |= 0x632D007D;
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HORIZ_TIM_CTRL+(0x200*i), value);
+        
+        // vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24      
+        value = cx25821_i2c_read(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), &tmp);
+        value &= 0x00C00C00;
+        value |= 0x28240026;        // vblank_cnt + 2 to get camera ID
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VERT_TIM_CTRL+(0x200*i), value);
+        
+        // chroma subcarrier step size
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], SC_STEP_SIZE+(0x200*i), 0x5411E2D0);
+
+        // enable VIP optional active
+        value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), &tmp);
+        value &= 0xFFFBFFFF;
+        value |= 0x00040000;            
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL_NS+(0x200*i), value);
+        
+        // enable VIP optional active (VIP_OPT_AL) for direct output.
+        value = cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), &tmp);
+        value &= 0xFFFBFFFF;
+        value |= 0x00040000;        
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1+(0x200*i), value);
+        
+        // clear VPRES_VERT_EN bit, fixes the chroma run away problem
+        // when the input switching rate < 16 fields
+        value = cx25821_i2c_read(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), &tmp);
+        value = setBitAtPos(value, 14);    // disable special play detection
+        value = clearBitAtPos(value, 15);
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MISC_TIM_CTRL+(0x200*i), value);
+        
+        // set vbi_gate_en to 0         
+        value = cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), &tmp);
+        value = clearBitAtPos(value, 29);
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1+(0x200*i), value);
+
+        medusa_PALCombInit(dev, i);
+         
+        // Enable the generation of blue field output if no video
+        medusa_enable_bluefield_output(dev, i, 1);
+    }
+
+    
+    for (i=0; i < MAX_ENCODERS; i++)        
+    {
+        // PAL hclock 
+        value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), &tmp);
+        value &= 0xF000FC00;
+        value |= 0x06C002D0;
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_1+(0x100*i), value);
+
+        // burst begin and burst end        
+        value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), &tmp);
+        value &= 0xFF000000;
+        value |= 0x007E9754;
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_2+(0x100*i), value);
+
+        // hblank and vactive       
+        value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), &tmp);
+        value &= 0xFC00FE00;
+        value |= 0x00FC0120;
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_3+(0x100*i), value);
+
+        // set PAL vblank, phase alternation, 0 IRE pedestal        
+        value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), &tmp);
+        value &= 0x00FCFFFF;
+        value |= 0x14010000;
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4+(0x100*i), value);
+        
+    
+        value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), &tmp);
+        value &= 0xFFFF0000;
+        value |= 0x0000F078;
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_5+(0x100*i), value);
+
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_6+(0x100*i), 0x00A493CF);
+
+        // Subcarrier Increment     
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_7+(0x100*i), 0x2A098ACB);
+    }
+          
+
+    //set picture resolutions   
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);  //0 - 720
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);  //0 - 576
+    
+    // set Bypass input format to PAL 625 lines 
+    value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+    value &= 0xFFF7FDFF;
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+    
+    mutex_unlock(&dev->lock);
+
+    return ret_val;
+}
+
+
+int medusa_set_videostandard(struct cx25821_dev *dev)
+{
+    int status = STATUS_SUCCESS;
+    u32 value = 0, tmp = 0;
+
+    
+    if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+    {
+        status = medusa_initialize_pal(dev);
+    }
+    else
+    {
+        status = medusa_initialize_ntsc(dev);
+    }
+        
+    // Enable DENC_A output
+    value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp);
+    value = setBitAtPos(value, 4);
+    status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value);
+    
+    // Enable DENC_B output
+    value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp);
+    value = setBitAtPos(value, 4);
+    status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value);
+    
+    return status;
+}
+
+
+void medusa_set_resolution(struct cx25821_dev *dev, int width, int decoder_select)
+{
+    int decoder = 0;
+    int decoder_count = 0;
+    int ret_val = 0;
+    u32 hscale = 0x0;
+    u32 vscale = 0x0; 
+    const int MAX_WIDTH = 720;
+
+    mutex_lock(&dev->lock);
+
+    // validate the width - cannot be negative
+    if (width > MAX_WIDTH)
+    {
+        printk("cx25821 %s() : width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH \n", __func__, width, MAX_WIDTH);
+        width = MAX_WIDTH;
+    } 
+             
+    if( decoder_select <= 7 && decoder_select >= 0 )
+    {
+        decoder = decoder_select;
+        decoder_count = decoder_select + 1;
+    }
+    else
+    {
+        decoder = 0;
+        decoder_count = _num_decoders;
+    }
+    
+    
+    switch( width )
+    {
+        case 320:
+            hscale = 0x13E34B;
+            vscale = 0x0;
+            break;
+
+        case 352:
+            hscale = 0x10A273;
+            vscale = 0x0;
+            break;
+
+        case 176:
+            hscale = 0x3115B2;
+            vscale = 0x1E00;
+            break;
+
+        case 160:
+            hscale = 0x378D84;
+            vscale = 0x1E00;
+            break;
+
+        default:            //720
+            hscale = 0x0;
+            vscale = 0x0;
+            break;  
+    } 
+
+    for( ; decoder < decoder_count; decoder++)
+    {
+        // write scaling values for each decoder
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL+(0x200*decoder), hscale);
+        ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL+(0x200*decoder), vscale);
+    }
+
+    mutex_unlock(&dev->lock);
+}
+
+static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, int duration)
+{
+    int ret_val = 0;
+    u32 fld_cnt = 0;
+    u32 tmp = 0;
+    u32 disp_cnt_reg = DISP_AB_CNT;
+    
+    mutex_lock(&dev->lock);
+
+    // no support 
+    if (decoder < VDEC_A && decoder > VDEC_H)
+    {
+        mutex_unlock(&dev->lock);
+        return;
+    }
+
+    switch (decoder)
+    {
+        default:
+            break;
+        case VDEC_C: 
+        case VDEC_D:
+            disp_cnt_reg = DISP_CD_CNT;
+            break;
+        case VDEC_E:
+        case VDEC_F: 
+            disp_cnt_reg = DISP_EF_CNT;
+            break;
+        case VDEC_G: 
+        case VDEC_H:
+            disp_cnt_reg = DISP_GH_CNT;
+            break;
+    }
+
+    _display_field_cnt[decoder] = duration;
+
+    // update hardware
+    fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp);
+    
+    if (!(decoder % 2)) // EVEN decoder
+    {
+        fld_cnt &= 0xFFFF0000;
+        fld_cnt |= duration;
+    }
+    else
+    {
+        fld_cnt &= 0x0000FFFF;
+        fld_cnt |= ((u32)duration) << 16;
+    }
+
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt);
+    
+    mutex_unlock(&dev->lock);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Map to Medusa register setting
+static int mapM(
+    int  srcMin,
+    int  srcMax,
+    int  srcVal,
+    int  dstMin,
+    int  dstMax,
+    int* dstVal
+)
+{
+    int numerator;
+    int denominator;
+    int quotient;
+
+    if((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax))
+    {
+        return -1;
+    }
+
+    // This is the overall expression used:
+    // *dstVal = (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin;
+    // but we need to account for rounding so below we use the modulus
+    // operator to find the remainder and increment if necessary.
+    numerator   = (srcVal - srcMin)*(dstMax - dstMin);
+    denominator = srcMax - srcMin;
+    quotient    = numerator/denominator;
+
+    if(2 * ( numerator % denominator ) >= denominator)
+    {
+        quotient++;
+    }
+
+    *dstVal = quotient + dstMin;
+
+    return 0;
+}
+
+static unsigned long convert_to_twos(long numeric, unsigned long bits_len)
+{
+    unsigned char temp;
+
+    if (numeric >= 0)
+        return numeric;
+    else
+    {
+        temp = ~(abs(numeric) & 0xFF);
+        temp += 1;
+        return temp;
+    }
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder)
+{
+    int ret_val = 0;
+    int value = 0;
+    u32 val = 0, tmp = 0;
+
+    mutex_lock(&dev->lock);
+    if((brightness > VIDEO_PROCAMP_MAX) || (brightness < VIDEO_PROCAMP_MIN))
+    {
+        mutex_unlock(&dev->lock);
+        return -1;
+    }
+    ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness, SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
+    value = convert_to_twos(value, 8);
+    val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_BRITE_CTRL+(0x200*decoder), &tmp);
+    val &= 0xFFFFFF00;
+    ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_BRITE_CTRL+(0x200*decoder), val | value);
+    mutex_unlock(&dev->lock);
+    return ret_val;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder)
+{
+    int ret_val = 0;
+    int value = 0;
+    u32 val = 0, tmp = 0;
+
+    mutex_lock(&dev->lock);
+    
+    if((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN))
+    {
+        mutex_unlock(&dev->lock);
+        return -1;
+    }
+
+    ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast, UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+    val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_CNTRST_CTRL+(0x200*decoder), &tmp);
+    val &= 0xFFFFFF00;
+    ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_CNTRST_CTRL+(0x200*decoder), val | value);
+
+    mutex_unlock(&dev->lock);
+    return ret_val;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder)
+{
+    int ret_val = 0;
+    int value = 0;
+    u32 val = 0, tmp = 0;
+
+    mutex_lock(&dev->lock);
+    
+    if((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN))
+    {
+        mutex_unlock(&dev->lock);
+        return -1;
+    }
+
+    ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
+    
+    value = convert_to_twos(value, 8);
+    val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_HUE_CTRL+(0x200*decoder), &tmp);
+    val &= 0xFFFFFF00;
+
+    ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_HUE_CTRL+(0x200*decoder), val | value);
+
+    mutex_unlock(&dev->lock);
+    return ret_val;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder)
+{
+    int ret_val = 0;
+    int value = 0;
+    u32 val = 0, tmp = 0;
+    
+    mutex_lock(&dev->lock);
+    
+    if((saturation > VIDEO_PROCAMP_MAX) || (saturation < VIDEO_PROCAMP_MIN))
+    {
+        mutex_unlock(&dev->lock);
+        return -1;
+    }
+
+    ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation, UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+    
+    val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_USAT_CTRL+(0x200*decoder), &tmp);
+    val &= 0xFFFFFF00;                          
+    ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_USAT_CTRL+(0x200*decoder), val | value);
+
+    val = cx25821_i2c_read(&dev->i2c_bus[0], VDEC_A_VSAT_CTRL+(0x200*decoder), &tmp);
+    val &= 0xFFFFFF00; 
+    ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], VDEC_A_VSAT_CTRL+(0x200*decoder), val | value);
+    
+    mutex_unlock(&dev->lock);
+    return ret_val;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Program the display sequence and monitor output.
+//
+int medusa_video_init(struct cx25821_dev *dev)
+{
+    u32 value = 0, tmp = 0;
+    int ret_val = 0;
+    int i=0;
+    
+    mutex_lock(&dev->lock);
+    
+    _num_decoders = dev->_max_num_decoders;
+    
+    
+    // disable Auto source selection on all video decoders  
+    value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
+    value &= 0xFFFFF0FF;
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
+    
+    if (ret_val < 0)
+    {
+        mutex_unlock(&dev->lock);
+        return -EINVAL;
+    }
+    
+    // Turn off Master source switch enable
+    value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
+    value &= 0xFFFFFFDF;
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
+    
+    if (ret_val < 0)
+    {
+        mutex_unlock(&dev->lock);
+        return -EINVAL;
+    }
+
+    mutex_unlock(&dev->lock);
+
+    for (i=0; i < _num_decoders; i++)
+    {
+        medusa_set_decoderduration(dev, i, _display_field_cnt[i]);
+    }
+    
+    mutex_lock(&dev->lock);
+
+    // Select monitor as DENC A input, power up the DAC 
+    value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp);
+    value &= 0xFF70FF70;
+    value |= 0x00090008;    // set en_active 
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value);
+    
+    if (ret_val < 0)
+    {
+        mutex_unlock(&dev->lock);
+        return -EINVAL;
+    }
+
+    // enable input is VIP/656
+    value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+    value |= 0x00040100;    // enable VIP
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+    
+    if (ret_val < 0)
+    {
+        mutex_unlock(&dev->lock);
+        return -EINVAL;
+    }
+
+    // select AFE clock to output mode 
+    value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
+    value &= 0x83FFFFFF;
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, value | 0x10000000);        
+    
+    if (ret_val < 0)
+    {
+        mutex_unlock(&dev->lock);
+        return -EINVAL;
+    }
+
+    // Turn on all of the data out and control output pins.
+    value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp);
+    value &= 0xFEF0FE00;
+    if (_num_decoders == MAX_DECODERS)
+    {
+        // Note: The octal board does not support control pins(bit16-19).
+        // These bits are ignored in the octal board.
+        value |= 0x010001F8;             // disable VDEC A-C port, default to Mobilygen Interface
+    }
+    else
+    {
+        value |= 0x010F0108;             // disable VDEC A-C port, default to Mobilygen Interface
+    }
+    
+    value |= 7;
+    ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value);
+    if (ret_val < 0)
+    {
+        mutex_unlock(&dev->lock);
+        return -EINVAL;
+    }
+
+    mutex_unlock(&dev->lock);
+
+    
+    ret_val = medusa_set_videostandard(dev);
+
+    
+    if (ret_val < 0)
+    {
+        mutex_unlock(&dev->lock);
+        return -EINVAL;
+    }   
+    
+    return 1;
+}
diff --git a/drivers/staging/cx25821/cx25821-medusa-video.h b/drivers/staging/cx25821/cx25821-medusa-video.h
new file mode 100644 (file)
index 0000000..0ba3cc7
--- /dev/null
@@ -0,0 +1,51 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+#ifndef _MEDUSA_VIDEO_H\r
+#define _MEDUSA_VIDEO_H\r
+\r
+#include "cx25821-medusa-defines.h"
+
+
+// Color control constants 
+#define VIDEO_PROCAMP_MIN                 0
+#define VIDEO_PROCAMP_MAX                 10000
+#define UNSIGNED_BYTE_MIN                 0
+#define UNSIGNED_BYTE_MAX                 0xFF
+#define SIGNED_BYTE_MIN                   -128
+#define SIGNED_BYTE_MAX                   127
+
+// Default video color settings
+#define SHARPNESS_DEFAULT                 50
+#define SATURATION_DEFAULT              5000
+#define BRIGHTNESS_DEFAULT              6200
+#define CONTRAST_DEFAULT                5000
+#define HUE_DEFAULT                     5000
+
+
+unsigned short                 _num_decoders;
+unsigned short                 _num_cameras;
+
+unsigned int            _video_standard;
+int                                        _display_field_cnt[MAX_DECODERS];
+\r
+#endif
diff --git a/drivers/staging/cx25821/cx25821-reg.h b/drivers/staging/cx25821/cx25821-reg.h
new file mode 100644 (file)
index 0000000..82f4f16
--- /dev/null
@@ -0,0 +1,1609 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+
+#ifndef __CX25821_REGISTERS__
+#define __CX25821_REGISTERS__
+
+/* Risc Instructions */
+#define RISC_CNT_INC    0x00010000
+#define RISC_CNT_RESET  0x00030000
+#define RISC_IRQ1               0x01000000
+#define RISC_IRQ2               0x02000000
+#define RISC_EOL                0x04000000
+#define RISC_SOL                0x08000000
+#define RISC_WRITE              0x10000000
+#define RISC_SKIP               0x20000000
+#define RISC_JUMP               0x70000000
+#define RISC_SYNC               0x80000000
+#define RISC_RESYNC             0x80008000
+#define RISC_READ               0x90000000
+#define RISC_WRITERM    0xB0000000
+#define RISC_WRITECM    0xC0000000
+#define RISC_WRITECR    0xD0000000
+#define RISC_WRITEC             0x50000000
+#define RISC_READC              0xA0000000
+
+#define RISC_SYNC_ODD           0x00000000
+#define RISC_SYNC_EVEN          0x00000200
+#define RISC_SYNC_ODD_VBI       0x00000006
+#define RISC_SYNC_EVEN_VBI      0x00000207
+#define RISC_NOOP                       0xF0000000
+\r
+//*****************************************************************************\r
+// ASB SRAM
+//*****************************************************************************
+#define  TX_SRAM                   0x000000      // Transmit SRAM
+
+//*****************************************************************************
+#define  RX_RAM                    0x010000      // Receive SRAM
+
+//*****************************************************************************
+// Application Layer (AL)
+//*****************************************************************************
+#define  DEV_CNTRL2                0x040000      // Device control
+#define  FLD_RUN_RISC              0x00000020
+
+//*****************************************************************************
+#define  PCI_INT_MSK               0x040010      // PCI interrupt mask
+#define  PCI_INT_STAT              0x040014      // PCI interrupt status
+#define  PCI_INT_MSTAT             0x040018      // PCI interrupt masked status
+#define  FLD_HAMMERHEAD_INT        (1 << 27)
+#define  FLD_UART_INT              (1 << 26)
+#define  FLD_IRQN_INT              (1 << 25)
+#define  FLD_TM_INT                (1 << 28)
+#define  FLD_I2C_3_RACK            (1 << 27)
+#define  FLD_I2C_3_INT             (1 << 26)
+#define  FLD_I2C_2_RACK            (1 << 25)
+#define  FLD_I2C_2_INT             (1 << 24)
+#define  FLD_I2C_1_RACK            (1 << 23)
+#define  FLD_I2C_1_INT             (1 << 22)
+
+#define  FLD_APB_DMA_BERR_INT      (1 << 21)
+#define  FLD_AL_WR_BERR_INT        (1 << 20)
+#define  FLD_AL_RD_BERR_INT        (1 << 19)
+#define  FLD_RISC_WR_BERR_INT      (1 << 18)
+#define  FLD_RISC_RD_BERR_INT      (1 << 17)
+
+#define  FLD_VID_I_INT             (1 << 8)
+#define  FLD_VID_H_INT             (1 << 7)
+#define  FLD_VID_G_INT             (1 << 6)
+#define  FLD_VID_F_INT             (1 << 5)
+#define  FLD_VID_E_INT             (1 << 4)
+#define  FLD_VID_D_INT             (1 << 3)
+#define  FLD_VID_C_INT             (1 << 2)
+#define  FLD_VID_B_INT             (1 << 1)
+#define  FLD_VID_A_INT             (1 << 0)
+
+//*****************************************************************************
+#define  VID_A_INT_MSK             0x040020      // Video A interrupt mask
+#define  VID_A_INT_STAT            0x040024      // Video A interrupt status
+#define  VID_A_INT_MSTAT           0x040028      // Video A interrupt masked status
+#define  VID_A_INT_SSTAT           0x04002C      // Video A interrupt set status
+
+//*****************************************************************************
+#define  VID_B_INT_MSK             0x040030      // Video B interrupt mask
+#define  VID_B_INT_STAT            0x040034      // Video B interrupt status
+#define  VID_B_INT_MSTAT           0x040038      // Video B interrupt masked status
+#define  VID_B_INT_SSTAT           0x04003C      // Video B interrupt set status
+
+//*****************************************************************************\r
+#define  VID_C_INT_MSK             0x040040      // Video C interrupt mask\r
+#define  VID_C_INT_STAT            0x040044      // Video C interrupt status\r
+#define  VID_C_INT_MSTAT           0x040048      // Video C interrupt masked status\r
+#define  VID_C_INT_SSTAT           0x04004C      // Video C interrupt set status\r
+\r
+//*****************************************************************************\r
+#define  VID_D_INT_MSK             0x040050      // Video D interrupt mask\r
+#define  VID_D_INT_STAT            0x040054      // Video D interrupt status\r
+#define  VID_D_INT_MSTAT           0x040058      // Video D interrupt masked status\r
+#define  VID_D_INT_SSTAT           0x04005C      // Video D interrupt set status\r
+\r
+//*****************************************************************************\r
+#define  VID_E_INT_MSK             0x040060      // Video E interrupt mask\r
+#define  VID_E_INT_STAT            0x040064      // Video E interrupt status\r
+#define  VID_E_INT_MSTAT           0x040068      // Video E interrupt masked status\r
+#define  VID_E_INT_SSTAT           0x04006C      // Video E interrupt set status\r
+\r
+//*****************************************************************************\r
+#define  VID_F_INT_MSK             0x040070      // Video F interrupt mask\r
+#define  VID_F_INT_STAT            0x040074      // Video F interrupt status\r
+#define  VID_F_INT_MSTAT           0x040078      // Video F interrupt masked status\r
+#define  VID_F_INT_SSTAT           0x04007C      // Video F interrupt set status\r
+\r
+//*****************************************************************************\r
+#define  VID_G_INT_MSK             0x040080      // Video G interrupt mask\r
+#define  VID_G_INT_STAT            0x040084      // Video G interrupt status\r
+#define  VID_G_INT_MSTAT           0x040088      // Video G interrupt masked status\r
+#define  VID_G_INT_SSTAT           0x04008C      // Video G interrupt set status\r
+\r
+//*****************************************************************************\r
+#define  VID_H_INT_MSK             0x040090      // Video H interrupt mask\r
+#define  VID_H_INT_STAT            0x040094      // Video H interrupt status\r
+#define  VID_H_INT_MSTAT           0x040098      // Video H interrupt masked status\r
+#define  VID_H_INT_SSTAT           0x04009C      // Video H interrupt set status\r
+\r
+//*****************************************************************************\r
+#define  VID_I_INT_MSK             0x0400A0      // Video I interrupt mask\r
+#define  VID_I_INT_STAT            0x0400A4      // Video I interrupt status\r
+#define  VID_I_INT_MSTAT           0x0400A8      // Video I interrupt masked status\r
+#define  VID_I_INT_SSTAT           0x0400AC      // Video I interrupt set status\r
+\r
+//*****************************************************************************\r
+#define  VID_J_INT_MSK             0x0400B0      // Video J interrupt mask\r
+#define  VID_J_INT_STAT            0x0400B4      // Video J interrupt status\r
+#define  VID_J_INT_MSTAT           0x0400B8      // Video J interrupt masked status\r
+#define  VID_J_INT_SSTAT           0x0400BC      // Video J interrupt set status\r
+\r
+#define  FLD_VID_SRC_OPC_ERR       0x00020000\r
+#define  FLD_VID_DST_OPC_ERR       0x00010000\r
+#define  FLD_VID_SRC_SYNC          0x00002000\r
+#define  FLD_VID_DST_SYNC          0x00001000\r
+#define  FLD_VID_SRC_UF            0x00000200\r
+#define  FLD_VID_DST_OF            0x00000100\r
+#define  FLD_VID_SRC_RISC2         0x00000020\r
+#define  FLD_VID_DST_RISC2         0x00000010\r
+#define  FLD_VID_SRC_RISC1         0x00000002\r
+#define  FLD_VID_DST_RISC1         0x00000001\r
+#define  FLD_VID_SRC_ERRORS            FLD_VID_SRC_OPC_ERR | FLD_VID_SRC_SYNC | FLD_VID_SRC_UF\r
+#define  FLD_VID_DST_ERRORS            FLD_VID_DST_OPC_ERR | FLD_VID_DST_SYNC | FLD_VID_DST_OF\r
+\r
+\r
+//*****************************************************************************\r
+#define  AUD_A_INT_MSK             0x0400C0      // Audio Int interrupt mask\r
+#define  AUD_A_INT_STAT            0x0400C4      // Audio Int interrupt status\r
+#define  AUD_A_INT_MSTAT           0x0400C8      // Audio Int interrupt masked status\r
+#define  AUD_A_INT_SSTAT           0x0400CC      // Audio Int interrupt set status\r
+\r
+//*****************************************************************************\r
+#define  AUD_B_INT_MSK             0x0400D0      // Audio Int interrupt mask\r
+#define  AUD_B_INT_STAT            0x0400D4      // Audio Int interrupt status\r
+#define  AUD_B_INT_MSTAT           0x0400D8      // Audio Int interrupt masked status\r
+#define  AUD_B_INT_SSTAT           0x0400DC      // Audio Int interrupt set status\r
+\r
+//*****************************************************************************\r
+#define  AUD_C_INT_MSK             0x0400E0      // Audio Int interrupt mask\r
+#define  AUD_C_INT_STAT            0x0400E4      // Audio Int interrupt status\r
+#define  AUD_C_INT_MSTAT           0x0400E8      // Audio Int interrupt masked status\r
+#define  AUD_C_INT_SSTAT           0x0400EC      // Audio Int interrupt set status\r
+\r
+//*****************************************************************************\r
+#define  AUD_D_INT_MSK             0x0400F0      // Audio Int interrupt mask\r
+#define  AUD_D_INT_STAT            0x0400F4      // Audio Int interrupt status\r
+#define  AUD_D_INT_MSTAT           0x0400F8      // Audio Int interrupt masked status\r
+#define  AUD_D_INT_SSTAT           0x0400FC      // Audio Int interrupt set status\r
+\r
+//*****************************************************************************\r
+#define  AUD_E_INT_MSK             0x040100      // Audio Int interrupt mask\r
+#define  AUD_E_INT_STAT            0x040104      // Audio Int interrupt status\r
+#define  AUD_E_INT_MSTAT           0x040108      // Audio Int interrupt masked status\r
+#define  AUD_E_INT_SSTAT           0x04010C      // Audio Int interrupt set status\r
+
+#define  FLD_AUD_SRC_OPC_ERR       0x00020000\r
+#define  FLD_AUD_DST_OPC_ERR       0x00010000\r
+#define  FLD_AUD_SRC_SYNC          0x00002000\r
+#define  FLD_AUD_DST_SYNC          0x00001000\r
+#define  FLD_AUD_SRC_OF            0x00000200\r
+#define  FLD_AUD_DST_OF            0x00000100\r
+#define  FLD_AUD_SRC_RISCI2        0x00000020\r
+#define  FLD_AUD_DST_RISCI2        0x00000010\r
+#define  FLD_AUD_SRC_RISCI1        0x00000002\r
+#define  FLD_AUD_DST_RISCI1        0x00000001\r
+\r
+//*****************************************************************************\r
+#define  MBIF_A_INT_MSK             0x040110      // MBIF Int interrupt mask\r
+#define  MBIF_A_INT_STAT            0x040114      // MBIF Int interrupt status\r
+#define  MBIF_A_INT_MSTAT           0x040118      // MBIF Int interrupt masked status\r
+#define  MBIF_A_INT_SSTAT           0x04011C      // MBIF Int interrupt set status\r
+\r
+//*****************************************************************************\r
+#define  MBIF_B_INT_MSK             0x040120      // MBIF Int interrupt mask\r
+#define  MBIF_B_INT_STAT            0x040124      // MBIF Int interrupt status\r
+#define  MBIF_B_INT_MSTAT           0x040128      // MBIF Int interrupt masked status\r
+#define  MBIF_B_INT_SSTAT           0x04012C      // MBIF Int interrupt set status\r
+\r
+#define  FLD_MBIF_DST_OPC_ERR       0x00010000\r
+#define  FLD_MBIF_DST_SYNC          0x00001000\r
+#define  FLD_MBIF_DST_OF            0x00000100\r
+#define  FLD_MBIF_DST_RISCI2        0x00000010\r
+#define  FLD_MBIF_DST_RISCI1        0x00000001\r
+\r
+//*****************************************************************************\r
+#define  AUD_EXT_INT_MSK           0x040060      // Audio Ext interrupt mask\r
+#define  AUD_EXT_INT_STAT          0x040064      // Audio Ext interrupt status\r
+#define  AUD_EXT_INT_MSTAT         0x040068      // Audio Ext interrupt masked status\r
+#define  AUD_EXT_INT_SSTAT         0x04006C      // Audio Ext interrupt set status\r
+#define  FLD_AUD_EXT_OPC_ERR       0x00010000\r
+#define  FLD_AUD_EXT_SYNC          0x00001000\r
+#define  FLD_AUD_EXT_OF            0x00000100\r
+#define  FLD_AUD_EXT_RISCI2        0x00000010\r
+#define  FLD_AUD_EXT_RISCI1        0x00000001\r
+\r
+\r
+//*****************************************************************************\r
+#define  GPIO_LO                   0x110010      // Lower  of GPIO pins [31:0]\r
+#define  GPIO_HI                   0x110014      // Upper WORD  of GPIO pins [47:31]\r
+\r
+#define  GPIO_LO_OE                0x110018      // Lower  of GPIO output enable [31:0]\r
+#define  GPIO_HI_OE                0x11001C      // Upper word  of GPIO output enable [47:32]\r
+\r
+#define  GPIO_LO_INT_MSK           0x11003C      // GPIO interrupt mask\r
+#define  GPIO_LO_INT_STAT          0x110044      // GPIO interrupt status\r
+#define  GPIO_LO_INT_MSTAT         0x11004C      // GPIO interrupt masked status\r
+#define  GPIO_LO_ISM_SNS           0x110054      // GPIO interrupt sensitivity\r
+#define  GPIO_LO_ISM_POL           0x11005C      // GPIO interrupt polarity\r
+\r
+#define  GPIO_HI_INT_MSK           0x110040      // GPIO interrupt mask\r
+#define  GPIO_HI_INT_STAT          0x110048      // GPIO interrupt status\r
+#define  GPIO_HI_INT_MSTAT         0x110050      // GPIO interrupt masked status\r
+#define  GPIO_HI_ISM_SNS           0x110058      // GPIO interrupt sensitivity\r
+#define  GPIO_HI_ISM_POL           0x110060      // GPIO interrupt polarity\r
+\r
+#define  FLD_GPIO43_INT            (1 << 11)\r
+#define  FLD_GPIO42_INT            (1 << 10)\r
+#define  FLD_GPIO41_INT            (1 << 9)\r
+#define  FLD_GPIO40_INT            (1 << 8)\r
+\r
+#define  FLD_GPIO9_INT             (1 << 9)\r
+#define  FLD_GPIO8_INT             (1 << 8)\r
+#define  FLD_GPIO7_INT             (1 << 7)\r
+#define  FLD_GPIO6_INT             (1 << 6)\r
+#define  FLD_GPIO5_INT             (1 << 5)\r
+#define  FLD_GPIO4_INT             (1 << 4)\r
+#define  FLD_GPIO3_INT             (1 << 3)\r
+#define  FLD_GPIO2_INT             (1 << 2)\r
+#define  FLD_GPIO1_INT             (1 << 1)\r
+#define  FLD_GPIO0_INT             (1 << 0)\r
+\r
+//*****************************************************************************\r
+#define  TC_REQ                    0x040090      // Rider PCI Express traFFic class request\r
+\r
+//*****************************************************************************\r
+#define  TC_REQ_SET                0x040094      // Rider PCI Express traFFic class request set\r
+\r
+\r
+//*****************************************************************************\r
+// Rider\r
+//*****************************************************************************\r
+\r
+// PCI Compatible Header\r
+//*****************************************************************************\r
+#define  RDR_CFG0                  0x050000\r
+#define  RDR_VENDOR_DEVICE_ID_CFG  0x050000\r
+\r
+//*****************************************************************************\r
+#define  RDR_CFG1                  0x050004\r
+\r
+//*****************************************************************************\r
+#define  RDR_CFG2                  0x050008\r
+\r
+//*****************************************************************************\r
+#define  RDR_CFG3                  0x05000C\r
+\r
+//*****************************************************************************\r
+#define  RDR_CFG4                  0x050010\r
+\r
+//*****************************************************************************\r
+#define  RDR_CFG5                  0x050014\r
+\r
+//*****************************************************************************\r
+#define  RDR_CFG6                  0x050018\r
+\r
+//*****************************************************************************\r
+#define  RDR_CFG7                  0x05001C\r
+\r
+//*****************************************************************************\r
+#define  RDR_CFG8                  0x050020\r
+\r
+//*****************************************************************************\r
+#define  RDR_CFG9                  0x050024\r
+\r
+//*****************************************************************************\r
+#define  RDR_CFGA                  0x050028\r
+\r
+//*****************************************************************************\r
+#define  RDR_CFGB                  0x05002C\r
+#define  RDR_SUSSYSTEM_ID_CFG      0x05002C\r
+\r
+//*****************************************************************************\r
+#define  RDR_CFGC                  0x050030\r
+\r
+//*****************************************************************************\r
+#define  RDR_CFGD                  0x050034\r
+\r
+//*****************************************************************************\r
+#define  RDR_CFGE                  0x050038\r
+\r
+//*****************************************************************************\r
+#define  RDR_CFGF                  0x05003C\r
+\r
+//*****************************************************************************\r
+// PCI-Express Capabilities\r
+//*****************************************************************************\r
+#define  RDR_PECAP                 0x050040\r
+\r
+//*****************************************************************************\r
+#define  RDR_PEDEVCAP              0x050044\r
+\r
+//*****************************************************************************\r
+#define  RDR_PEDEVSC               0x050048\r
+\r
+//*****************************************************************************\r
+#define  RDR_PELINKCAP             0x05004C\r
+\r
+//*****************************************************************************\r
+#define  RDR_PELINKSC              0x050050\r
+\r
+//*****************************************************************************\r
+#define  RDR_PMICAP                0x050080\r
+\r
+//*****************************************************************************\r
+#define  RDR_PMCSR                 0x050084\r
+\r
+//*****************************************************************************\r
+#define  RDR_VPDCAP                0x050090\r
+\r
+//*****************************************************************************\r
+#define  RDR_VPDDATA               0x050094\r
+\r
+//*****************************************************************************\r
+#define  RDR_MSICAP                0x0500A0\r
+\r
+//*****************************************************************************\r
+#define  RDR_MSIARL                0x0500A4\r
+\r
+//*****************************************************************************\r
+#define  RDR_MSIARU                0x0500A8\r
+\r
+//*****************************************************************************\r
+#define  RDR_MSIDATA               0x0500AC\r
+\r
+//*****************************************************************************\r
+// PCI Express Extended Capabilities\r
+//*****************************************************************************\r
+#define  RDR_AERXCAP               0x050100\r
+\r
+//*****************************************************************************\r
+#define  RDR_AERUESTA              0x050104\r
+\r
+//*****************************************************************************\r
+#define  RDR_AERUEMSK              0x050108\r
+\r
+//*****************************************************************************\r
+#define  RDR_AERUESEV              0x05010C\r
+\r
+//*****************************************************************************\r
+#define  RDR_AERCESTA              0x050110\r
+\r
+//*****************************************************************************\r
+#define  RDR_AERCEMSK              0x050114\r
+\r
+//*****************************************************************************\r
+#define  RDR_AERCC                 0x050118\r
+\r
+//*****************************************************************************\r
+#define  RDR_AERHL0                0x05011C\r
+\r
+//*****************************************************************************\r
+#define  RDR_AERHL1                0x050120\r
+\r
+//*****************************************************************************\r
+#define  RDR_AERHL2                0x050124\r
+\r
+//*****************************************************************************\r
+#define  RDR_AERHL3                0x050128\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCXCAP                0x050200\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCCAP1                0x050204\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCCAP2                0x050208\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCSC                  0x05020C\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCR0_CAP              0x050210\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCR0_CTRL             0x050214\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCR0_STAT             0x050218\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCR1_CAP              0x05021C\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCR1_CTRL             0x050220\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCR1_STAT             0x050224\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCR2_CAP              0x050228\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCR2_CTRL             0x05022C\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCR2_STAT             0x050230\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCR3_CAP              0x050234\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCR3_CTRL             0x050238\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCR3_STAT             0x05023C\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCARB0                0x050240\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCARB1                0x050244\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCARB2                0x050248\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCARB3                0x05024C\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCARB4                0x050250\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCARB5                0x050254\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCARB6                0x050258\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCARB7                0x05025C\r
+\r
+//*****************************************************************************\r
+#define  RDR_RDRSTAT0              0x050300\r
+\r
+//*****************************************************************************\r
+#define  RDR_RDRSTAT1              0x050304\r
+\r
+//*****************************************************************************\r
+#define  RDR_RDRCTL0               0x050308\r
+\r
+//*****************************************************************************\r
+#define  RDR_RDRCTL1               0x05030C\r
+\r
+//*****************************************************************************\r
+// Transaction Layer Registers\r
+//*****************************************************************************\r
+#define  RDR_TLSTAT0               0x050310\r
+\r
+//*****************************************************************************\r
+#define  RDR_TLSTAT1               0x050314\r
+\r
+//*****************************************************************************\r
+#define  RDR_TLCTL0                0x050318\r
+#define  FLD_CFG_UR_CPL_MODE       0x00000040\r
+#define  FLD_CFG_CORR_ERR_QUITE    0x00000020\r
+#define  FLD_CFG_RCB_CK_EN         0x00000010\r
+#define  FLD_CFG_BNDRY_CK_EN       0x00000008\r
+#define  FLD_CFG_BYTE_EN_CK_EN     0x00000004\r
+#define  FLD_CFG_RELAX_ORDER_MSK   0x00000002\r
+#define  FLD_CFG_TAG_ORDER_EN      0x00000001\r
+\r
+//*****************************************************************************\r
+#define  RDR_TLCTL1                0x05031C\r
+\r
+//*****************************************************************************\r
+#define  RDR_REQRCAL               0x050320\r
+\r
+//*****************************************************************************\r
+#define  RDR_REQRCAU               0x050324\r
+\r
+//*****************************************************************************\r
+#define  RDR_REQEPA                0x050328\r
+\r
+//*****************************************************************************\r
+#define  RDR_REQCTRL               0x05032C\r
+\r
+//*****************************************************************************\r
+#define  RDR_REQSTAT               0x050330\r
+\r
+//*****************************************************************************\r
+#define  RDR_TL_TEST               0x050334\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCR01_CTL             0x050348\r
+\r
+//*****************************************************************************\r
+#define  RDR_VCR23_CTL             0x05034C\r
+\r
+//*****************************************************************************\r
+#define  RDR_RX_VCR0_FC            0x050350\r
+\r
+//*****************************************************************************\r
+#define  RDR_RX_VCR1_FC            0x050354\r
+\r
+//*****************************************************************************\r
+#define  RDR_RX_VCR2_FC            0x050358\r
+\r
+//*****************************************************************************\r
+#define  RDR_RX_VCR3_FC            0x05035C\r
+\r
+//*****************************************************************************\r
+// Data Link Layer Registers\r
+//*****************************************************************************\r
+#define  RDR_DLLSTAT               0x050360\r
+\r
+//*****************************************************************************\r
+#define  RDR_DLLCTRL               0x050364\r
+\r
+//*****************************************************************************\r
+#define  RDR_REPLAYTO              0x050368\r
+\r
+//*****************************************************************************\r
+#define  RDR_ACKLATTO              0x05036C\r
+\r
+//*****************************************************************************\r
+// MAC Layer Registers\r
+//*****************************************************************************\r
+#define  RDR_MACSTAT0              0x050380\r
+\r
+//*****************************************************************************\r
+#define  RDR_MACSTAT1              0x050384\r
+\r
+//*****************************************************************************\r
+#define  RDR_MACCTRL0              0x050388\r
+\r
+//*****************************************************************************\r
+#define  RDR_MACCTRL1              0x05038C\r
+\r
+//*****************************************************************************\r
+#define  RDR_MACCTRL2              0x050390\r
+\r
+//*****************************************************************************\r
+#define  RDR_MAC_LB_DATA           0x050394\r
+\r
+//*****************************************************************************\r
+#define  RDR_L0S_EXIT_LAT          0x050398\r
+\r
+//*****************************************************************************\r
+// DMAC\r
+//*****************************************************************************\r
+#define  DMA1_PTR1                 0x100000      // DMA Current Ptr : Ch#1\r
+\r
+//*****************************************************************************\r
+#define  DMA2_PTR1                 0x100004      // DMA Current Ptr : Ch#2\r
+\r
+//*****************************************************************************\r
+#define  DMA3_PTR1                 0x100008      // DMA Current Ptr : Ch#3\r
+\r
+//*****************************************************************************\r
+#define  DMA4_PTR1                 0x10000C      // DMA Current Ptr : Ch#4\r
+\r
+//*****************************************************************************\r
+#define  DMA5_PTR1                 0x100010      // DMA Current Ptr : Ch#5\r
+\r
+//*****************************************************************************\r
+#define  DMA6_PTR1                 0x100014      // DMA Current Ptr : Ch#6\r
+\r
+//*****************************************************************************\r
+#define  DMA7_PTR1                 0x100018      // DMA Current Ptr : Ch#7\r
+\r
+//*****************************************************************************\r
+#define  DMA8_PTR1                 0x10001C      // DMA Current Ptr : Ch#8\r
+\r
+//*****************************************************************************\r
+#define  DMA9_PTR1                 0x100020      // DMA Current Ptr : Ch#9\r
+\r
+//*****************************************************************************\r
+#define  DMA10_PTR1                0x100024      // DMA Current Ptr : Ch#10\r
+\r
+//*****************************************************************************\r
+#define  DMA11_PTR1                0x100028      // DMA Current Ptr : Ch#11\r
+\r
+//*****************************************************************************\r
+#define  DMA12_PTR1                0x10002C      // DMA Current Ptr : Ch#12\r
+\r
+//*****************************************************************************\r
+#define  DMA13_PTR1                0x100030      // DMA Current Ptr : Ch#13\r
+\r
+//*****************************************************************************\r
+#define  DMA14_PTR1                0x100034      // DMA Current Ptr : Ch#14\r
+\r
+//*****************************************************************************\r
+#define  DMA15_PTR1                0x100038      // DMA Current Ptr : Ch#15\r
+\r
+//*****************************************************************************\r
+#define  DMA16_PTR1                0x10003C      // DMA Current Ptr : Ch#16\r
+\r
+//*****************************************************************************\r
+#define  DMA17_PTR1                0x100040      // DMA Current Ptr : Ch#17\r
+\r
+//*****************************************************************************\r
+#define  DMA18_PTR1                0x100044      // DMA Current Ptr : Ch#18\r
+\r
+//*****************************************************************************\r
+#define  DMA19_PTR1                0x100048      // DMA Current Ptr : Ch#19\r
+\r
+//*****************************************************************************\r
+#define  DMA20_PTR1                0x10004C      // DMA Current Ptr : Ch#20\r
+\r
+//*****************************************************************************\r
+#define  DMA21_PTR1                0x100050      // DMA Current Ptr : Ch#21\r
+\r
+//*****************************************************************************\r
+#define  DMA22_PTR1                0x100054      // DMA Current Ptr : Ch#22\r
+\r
+//*****************************************************************************\r
+#define  DMA23_PTR1                0x100058      // DMA Current Ptr : Ch#23\r
+\r
+//*****************************************************************************\r
+#define  DMA24_PTR1                0x10005C      // DMA Current Ptr : Ch#24\r
+\r
+//*****************************************************************************\r
+#define  DMA25_PTR1                0x100060      // DMA Current Ptr : Ch#25\r
+\r
+//*****************************************************************************\r
+#define  DMA26_PTR1                0x100064      // DMA Current Ptr : Ch#26\r
+\r
+\r
+//*****************************************************************************\r
+#define  DMA1_PTR2                 0x100080      // DMA Tab Ptr : Ch#1\r
+\r
+//*****************************************************************************\r
+#define  DMA2_PTR2                 0x100084      // DMA Tab Ptr : Ch#2\r
+\r
+//*****************************************************************************\r
+#define  DMA3_PTR2                 0x100088      // DMA Tab Ptr : Ch#3\r
+\r
+//*****************************************************************************\r
+#define  DMA4_PTR2                 0x10008C      // DMA Tab Ptr : Ch#4\r
+\r
+//*****************************************************************************\r
+#define  DMA5_PTR2                 0x100090      // DMA Tab Ptr : Ch#5\r
+\r
+//*****************************************************************************\r
+#define  DMA6_PTR2                 0x100094      // DMA Tab Ptr : Ch#6\r
+\r
+//*****************************************************************************\r
+#define  DMA7_PTR2                 0x100098      // DMA Tab Ptr : Ch#7\r
+\r
+//*****************************************************************************\r
+#define  DMA8_PTR2                 0x10009C      // DMA Tab Ptr : Ch#8\r
+\r
+//*****************************************************************************\r
+#define  DMA9_PTR2                 0x1000A0      // DMA Tab Ptr : Ch#9\r
+\r
+//*****************************************************************************\r
+#define  DMA10_PTR2                0x1000A4      // DMA Tab Ptr : Ch#10\r
+\r
+//*****************************************************************************\r
+#define  DMA11_PTR2                0x1000A8      // DMA Tab Ptr : Ch#11\r
+\r
+//*****************************************************************************\r
+#define  DMA12_PTR2                0x1000AC      // DMA Tab Ptr : Ch#12\r
+\r
+//*****************************************************************************\r
+#define  DMA13_PTR2                0x1000B0      // DMA Tab Ptr : Ch#13\r
+\r
+//*****************************************************************************\r
+#define  DMA14_PTR2                0x1000B4      // DMA Tab Ptr : Ch#14\r
+\r
+//*****************************************************************************\r
+#define  DMA15_PTR2                0x1000B8      // DMA Tab Ptr : Ch#15\r
+\r
+//*****************************************************************************\r
+#define  DMA16_PTR2                0x1000BC      // DMA Tab Ptr : Ch#16\r
+\r
+//*****************************************************************************\r
+#define  DMA17_PTR2                0x1000C0      // DMA Tab Ptr : Ch#17\r
+\r
+//*****************************************************************************\r
+#define  DMA18_PTR2                0x1000C4      // DMA Tab Ptr : Ch#18\r
+\r
+//*****************************************************************************\r
+#define  DMA19_PTR2                0x1000C8      // DMA Tab Ptr : Ch#19\r
+\r
+//*****************************************************************************\r
+#define  DMA20_PTR2                0x1000CC      // DMA Tab Ptr : Ch#20\r
+\r
+//*****************************************************************************\r
+#define  DMA21_PTR2                0x1000D0      // DMA Tab Ptr : Ch#21\r
+\r
+//*****************************************************************************\r
+#define  DMA22_PTR2                0x1000D4      // DMA Tab Ptr : Ch#22\r
+\r
+//*****************************************************************************\r
+#define  DMA23_PTR2                0x1000D8      // DMA Tab Ptr : Ch#23\r
+\r
+//*****************************************************************************\r
+#define  DMA24_PTR2                0x1000DC      // DMA Tab Ptr : Ch#24\r
+\r
+//*****************************************************************************\r
+#define  DMA25_PTR2                0x1000E0      // DMA Tab Ptr : Ch#25\r
+\r
+//*****************************************************************************\r
+#define  DMA26_PTR2                0x1000E4      // DMA Tab Ptr : Ch#26\r
+\r
+\r
+\r
+//*****************************************************************************\r
+#define  DMA1_CNT1                 0x100100      // DMA BuFFer Size : Ch#1\r
+\r
+//*****************************************************************************\r
+#define  DMA2_CNT1                 0x100104      // DMA BuFFer Size : Ch#2\r
+\r
+//*****************************************************************************\r
+#define  DMA3_CNT1                 0x100108      // DMA BuFFer Size : Ch#3\r
+\r
+//*****************************************************************************\r
+#define  DMA4_CNT1                 0x10010C      // DMA BuFFer Size : Ch#4\r
+\r
+//*****************************************************************************\r
+#define  DMA5_CNT1                 0x100110      // DMA BuFFer Size : Ch#5\r
+\r
+//*****************************************************************************\r
+#define  DMA6_CNT1                 0x100114      // DMA BuFFer Size : Ch#6\r
+\r
+//*****************************************************************************\r
+#define  DMA7_CNT1                 0x100118      // DMA BuFFer Size : Ch#7\r
+\r
+//*****************************************************************************\r
+#define  DMA8_CNT1                 0x10011C      // DMA BuFFer Size : Ch#8\r
+\r
+//*****************************************************************************\r
+#define  DMA9_CNT1                 0x100120      // DMA BuFFer Size : Ch#9\r
+\r
+//*****************************************************************************\r
+#define  DMA10_CNT1                0x100124      // DMA BuFFer Size : Ch#10\r
+\r
+//*****************************************************************************\r
+#define  DMA11_CNT1                0x100128      // DMA BuFFer Size : Ch#11\r
+\r
+//*****************************************************************************\r
+#define  DMA12_CNT1                0x10012C      // DMA BuFFer Size : Ch#12\r
+\r
+//*****************************************************************************\r
+#define  DMA13_CNT1                0x100130      // DMA BuFFer Size : Ch#13\r
+\r
+//*****************************************************************************\r
+#define  DMA14_CNT1                0x100134      // DMA BuFFer Size : Ch#14\r
+\r
+//*****************************************************************************\r
+#define  DMA15_CNT1                0x100138      // DMA BuFFer Size : Ch#15\r
+\r
+//*****************************************************************************\r
+#define  DMA16_CNT1                0x10013C      // DMA BuFFer Size : Ch#16\r
+\r
+//*****************************************************************************\r
+#define  DMA17_CNT1                0x100140      // DMA BuFFer Size : Ch#17\r
+\r
+//*****************************************************************************\r
+#define  DMA18_CNT1                0x100144      // DMA BuFFer Size : Ch#18\r
+\r
+//*****************************************************************************\r
+#define  DMA19_CNT1                0x100148      // DMA BuFFer Size : Ch#19\r
+\r
+//*****************************************************************************\r
+#define  DMA20_CNT1                0x10014C      // DMA BuFFer Size : Ch#20\r
+\r
+//*****************************************************************************\r
+#define  DMA21_CNT1                0x100150      // DMA BuFFer Size : Ch#21\r
+\r
+//*****************************************************************************\r
+#define  DMA22_CNT1                0x100154      // DMA BuFFer Size : Ch#22\r
+\r
+//*****************************************************************************\r
+#define  DMA23_CNT1                0x100158      // DMA BuFFer Size : Ch#23\r
+\r
+//*****************************************************************************\r
+#define  DMA24_CNT1                0x10015C      // DMA BuFFer Size : Ch#24\r
+\r
+//*****************************************************************************\r
+#define  DMA25_CNT1                0x100160      // DMA BuFFer Size : Ch#25\r
+\r
+//*****************************************************************************\r
+#define  DMA26_CNT1                0x100164      // DMA BuFFer Size : Ch#26\r
+\r
+\r
+//*****************************************************************************\r
+#define  DMA1_CNT2                 0x100180      // DMA Table Size : Ch#1\r
+\r
+//*****************************************************************************\r
+#define  DMA2_CNT2                 0x100184      // DMA Table Size : Ch#2\r
+\r
+//*****************************************************************************\r
+#define  DMA3_CNT2                 0x100188      // DMA Table Size : Ch#3\r
+\r
+//*****************************************************************************\r
+#define  DMA4_CNT2                 0x10018C      // DMA Table Size : Ch#4\r
+\r
+//*****************************************************************************\r
+#define  DMA5_CNT2                 0x100190      // DMA Table Size : Ch#5\r
+\r
+//*****************************************************************************\r
+#define  DMA6_CNT2                 0x100194      // DMA Table Size : Ch#6\r
+\r
+//*****************************************************************************\r
+#define  DMA7_CNT2                 0x100198      // DMA Table Size : Ch#7\r
+\r
+//*****************************************************************************\r
+#define  DMA8_CNT2                 0x10019C      // DMA Table Size : Ch#8\r
+\r
+//*****************************************************************************\r
+#define  DMA9_CNT2                 0x1001A0      // DMA Table Size : Ch#9\r
+\r
+//*****************************************************************************\r
+#define  DMA10_CNT2                0x1001A4      // DMA Table Size : Ch#10\r
+\r
+//*****************************************************************************\r
+#define  DMA11_CNT2                0x1001A8      // DMA Table Size : Ch#11\r
+\r
+//*****************************************************************************\r
+#define  DMA12_CNT2                0x1001AC      // DMA Table Size : Ch#12\r
+\r
+//*****************************************************************************\r
+#define  DMA13_CNT2                0x1001B0      // DMA Table Size : Ch#13\r
+\r
+//*****************************************************************************\r
+#define  DMA14_CNT2                0x1001B4      // DMA Table Size : Ch#14\r
+\r
+//*****************************************************************************\r
+#define  DMA15_CNT2                0x1001B8      // DMA Table Size : Ch#15\r
+\r
+//*****************************************************************************\r
+#define  DMA16_CNT2                0x1001BC      // DMA Table Size : Ch#16\r
+\r
+//*****************************************************************************\r
+#define  DMA17_CNT2                0x1001C0      // DMA Table Size : Ch#17\r
+\r
+//*****************************************************************************\r
+#define  DMA18_CNT2                0x1001C4      // DMA Table Size : Ch#18\r
+\r
+//*****************************************************************************\r
+#define  DMA19_CNT2                0x1001C8      // DMA Table Size : Ch#19\r
+\r
+//*****************************************************************************\r
+#define  DMA20_CNT2                0x1001CC      // DMA Table Size : Ch#20\r
+\r
+//*****************************************************************************\r
+#define  DMA21_CNT2                0x1001D0      // DMA Table Size : Ch#21\r
+\r
+//*****************************************************************************\r
+#define  DMA22_CNT2                0x1001D4      // DMA Table Size : Ch#22\r
+\r
+//*****************************************************************************\r
+#define  DMA23_CNT2                0x1001D8      // DMA Table Size : Ch#23\r
+\r
+//*****************************************************************************\r
+#define  DMA24_CNT2                0x1001DC      // DMA Table Size : Ch#24\r
+\r
+//*****************************************************************************\r
+#define  DMA25_CNT2                0x1001E0      // DMA Table Size : Ch#25\r
+\r
+//*****************************************************************************\r
+#define  DMA26_CNT2                0x1001E4      // DMA Table Size : Ch#26\r
+\r
+\r
+\r
+//*****************************************************************************\r
+ // ITG\r
+//*****************************************************************************\r
+#define  TM_CNT_LDW                0x110000      // Timer : Counter low \r
+\r
+//*****************************************************************************\r
+#define  TM_CNT_UW                 0x110004      // Timer : Counter high word\r
+\r
+//*****************************************************************************\r
+#define  TM_LMT_LDW                0x110008      // Timer : Limit low \r
+\r
+//*****************************************************************************\r
+#define  TM_LMT_UW                 0x11000C      // Timer : Limit high word\r
+\r
+//*****************************************************************************\r
+#define  GP0_IO                    0x110010      // GPIO output enables data I/O\r
+#define  FLD_GP_OE                 0x00FF0000    // GPIO: GP_OE output enable\r
+#define  FLD_GP_IN                 0x0000FF00    // GPIO: GP_IN status\r
+#define  FLD_GP_OUT                0x000000FF    // GPIO: GP_OUT control\r
+\r
+//*****************************************************************************\r
+#define  GPIO_ISM                  0x110014      // GPIO interrupt sensitivity mode\r
+#define  FLD_GP_ISM_SNS            0x00000070\r
+#define  FLD_GP_ISM_POL            0x00000007\r
+\r
+//*****************************************************************************\r
+#define  SOFT_RESET                0x11001C      // Output system reset reg\r
+#define  FLD_PECOS_SOFT_RESET      0x00000001\r
+\r
+//*****************************************************************************\r
+#define  MC416_RWD                 0x110020      // MC416 GPIO[18:3] pin\r
+#define  MC416_OEN                 0x110024      // Output enable of GPIO[18:3]\r
+#define  MC416_CTL                 0x110028\r
+\r
+//*****************************************************************************\r
+#define  ALT_PIN_OUT_SEL           0x11002C      // Alternate GPIO output select\r
+\r
+#define  FLD_ALT_GPIO_OUT_SEL      0xF0000000\r
+// 0          Disabled <-- default\r
+// 1          GPIO[0]\r
+// 2          GPIO[10]\r
+// 3          VIP_656_DATA_VAL\r
+// 4          VIP_656_DATA[0]\r
+// 5          VIP_656_CLK\r
+// 6          VIP_656_DATA_EXT[1]\r
+// 7          VIP_656_DATA_EXT[0]\r
+// 8          ATT_IF\r
+\r
+#define  FLD_AUX_PLL_CLK_ALT_SEL   0x0F000000\r
+// 0          AUX_PLL_CLK<-- default\r
+// 1          GPIO[2]\r
+// 2          GPIO[10]\r
+// 3          VIP_656_DATA_VAL\r
+// 4          VIP_656_DATA[0]\r
+// 5          VIP_656_CLK\r
+// 6          VIP_656_DATA_EXT[1]\r
+// 7          VIP_656_DATA_EXT[0]\r
+\r
+#define  FLD_IR_TX_ALT_SEL         0x00F00000\r
+// 0          IR_TX <-- default\r
+// 1          GPIO[1]\r
+// 2          GPIO[10]\r
+// 3          VIP_656_DATA_VAL\r
+// 4          VIP_656_DATA[0]\r
+// 5          VIP_656_CLK\r
+// 6          VIP_656_DATA_EXT[1]\r
+// 7          VIP_656_DATA_EXT[0]\r
+\r
+#define  FLD_IR_RX_ALT_SEL         0x000F0000\r
+// 0          IR_RX <-- default\r
+// 1          GPIO[0]\r
+// 2          GPIO[10]\r
+// 3          VIP_656_DATA_VAL\r
+// 4          VIP_656_DATA[0]\r
+// 5          VIP_656_CLK\r
+// 6          VIP_656_DATA_EXT[1]\r
+// 7          VIP_656_DATA_EXT[0]\r
+\r
+#define  FLD_GPIO10_ALT_SEL        0x0000F000\r
+// 0          GPIO[10] <-- default\r
+// 1          GPIO[0]\r
+// 2          GPIO[10]\r
+// 3          VIP_656_DATA_VAL\r
+// 4          VIP_656_DATA[0]\r
+// 5          VIP_656_CLK\r
+// 6          VIP_656_DATA_EXT[1]\r
+// 7          VIP_656_DATA_EXT[0]\r
+\r
+#define  FLD_GPIO2_ALT_SEL         0x00000F00\r
+// 0          GPIO[2] <-- default\r
+// 1          GPIO[1]\r
+// 2          GPIO[10]\r
+// 3          VIP_656_DATA_VAL\r
+// 4          VIP_656_DATA[0]\r
+// 5          VIP_656_CLK\r
+// 6          VIP_656_DATA_EXT[1]\r
+// 7          VIP_656_DATA_EXT[0]\r
+\r
+#define  FLD_GPIO1_ALT_SEL         0x000000F0\r
+// 0          GPIO[1] <-- default\r
+// 1          GPIO[0]\r
+// 2          GPIO[10]\r
+// 3          VIP_656_DATA_VAL\r
+// 4          VIP_656_DATA[0]\r
+// 5          VIP_656_CLK\r
+// 6          VIP_656_DATA_EXT[1]\r
+// 7          VIP_656_DATA_EXT[0]\r
+\r
+#define  FLD_GPIO0_ALT_SEL         0x0000000F\r
+// 0          GPIO[0] <-- default\r
+// 1          GPIO[1]\r
+// 2          GPIO[10]\r
+// 3          VIP_656_DATA_VAL\r
+// 4          VIP_656_DATA[0]\r
+// 5          VIP_656_CLK\r
+// 6          VIP_656_DATA_EXT[1]\r
+// 7          VIP_656_DATA_EXT[0]\r
+\r
+#define  ALT_PIN_IN_SEL            0x110030      // Alternate GPIO input select\r
+\r
+#define  FLD_GPIO10_ALT_IN_SEL     0x0000F000\r
+// 0          GPIO[10] <-- default\r
+// 1          IR_RX\r
+// 2          IR_TX\r
+// 3          AUX_PLL_CLK\r
+// 4          IF_ATT_SEL\r
+// 5          GPIO[0]\r
+// 6          GPIO[1]\r
+// 7          GPIO[2]\r
+\r
+#define  FLD_GPIO2_ALT_IN_SEL      0x00000F00\r
+// 0          GPIO[2] <-- default\r
+// 1          IR_RX\r
+// 2          IR_TX\r
+// 3          AUX_PLL_CLK\r
+// 4          IF_ATT_SEL\r
+\r
+#define  FLD_GPIO1_ALT_IN_SEL      0x000000F0\r
+// 0          GPIO[1] <-- default\r
+// 1          IR_RX\r
+// 2          IR_TX\r
+// 3          AUX_PLL_CLK\r
+// 4          IF_ATT_SEL\r
+\r
+#define  FLD_GPIO0_ALT_IN_SEL      0x0000000F\r
+// 0          GPIO[0] <-- default\r
+// 1          IR_RX\r
+// 2          IR_TX\r
+// 3          AUX_PLL_CLK\r
+// 4          IF_ATT_SEL\r
+\r
+//*****************************************************************************\r
+#define  TEST_BUS_CTL1             0x110040      // Test bus control register #1\r
+\r
+//*****************************************************************************\r
+#define  TEST_BUS_CTL2             0x110044      // Test bus control register #2\r
+\r
+//*****************************************************************************\r
+#define  CLK_DELAY                 0x110048      // Clock delay\r
+#define  FLD_MOE_CLK_DIS           0x80000000    // Disable MoE clock\r
+\r
+\r
+//*****************************************************************************\r
+#define  PAD_CTRL                  0x110068      // Pad drive strength control\r
+\r
+//*****************************************************************************\r
+#define  MBIST_CTRL                0x110050      // SRAM memory built-in self test control\r
+\r
+//*****************************************************************************\r
+#define  MBIST_STAT                0x110054      // SRAM memory built-in self test status\r
+\r
+//*****************************************************************************\r
+// PLL registers\r
+//*****************************************************************************\r
+#define  PLL_A_INT_FRAC            0x110088\r
+#define  PLL_A_POST_STAT_BIST      0x11008C\r
+#define  PLL_B_INT_FRAC            0x110090\r
+#define  PLL_B_POST_STAT_BIST      0x110094\r
+#define  PLL_C_INT_FRAC            0x110098\r
+#define  PLL_C_POST_STAT_BIST      0x11009C\r
+#define  PLL_D_INT_FRAC            0x1100A0\r
+#define  PLL_D_POST_STAT_BIST      0x1100A4\r
+\r
+#define  CLK_RST                   0x11002C\r
+#define  FLD_VID_I_CLK_NOE         0x00001000\r
+#define  FLD_VID_J_CLK_NOE         0x00002000\r
+#define  FLD_USE_ALT_PLL_REF       0x00004000\r
+\r
+#define  VID_CH_MODE_SEL           0x110078\r
+#define  VID_CH_CLK_SEL            0x11007C\r
+\r
+\r
+//*****************************************************************************\r
+#define  VBI_A_DMA                 0x130008      // VBI A DMA data port\r
+\r
+//*****************************************************************************\r
+#define  VID_A_VIP_CTL             0x130080      // Video A VIP format control\r
+#define  FLD_VIP_MODE              0x00000001\r
+\r
+//*****************************************************************************\r
+#define  VID_A_PIXEL_FRMT          0x130084      // Video A pixel format\r
+#define  FLD_VID_A_GAMMA_DIS       0x00000008\r
+#define  FLD_VID_A_FORMAT          0x00000007\r
+#define  FLD_VID_A_GAMMA_FACTOR    0x00000010\r
+\r
+//*****************************************************************************\r
+#define  VID_A_VBI_CTL             0x130088      // Video A VBI miscellaneous control\r
+#define  FLD_VID_A_VIP_EXT         0x00000003\r
+\r
+//*****************************************************************************\r
+#define  VID_B_DMA                 0x130100      // Video B DMA data port\r
+\r
+//*****************************************************************************\r
+#define  VBI_B_DMA                 0x130108      // VBI B DMA data port\r
+\r
+//*****************************************************************************\r
+#define  VID_B_SRC_SEL             0x130144      // Video B source select\r
+#define  FLD_VID_B_SRC_SEL         0x00000000\r
+\r
+//*****************************************************************************\r
+#define  VID_B_LNGTH               0x130150      // Video B line length\r
+#define  FLD_VID_B_LN_LNGTH        0x00000FFF\r
+\r
+//*****************************************************************************\r
+#define  VID_B_VIP_CTL             0x130180      // Video B VIP format control\r
+\r
+//*****************************************************************************\r
+#define  VID_B_PIXEL_FRMT          0x130184      // Video B pixel format\r
+#define  FLD_VID_B_GAMMA_DIS       0x00000008\r
+#define  FLD_VID_B_FORMAT          0x00000007\r
+#define  FLD_VID_B_GAMMA_FACTOR    0x00000010\r
+\r
+//*****************************************************************************\r
+#define  VID_C_DMA                 0x130200      // Video C DMA data port\r
+\r
+//*****************************************************************************\r
+#define  VID_C_LNGTH               0x130250      // Video C line length\r
+#define  FLD_VID_C_LN_LNGTH        0x00000FFF\r
+\r
+\r
+//*****************************************************************************\r
+// Video Destination Channels\r
+//*****************************************************************************\r
+\r
+#define  VID_DST_A_GPCNT           0x130020      // Video A general purpose counter\r
+#define  VID_DST_B_GPCNT           0x130120      // Video B general purpose counter\r
+#define  VID_DST_C_GPCNT           0x130220      // Video C general purpose counter\r
+#define  VID_DST_D_GPCNT           0x130320      // Video D general purpose counter\r
+#define  VID_DST_E_GPCNT           0x130420      // Video E general purpose counter\r
+#define  VID_DST_F_GPCNT           0x130520      // Video F general purpose counter\r
+#define  VID_DST_G_GPCNT           0x130620      // Video G general purpose counter\r
+#define  VID_DST_H_GPCNT           0x130720      // Video H general purpose counter\r
+\r
+//*****************************************************************************\r
+\r
+#define  VID_DST_A_GPCNT_CTL       0x130030      // Video A general purpose control\r
+#define  VID_DST_B_GPCNT_CTL       0x130130      // Video B general purpose control\r
+#define  VID_DST_C_GPCNT_CTL       0x130230      // Video C general purpose control\r
+#define  VID_DST_D_GPCNT_CTL       0x130330      // Video D general purpose control\r
+#define  VID_DST_E_GPCNT_CTL       0x130430      // Video E general purpose control\r
+#define  VID_DST_F_GPCNT_CTL       0x130530      // Video F general purpose control\r
+#define  VID_DST_G_GPCNT_CTL       0x130630      // Video G general purpose control\r
+#define  VID_DST_H_GPCNT_CTL       0x130730      // Video H general purpose control\r
+\r
+\r
+//*****************************************************************************\r
+\r
+#define  VID_DST_A_DMA_CTL         0x130040      // Video A DMA control\r
+#define  VID_DST_B_DMA_CTL         0x130140      // Video B DMA control\r
+#define  VID_DST_C_DMA_CTL         0x130240      // Video C DMA control\r
+#define  VID_DST_D_DMA_CTL         0x130340      // Video D DMA control\r
+#define  VID_DST_E_DMA_CTL         0x130440      // Video E DMA control\r
+#define  VID_DST_F_DMA_CTL         0x130540      // Video F DMA control\r
+#define  VID_DST_G_DMA_CTL         0x130640      // Video G DMA control\r
+#define  VID_DST_H_DMA_CTL         0x130740      // Video H DMA control\r
+\r
+#define  FLD_VID_RISC_EN           0x00000010\r
+#define  FLD_VID_FIFO_EN           0x00000001\r
+\r
+//*****************************************************************************\r
+\r
+#define  VID_DST_A_VIP_CTL         0x130080      // Video A VIP control\r
+#define  VID_DST_B_VIP_CTL         0x130180      // Video B VIP control\r
+#define  VID_DST_C_VIP_CTL         0x130280      // Video C VIP control\r
+#define  VID_DST_D_VIP_CTL         0x130380      // Video D VIP control\r
+#define  VID_DST_E_VIP_CTL         0x130480      // Video E VIP control\r
+#define  VID_DST_F_VIP_CTL         0x130580      // Video F VIP control\r
+#define  VID_DST_G_VIP_CTL         0x130680      // Video G VIP control\r
+#define  VID_DST_H_VIP_CTL         0x130780      // Video H VIP control\r
+\r
+//*****************************************************************************\r
+\r
+#define  VID_DST_A_PIX_FRMT        0x130084      // Video A Pixel format\r
+#define  VID_DST_B_PIX_FRMT        0x130184      // Video B Pixel format\r
+#define  VID_DST_C_PIX_FRMT        0x130284      // Video C Pixel format\r
+#define  VID_DST_D_PIX_FRMT        0x130384      // Video D Pixel format\r
+#define  VID_DST_E_PIX_FRMT        0x130484      // Video E Pixel format\r
+#define  VID_DST_F_PIX_FRMT        0x130584      // Video F Pixel format\r
+#define  VID_DST_G_PIX_FRMT        0x130684      // Video G Pixel format\r
+#define  VID_DST_H_PIX_FRMT        0x130784      // Video H Pixel format\r
+\r
+//*****************************************************************************\r
+// Video Source Channels\r
+//*****************************************************************************\r
+\r
+#define  VID_SRC_A_GPCNT_CTL       0x130804      // Video A general purpose control\r
+#define  VID_SRC_B_GPCNT_CTL       0x130904      // Video B general purpose control\r
+#define  VID_SRC_C_GPCNT_CTL       0x130A04      // Video C general purpose control\r
+#define  VID_SRC_D_GPCNT_CTL       0x130B04      // Video D general purpose control\r
+#define  VID_SRC_E_GPCNT_CTL       0x130C04      // Video E general purpose control\r
+#define  VID_SRC_F_GPCNT_CTL       0x130D04      // Video F general purpose control\r
+#define  VID_SRC_I_GPCNT_CTL       0x130E04      // Video I general purpose control\r
+#define  VID_SRC_J_GPCNT_CTL       0x130F04      // Video J general purpose control\r
+\r
+//*****************************************************************************\r
+\r
+#define  VID_SRC_A_GPCNT           0x130808      // Video A general purpose counter\r
+#define  VID_SRC_B_GPCNT           0x130908      // Video B general purpose counter\r
+#define  VID_SRC_C_GPCNT           0x130A08      // Video C general purpose counter\r
+#define  VID_SRC_D_GPCNT           0x130B08      // Video D general purpose counter\r
+#define  VID_SRC_E_GPCNT           0x130C08      // Video E general purpose counter\r
+#define  VID_SRC_F_GPCNT           0x130D08      // Video F general purpose counter\r
+#define  VID_SRC_I_GPCNT           0x130E08      // Video I general purpose counter\r
+#define  VID_SRC_J_GPCNT           0x130F08      // Video J general purpose counter\r
+\r
+//*****************************************************************************\r
+\r
+#define  VID_SRC_A_DMA_CTL         0x13080C      // Video A DMA control\r
+#define  VID_SRC_B_DMA_CTL         0x13090C      // Video B DMA control\r
+#define  VID_SRC_C_DMA_CTL         0x130A0C      // Video C DMA control\r
+#define  VID_SRC_D_DMA_CTL         0x130B0C      // Video D DMA control\r
+#define  VID_SRC_E_DMA_CTL         0x130C0C      // Video E DMA control\r
+#define  VID_SRC_F_DMA_CTL         0x130D0C      // Video F DMA control\r
+#define  VID_SRC_I_DMA_CTL         0x130E0C      // Video I DMA control\r
+#define  VID_SRC_J_DMA_CTL         0x130F0C      // Video J DMA control\r
+\r
+#define  FLD_APB_RISC_EN           0x00000010\r
+#define  FLD_APB_FIFO_EN           0x00000001\r
+\r
+//*****************************************************************************\r
+\r
+#define  VID_SRC_A_FMT_CTL         0x130810      // Video A format control\r
+#define  VID_SRC_B_FMT_CTL         0x130910      // Video B format control\r
+#define  VID_SRC_C_FMT_CTL         0x130A10      // Video C format control\r
+#define  VID_SRC_D_FMT_CTL         0x130B10      // Video D format control\r
+#define  VID_SRC_E_FMT_CTL         0x130C10      // Video E format control\r
+#define  VID_SRC_F_FMT_CTL         0x130D10      // Video F format control\r
+#define  VID_SRC_I_FMT_CTL         0x130E10      // Video I format control\r
+#define  VID_SRC_J_FMT_CTL         0x130F10      // Video J format control\r
+\r
+//*****************************************************************************\r
+\r
+#define  VID_SRC_A_ACTIVE_CTL1     0x130814      // Video A active control     1\r
+#define  VID_SRC_B_ACTIVE_CTL1     0x130914      // Video B active control     1\r
+#define  VID_SRC_C_ACTIVE_CTL1     0x130A14      // Video C active control     1\r
+#define  VID_SRC_D_ACTIVE_CTL1     0x130B14      // Video D active control     1\r
+#define  VID_SRC_E_ACTIVE_CTL1     0x130C14      // Video E active control     1\r
+#define  VID_SRC_F_ACTIVE_CTL1     0x130D14      // Video F active control     1\r
+#define  VID_SRC_I_ACTIVE_CTL1     0x130E14      // Video I active control     1\r
+#define  VID_SRC_J_ACTIVE_CTL1     0x130F14      // Video J active control     1\r
+\r
+//*****************************************************************************\r
+\r
+#define  VID_SRC_A_ACTIVE_CTL2     0x130818      // Video A active control     2\r
+#define  VID_SRC_B_ACTIVE_CTL2     0x130918      // Video B active control     2\r
+#define  VID_SRC_C_ACTIVE_CTL2     0x130A18      // Video C active control     2\r
+#define  VID_SRC_D_ACTIVE_CTL2     0x130B18      // Video D active control     2\r
+#define  VID_SRC_E_ACTIVE_CTL2     0x130C18      // Video E active control     2\r
+#define  VID_SRC_F_ACTIVE_CTL2     0x130D18      // Video F active control     2\r
+#define  VID_SRC_I_ACTIVE_CTL2     0x130E18      // Video I active control     2\r
+#define  VID_SRC_J_ACTIVE_CTL2     0x130F18      // Video J active control     2\r
+\r
+//*****************************************************************************\r
+\r
+#define  VID_SRC_A_CDT_SZ          0x13081C      // Video A CDT size\r
+#define  VID_SRC_B_CDT_SZ          0x13091C      // Video B CDT size\r
+#define  VID_SRC_C_CDT_SZ          0x130A1C      // Video C CDT size\r
+#define  VID_SRC_D_CDT_SZ          0x130B1C      // Video D CDT size\r
+#define  VID_SRC_E_CDT_SZ          0x130C1C      // Video E CDT size\r
+#define  VID_SRC_F_CDT_SZ          0x130D1C      // Video F CDT size\r
+#define  VID_SRC_I_CDT_SZ          0x130E1C      // Video I CDT size\r
+#define  VID_SRC_J_CDT_SZ          0x130F1C      // Video J CDT size\r
+\r
+//*****************************************************************************\r
+// Audio I/F\r
+//*****************************************************************************\r
+#define  AUD_DST_A_DMA             0x140000      // Audio Int A DMA data port\r
+#define  AUD_SRC_A_DMA             0x140008      // Audio Int A DMA data port\r
+\r
+#define  AUD_A_GPCNT               0x140010      // Audio Int A gp counter\r
+#define  FLD_AUD_A_GP_CNT          0x0000FFFF\r
+\r
+#define  AUD_A_GPCNT_CTL           0x140014      // Audio Int A gp control\r
+\r
+#define  AUD_A_LNGTH               0x140018      // Audio Int A line length\r
+\r
+#define  AUD_A_CFG                 0x14001C      // Audio Int A configuration\r
+\r
+//*****************************************************************************\r
+#define  AUD_DST_B_DMA             0x140100      // Audio Int B DMA data port\r
+#define  AUD_SRC_B_DMA             0x140108      // Audio Int B DMA data port\r
+\r
+#define  AUD_B_GPCNT               0x140110      // Audio Int B gp counter\r
+#define  FLD_AUD_B_GP_CNT          0x0000FFFF\r
+\r
+#define  AUD_B_GPCNT_CTL           0x140114      // Audio Int B gp control\r
+\r
+#define  AUD_B_LNGTH               0x140118      // Audio Int B line length\r
+\r
+#define  AUD_B_CFG                 0x14011C      // Audio Int B configuration\r
+\r
+//*****************************************************************************\r
+#define  AUD_DST_C_DMA             0x140200      // Audio Int C DMA data port\r
+#define  AUD_SRC_C_DMA             0x140208      // Audio Int C DMA data port\r
+\r
+#define  AUD_C_GPCNT               0x140210      // Audio Int C gp counter\r
+#define  FLD_AUD_C_GP_CNT          0x0000FFFF\r
+\r
+#define  AUD_C_GPCNT_CTL           0x140214      // Audio Int C gp control\r
+\r
+#define  AUD_C_LNGTH               0x140218      // Audio Int C line length\r
+\r
+#define  AUD_C_CFG                 0x14021C      // Audio Int C configuration\r
+\r
+//*****************************************************************************\r
+#define  AUD_DST_D_DMA             0x140300      // Audio Int D DMA data port\r
+#define  AUD_SRC_D_DMA             0x140308      // Audio Int D DMA data port\r
+\r
+#define  AUD_D_GPCNT               0x140310      // Audio Int D gp counter\r
+#define  FLD_AUD_D_GP_CNT          0x0000FFFF\r
+\r
+#define  AUD_D_GPCNT_CTL           0x140314      // Audio Int D gp control\r
+\r
+#define  AUD_D_LNGTH               0x140318      // Audio Int D line length\r
+\r
+#define  AUD_D_CFG                 0x14031C      // Audio Int D configuration\r
+\r
+//*****************************************************************************\r
+#define  AUD_SRC_E_DMA             0x140400      // Audio Int E DMA data port\r
+\r
+#define  AUD_E_GPCNT               0x140410      // Audio Int E gp counter\r
+#define  FLD_AUD_E_GP_CNT          0x0000FFFF\r
+\r
+#define  AUD_E_GPCNT_CTL           0x140414      // Audio Int E gp control\r
+\r
+#define  AUD_E_CFG                 0x14041C      // Audio Int E configuration\r
+\r
+//*****************************************************************************\r
+\r
+#define  FLD_AUD_DST_LN_LNGTH      0x00000FFF\r
+\r
+#define  FLD_AUD_DST_PK_MODE       0x00004000\r
+\r
+#define  FLD_AUD_CLK_ENABLE        0x00000200\r
+\r
+#define  FLD_AUD_MASTER_MODE       0x00000002\r
+\r
+#define  FLD_AUD_SONY_MODE         0x00000001\r
+\r
+#define  FLD_AUD_CLK_SELECT_PLL_D  0x00001800\r
+\r
+#define  FLD_AUD_DST_ENABLE        0x00020000\r
+\r
+#define  FLD_AUD_SRC_ENABLE        0x00010000\r
+\r
+//*****************************************************************************\r
+#define  AUD_INT_DMA_CTL           0x140500      // Audio Int DMA control\r
+\r
+#define  FLD_AUD_SRC_E_RISC_EN     0x00008000\r
+#define  FLD_AUD_SRC_C_RISC_EN     0x00004000\r
+#define  FLD_AUD_SRC_B_RISC_EN     0x00002000\r
+#define  FLD_AUD_SRC_A_RISC_EN     0x00001000\r
+\r
+#define  FLD_AUD_DST_D_RISC_EN     0x00000800\r
+#define  FLD_AUD_DST_C_RISC_EN     0x00000400\r
+#define  FLD_AUD_DST_B_RISC_EN     0x00000200\r
+#define  FLD_AUD_DST_A_RISC_EN     0x00000100\r
+\r
+#define  FLD_AUD_SRC_E_FIFO_EN     0x00000080\r
+#define  FLD_AUD_SRC_C_FIFO_EN     0x00000040\r
+#define  FLD_AUD_SRC_B_FIFO_EN     0x00000020\r
+#define  FLD_AUD_SRC_A_FIFO_EN     0x00000010\r
+\r
+#define  FLD_AUD_DST_D_FIFO_EN     0x00000008\r
+#define  FLD_AUD_DST_C_FIFO_EN     0x00000004\r
+#define  FLD_AUD_DST_B_FIFO_EN     0x00000002\r
+#define  FLD_AUD_DST_A_FIFO_EN     0x00000001\r
+\r
+\r
+//*****************************************************************************\r
+//\r
+//                   Mobilygen Interface Registers\r
+//\r
+//*****************************************************************************\r
+// Mobilygen Interface A\r
+//*****************************************************************************\r
+#define  MB_IF_A_DMA               0x150000      // MBIF A DMA data port\r
+#define  MB_IF_A_GPCN              0x150008      // MBIF A GP counter\r
+#define  MB_IF_A_GPCN_CTRL         0x15000C\r
+#define  MB_IF_A_DMA_CTRL          0x150010\r
+#define  MB_IF_A_LENGTH            0x150014\r
+#define  MB_IF_A_HDMA_XFER_SZ      0x150018\r
+#define  MB_IF_A_HCMD              0x15001C\r
+#define  MB_IF_A_HCONFIG           0x150020\r
+#define  MB_IF_A_DATA_STRUCT_0     0x150024\r
+#define  MB_IF_A_DATA_STRUCT_1     0x150028\r
+#define  MB_IF_A_DATA_STRUCT_2     0x15002C\r
+#define  MB_IF_A_DATA_STRUCT_3     0x150030\r
+#define  MB_IF_A_DATA_STRUCT_4     0x150034\r
+#define  MB_IF_A_DATA_STRUCT_5     0x150038\r
+#define  MB_IF_A_DATA_STRUCT_6     0x15003C\r
+#define  MB_IF_A_DATA_STRUCT_7     0x150040\r
+#define  MB_IF_A_DATA_STRUCT_8     0x150044\r
+#define  MB_IF_A_DATA_STRUCT_9     0x150048\r
+#define  MB_IF_A_DATA_STRUCT_A     0x15004C\r
+#define  MB_IF_A_DATA_STRUCT_B     0x150050\r
+#define  MB_IF_A_DATA_STRUCT_C     0x150054\r
+#define  MB_IF_A_DATA_STRUCT_D     0x150058\r
+#define  MB_IF_A_DATA_STRUCT_E     0x15005C\r
+#define  MB_IF_A_DATA_STRUCT_F     0x150060\r
+//*****************************************************************************\r
+// Mobilygen Interface B\r
+//*****************************************************************************\r
+#define  MB_IF_B_DMA               0x160000      // MBIF A DMA data port\r
+#define  MB_IF_B_GPCN              0x160008      // MBIF A GP counter\r
+#define  MB_IF_B_GPCN_CTRL         0x16000C\r
+#define  MB_IF_B_DMA_CTRL          0x160010\r
+#define  MB_IF_B_LENGTH            0x160014\r
+#define  MB_IF_B_HDMA_XFER_SZ      0x160018\r
+#define  MB_IF_B_HCMD              0x16001C\r
+#define  MB_IF_B_HCONFIG           0x160020\r
+#define  MB_IF_B_DATA_STRUCT_0     0x160024\r
+#define  MB_IF_B_DATA_STRUCT_1     0x160028\r
+#define  MB_IF_B_DATA_STRUCT_2     0x16002C\r
+#define  MB_IF_B_DATA_STRUCT_3     0x160030\r
+#define  MB_IF_B_DATA_STRUCT_4     0x160034\r
+#define  MB_IF_B_DATA_STRUCT_5     0x160038\r
+#define  MB_IF_B_DATA_STRUCT_6     0x16003C\r
+#define  MB_IF_B_DATA_STRUCT_7     0x160040\r
+#define  MB_IF_B_DATA_STRUCT_8     0x160044\r
+#define  MB_IF_B_DATA_STRUCT_9     0x160048\r
+#define  MB_IF_B_DATA_STRUCT_A     0x16004C\r
+#define  MB_IF_B_DATA_STRUCT_B     0x160050\r
+#define  MB_IF_B_DATA_STRUCT_C     0x160054\r
+#define  MB_IF_B_DATA_STRUCT_D     0x160058\r
+#define  MB_IF_B_DATA_STRUCT_E     0x16005C\r
+#define  MB_IF_B_DATA_STRUCT_F     0x160060\r
+\r
+// MB_DMA_CTRL\r
+#define  FLD_MB_IF_RISC_EN         0x00000010\r
+#define  FLD_MB_IF_FIFO_EN         0x00000001\r
+\r
+// MB_LENGTH\r
+#define  FLD_MB_IF_LN_LNGTH        0x00000FFF\r
+\r
+// MB_HCMD register\r
+#define  FLD_MB_HCMD_H_GO          0x80000000\r
+#define  FLD_MB_HCMD_H_BUSY        0x40000000\r
+#define  FLD_MB_HCMD_H_DMA_HOLD    0x10000000\r
+#define  FLD_MB_HCMD_H_DMA_BUSY    0x08000000\r
+#define  FLD_MB_HCMD_H_DMA_TYPE    0x04000000\r
+#define  FLD_MB_HCMD_H_DMA_XACT    0x02000000\r
+#define  FLD_MB_HCMD_H_RW_N        0x01000000\r
+#define  FLD_MB_HCMD_H_ADDR        0x00FF0000\r
+#define  FLD_MB_HCMD_H_DATA        0x0000FFFF\r
+\r
+\r
+//*****************************************************************************\r
+// I2C #1\r
+//*****************************************************************************\r
+#define  I2C1_ADDR                 0x180000      // I2C #1 address\r
+#define  FLD_I2C_DADDR             0xfe000000    // RW [31:25] I2C Device Address\r
+                                                 // RO [24] reserved\r
+//*****************************************************************************\r
+#define  FLD_I2C_SADDR             0x00FFFFFF    // RW [23:0]  I2C Sub-address\r
+\r
+//*****************************************************************************\r
+#define  I2C1_WDATA                0x180004      // I2C #1 write data\r
+#define  FLD_I2C_WDATA             0xFFFFFFFF    // RW [31:0]\r
+\r
+//*****************************************************************************\r
+#define  I2C1_CTRL                 0x180008      // I2C #1 control\r
+#define  FLD_I2C_PERIOD            0xFF000000    // RW [31:24]\r
+#define  FLD_I2C_SCL_IN            0x00200000    // RW [21]\r
+#define  FLD_I2C_SDA_IN            0x00100000    // RW [20]\r
+                                                 // RO [19:18] reserved\r
+#define  FLD_I2C_SCL_OUT           0x00020000    // RW [17]\r
+#define  FLD_I2C_SDA_OUT           0x00010000    // RW [16]\r
+                                                 // RO [15] reserved\r
+#define  FLD_I2C_DATA_LEN          0x00007000    // RW [14:12]\r
+#define  FLD_I2C_SADDR_INC         0x00000800    // RW [11]\r
+                                                 // RO [10:9] reserved\r
+#define  FLD_I2C_SADDR_LEN         0x00000300    // RW [9:8]\r
+                                                 // RO [7:6] reserved\r
+#define  FLD_I2C_SOFT              0x00000020    // RW [5]\r
+#define  FLD_I2C_NOSTOP            0x00000010    // RW [4]\r
+#define  FLD_I2C_EXTEND            0x00000008    // RW [3]\r
+#define  FLD_I2C_SYNC              0x00000004    // RW [2]\r
+#define  FLD_I2C_READ_SA           0x00000002    // RW [1]\r
+#define  FLD_I2C_READ_WRN          0x00000001    // RW [0]\r
+\r
+//*****************************************************************************\r
+#define  I2C1_RDATA                0x18000C      // I2C #1 read data\r
+#define  FLD_I2C_RDATA             0xFFFFFFFF    // RO [31:0]\r
+\r
+//*****************************************************************************\r
+#define  I2C1_STAT                 0x180010      // I2C #1 status\r
+#define  FLD_I2C_XFER_IN_PROG      0x00000002    // RO [1]\r
+#define  FLD_I2C_RACK              0x00000001    // RO [0]\r
+\r
+//*****************************************************************************\r
+// I2C #2\r
+//*****************************************************************************\r
+#define  I2C2_ADDR                 0x190000      // I2C #2 address\r
+\r
+//*****************************************************************************\r
+#define  I2C2_WDATA                0x190004      // I2C #2 write data\r
+\r
+//*****************************************************************************\r
+#define  I2C2_CTRL                 0x190008      // I2C #2 control\r
+\r
+//*****************************************************************************\r
+#define  I2C2_RDATA                0x19000C      // I2C #2 read data\r
+\r
+//*****************************************************************************\r
+#define  I2C2_STAT                 0x190010      // I2C #2 status\r
+\r
+//*****************************************************************************\r
+// I2C #3\r
+//*****************************************************************************\r
+#define  I2C3_ADDR                 0x1A0000      // I2C #3 address\r
+\r
+//*****************************************************************************\r
+#define  I2C3_WDATA                0x1A0004      // I2C #3 write data\r
+\r
+//*****************************************************************************\r
+#define  I2C3_CTRL                 0x1A0008      // I2C #3 control\r
+\r
+//*****************************************************************************\r
+#define  I2C3_RDATA                0x1A000C      // I2C #3 read data\r
+\r
+//*****************************************************************************\r
+#define  I2C3_STAT                 0x1A0010      // I2C #3 status\r
+\r
+//*****************************************************************************\r
+// UART\r
+//*****************************************************************************\r
+#define  UART_CTL                  0x1B0000      // UART Control Register\r
+#define  FLD_LOOP_BACK_EN          (1 << 7)      // RW field - default 0\r
+#define  FLD_RX_TRG_SZ             (3 << 2)      // RW field - default 0\r
+#define  FLD_RX_EN                 (1 << 1)      // RW field - default 0\r
+#define  FLD_TX_EN                 (1 << 0)      // RW field - default 0\r
+\r
+//*****************************************************************************\r
+#define  UART_BRD                  0x1B0004      // UART Baud Rate Divisor\r
+#define  FLD_BRD                   0x0000FFFF    // RW field - default 0x197\r
+\r
+//*****************************************************************************\r
+#define  UART_DBUF                 0x1B0008      // UART Tx/Rx Data BuFFer\r
+#define  FLD_DB                    0xFFFFFFFF    // RW field - default 0\r
+\r
+//*****************************************************************************\r
+#define  UART_ISR                  0x1B000C      // UART Interrupt Status\r
+#define  FLD_RXD_TIMEOUT_EN        (1 << 7)      // RW field - default 0\r
+#define  FLD_FRM_ERR_EN            (1 << 6)      // RW field - default 0\r
+#define  FLD_RXD_RDY_EN            (1 << 5)      // RW field - default 0\r
+#define  FLD_TXD_EMPTY_EN          (1 << 4)      // RW field - default 0\r
+#define  FLD_RXD_OVERFLOW          (1 << 3)      // RW field - default 0\r
+#define  FLD_FRM_ERR               (1 << 2)      // RW field - default 0\r
+#define  FLD_RXD_RDY               (1 << 1)      // RW field - default 0\r
+#define  FLD_TXD_EMPTY             (1 << 0)      // RW field - default 0\r
+\r
+//*****************************************************************************\r
+#define  UART_CNT                  0x1B0010      // UART Tx/Rx FIFO Byte Count\r
+#define  FLD_TXD_CNT               (0x1F << 8)   // RW field - default 0\r
+#define  FLD_RXD_CNT               (0x1F << 0)   // RW field - default 0\r
+\r
+//*****************************************************************************\r
+// Motion Detection
+#define  MD_CH0_GRID_BLOCK_YCNT    0x170014      
+#define  MD_CH1_GRID_BLOCK_YCNT    0x170094      
+#define  MD_CH2_GRID_BLOCK_YCNT    0x170114      
+#define  MD_CH3_GRID_BLOCK_YCNT    0x170194      
+#define  MD_CH4_GRID_BLOCK_YCNT    0x170214      
+#define  MD_CH5_GRID_BLOCK_YCNT    0x170294      
+#define  MD_CH6_GRID_BLOCK_YCNT    0x170314      
+#define  MD_CH7_GRID_BLOCK_YCNT    0x170394
+
+#define PIXEL_FRMT_422    4
+#define PIXEL_FRMT_411    5
+#define PIXEL_FRMT_Y8     6
+
+#define PIXEL_ENGINE_VIP1 0
+#define PIXEL_ENGINE_VIP2 1
+
+#endif  //Athena_REGISTERS\r
+\r
+\r
diff --git a/drivers/staging/cx25821/cx25821-sram.h b/drivers/staging/cx25821/cx25821-sram.h
new file mode 100644 (file)
index 0000000..8130635
--- /dev/null
@@ -0,0 +1,266 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+#ifndef __ATHENA_SRAM_H__\r
+#define __ATHENA_SRAM_H__\r
+\r
+//#define RX_SRAM_START_SIZE        = 0;  //  Start of reserved SRAM\r
+#define VID_CMDS_SIZE             80 //  Video CMDS size in bytes\r
+#define AUDIO_CMDS_SIZE           80 //  AUDIO CMDS size in bytes\r
+#define MBIF_CMDS_SIZE            80 //  MBIF  CMDS size in bytes\r
+\r
+//#define RX_SRAM_POOL_START_SIZE   = 0;  //  Start of useable RX SRAM for buffers\r
+#define VID_IQ_SIZE               64 //  VID instruction queue size in bytes\r
+#define MBIF_IQ_SIZE              64\r
+#define AUDIO_IQ_SIZE             64 //  AUD instruction queue size in bytes\r
+\r
+#define VID_CDT_SIZE              64 //  VID cluster descriptor table size in bytes\r
+#define MBIF_CDT_SIZE             64 //  MBIF/HBI cluster descriptor table size in bytes\r
+#define AUDIO_CDT_SIZE            48 //  AUD cluster descriptor table size in bytes\r
+\r
+//#define RX_SRAM_POOL_FREE_SIZE    = 16; //  Start of available RX SRAM\r
+//#define RX_SRAM_END_SIZE          = 0;  //  End of RX SRAM\r
+\r
+//#define TX_SRAM_POOL_START_SIZE   = 0;  //  Start of transmit pool SRAM\r
+//#define MSI_DATA_SIZE             = 64; //  Reserved (MSI Data, RISC working stora\r
+\r
+#define VID_CLUSTER_SIZE          1440   //  VID cluster data line\r
+#define AUDIO_CLUSTER_SIZE        128    //  AUDIO cluster data line\r
+#define MBIF_CLUSTER_SIZE         1440   //  MBIF/HBI cluster data line\r
+\r
+\r
+//#define TX_SRAM_POOL_FREE_SIZE    = 704;    //  Start of available TX SRAM\r
+//#define TX_SRAM_END_SIZE          = 0;      //  End of TX SRAM\r
+\r
+// Receive SRAM\r
+#define RX_SRAM_START             0x10000\r
+#define VID_A_DOWN_CMDS           0x10000\r
+#define VID_B_DOWN_CMDS           0x10050\r
+#define VID_C_DOWN_CMDS           0x100A0\r
+#define VID_D_DOWN_CMDS           0x100F0\r
+#define VID_E_DOWN_CMDS           0x10140\r
+#define VID_F_DOWN_CMDS           0x10190\r
+#define VID_G_DOWN_CMDS           0x101E0\r
+#define VID_H_DOWN_CMDS           0x10230\r
+#define VID_A_UP_CMDS             0x10280\r
+#define VID_B_UP_CMDS             0x102D0\r
+#define VID_C_UP_CMDS             0x10320\r
+#define VID_D_UP_CMDS             0x10370\r
+#define VID_E_UP_CMDS             0x103C0\r
+#define VID_F_UP_CMDS             0x10410\r
+#define VID_I_UP_CMDS             0x10460\r
+#define VID_J_UP_CMDS             0x104B0\r
+#define AUD_A_DOWN_CMDS           0x10500\r
+#define AUD_B_DOWN_CMDS           0x10550\r
+#define AUD_C_DOWN_CMDS           0x105A0\r
+#define AUD_D_DOWN_CMDS           0x105F0\r
+#define AUD_A_UP_CMDS             0x10640\r
+#define AUD_B_UP_CMDS             0x10690\r
+#define AUD_C_UP_CMDS             0x106E0\r
+#define AUD_E_UP_CMDS             0x10730\r
+#define MBIF_A_DOWN_CMDS          0x10780\r
+#define MBIF_B_DOWN_CMDS          0x107D0\r
+#define DMA_SCRATCH_PAD           0x10820  // Scratch pad area from 0x10820 to 0x10B40\r
+\r
+//#define RX_SRAM_POOL_START        = 0x105B0;\r
+\r
+#define VID_A_IQ                  0x11000\r
+#define VID_B_IQ                  0x11040\r
+#define VID_C_IQ                  0x11080\r
+#define VID_D_IQ                  0x110C0\r
+#define VID_E_IQ                  0x11100\r
+#define VID_F_IQ                  0x11140\r
+#define VID_G_IQ                  0x11180\r
+#define VID_H_IQ                  0x111C0\r
+#define VID_I_IQ                  0x11200\r
+#define VID_J_IQ                  0x11240\r
+#define AUD_A_IQ                  0x11280\r
+#define AUD_B_IQ                  0x112C0\r
+#define AUD_C_IQ                  0x11300\r
+#define AUD_D_IQ                  0x11340\r
+#define AUD_E_IQ                  0x11380\r
+#define MBIF_A_IQ                 0x11000\r
+#define MBIF_B_IQ                 0x110C0\r
+\r
+#define VID_A_CDT                 0x10C00\r
+#define VID_B_CDT                 0x10C40\r
+#define VID_C_CDT                 0x10C80\r
+#define VID_D_CDT                 0x10CC0\r
+#define VID_E_CDT                 0x10D00\r
+#define VID_F_CDT                 0x10D40\r
+#define VID_G_CDT                 0x10D80\r
+#define VID_H_CDT                 0x10DC0\r
+#define VID_I_CDT                 0x10E00\r
+#define VID_J_CDT                 0x10E40\r
+#define AUD_A_CDT                 0x10E80\r
+#define AUD_B_CDT                 0x10EB0\r
+#define AUD_C_CDT                 0x10EE0\r
+#define AUD_D_CDT                 0x10F10\r
+#define AUD_E_CDT                 0x10F40\r
+#define MBIF_A_CDT                0x10C00\r
+#define MBIF_B_CDT                0x10CC0\r
+\r
+// Cluster Buffer for RX\r
+#define VID_A_UP_CLUSTER_1        0x11400\r
+#define VID_A_UP_CLUSTER_2        0x119A0\r
+#define VID_A_UP_CLUSTER_3        0x11F40\r
+#define VID_A_UP_CLUSTER_4        0x124E0\r
+\r
+#define VID_B_UP_CLUSTER_1        0x12A80\r
+#define VID_B_UP_CLUSTER_2        0x13020\r
+#define VID_B_UP_CLUSTER_3        0x135C0\r
+#define VID_B_UP_CLUSTER_4        0x13B60\r
+\r
+#define VID_C_UP_CLUSTER_1        0x14100\r
+#define VID_C_UP_CLUSTER_2        0x146A0\r
+#define VID_C_UP_CLUSTER_3        0x14C40\r
+#define VID_C_UP_CLUSTER_4        0x151E0\r
+\r
+#define VID_D_UP_CLUSTER_1        0x15780\r
+#define VID_D_UP_CLUSTER_2        0x15D20\r
+#define VID_D_UP_CLUSTER_3        0x162C0\r
+#define VID_D_UP_CLUSTER_4        0x16860\r
+\r
+#define VID_E_UP_CLUSTER_1        0x16E00\r
+#define VID_E_UP_CLUSTER_2        0x173A0\r
+#define VID_E_UP_CLUSTER_3        0x17940\r
+#define VID_E_UP_CLUSTER_4        0x17EE0\r
+\r
+#define VID_F_UP_CLUSTER_1        0x18480\r
+#define VID_F_UP_CLUSTER_2        0x18A20\r
+#define VID_F_UP_CLUSTER_3        0x18FC0\r
+#define VID_F_UP_CLUSTER_4        0x19560\r
+\r
+#define VID_I_UP_CLUSTER_1        0x19B00\r
+#define VID_I_UP_CLUSTER_2        0x1A0A0\r
+#define VID_I_UP_CLUSTER_3        0x1A640\r
+#define VID_I_UP_CLUSTER_4        0x1ABE0\r
+\r
+#define VID_J_UP_CLUSTER_1        0x1B180\r
+#define VID_J_UP_CLUSTER_2        0x1B720\r
+#define VID_J_UP_CLUSTER_3        0x1BCC0\r
+#define VID_J_UP_CLUSTER_4        0x1C260\r
+\r
+#define AUD_A_UP_CLUSTER_1        0x1C800\r
+#define AUD_A_UP_CLUSTER_2        0x1C880\r
+#define AUD_A_UP_CLUSTER_3        0x1C900\r
+\r
+#define AUD_B_UP_CLUSTER_1        0x1C980\r
+#define AUD_B_UP_CLUSTER_2        0x1CA00\r
+#define AUD_B_UP_CLUSTER_3        0x1CA80\r
+\r
+#define AUD_C_UP_CLUSTER_1        0x1CB00\r
+#define AUD_C_UP_CLUSTER_2        0x1CB80\r
+#define AUD_C_UP_CLUSTER_3        0x1CC00\r
+\r
+#define AUD_E_UP_CLUSTER_1        0x1CC80\r
+#define AUD_E_UP_CLUSTER_2        0x1CD00\r
+#define AUD_E_UP_CLUSTER_3        0x1CD80\r
+\r
+#define RX_SRAM_POOL_FREE         0x1CE00\r
+#define RX_SRAM_END               0x1D000\r
+\r
+// Free Receive SRAM    144 Bytes\r
+\r
+\r
+// Transmit SRAM\r
+#define TX_SRAM_POOL_START        0x00000\r
+\r
+#define VID_A_DOWN_CLUSTER_1      0x00040\r
+#define VID_A_DOWN_CLUSTER_2      0x005E0\r
+#define VID_A_DOWN_CLUSTER_3      0x00B80\r
+#define VID_A_DOWN_CLUSTER_4      0x01120\r
+\r
+#define VID_B_DOWN_CLUSTER_1      0x016C0\r
+#define VID_B_DOWN_CLUSTER_2      0x01C60\r
+#define VID_B_DOWN_CLUSTER_3      0x02200\r
+#define VID_B_DOWN_CLUSTER_4      0x027A0\r
+\r
+#define VID_C_DOWN_CLUSTER_1      0x02D40\r
+#define VID_C_DOWN_CLUSTER_2      0x032E0\r
+#define VID_C_DOWN_CLUSTER_3      0x03880\r
+#define VID_C_DOWN_CLUSTER_4      0x03E20\r
+\r
+#define VID_D_DOWN_CLUSTER_1      0x043C0\r
+#define VID_D_DOWN_CLUSTER_2      0x04960\r
+#define VID_D_DOWN_CLUSTER_3      0x04F00\r
+#define VID_D_DOWN_CLUSTER_4      0x054A0\r
+\r
+#define VID_E_DOWN_CLUSTER_1      0x05a40\r
+#define VID_E_DOWN_CLUSTER_2      0x05FE0\r
+#define VID_E_DOWN_CLUSTER_3      0x06580\r
+#define VID_E_DOWN_CLUSTER_4      0x06B20\r
+\r
+#define VID_F_DOWN_CLUSTER_1      0x070C0\r
+#define VID_F_DOWN_CLUSTER_2      0x07660\r
+#define VID_F_DOWN_CLUSTER_3      0x07C00\r
+#define VID_F_DOWN_CLUSTER_4      0x081A0\r
+\r
+#define VID_G_DOWN_CLUSTER_1      0x08740\r
+#define VID_G_DOWN_CLUSTER_2      0x08CE0\r
+#define VID_G_DOWN_CLUSTER_3      0x09280\r
+#define VID_G_DOWN_CLUSTER_4      0x09820\r
+\r
+#define VID_H_DOWN_CLUSTER_1      0x09DC0\r
+#define VID_H_DOWN_CLUSTER_2      0x0A360\r
+#define VID_H_DOWN_CLUSTER_3      0x0A900\r
+#define VID_H_DOWN_CLUSTER_4      0x0AEA0\r
+\r
+#define AUD_A_DOWN_CLUSTER_1      0x0B500\r
+#define AUD_A_DOWN_CLUSTER_2      0x0B580\r
+#define AUD_A_DOWN_CLUSTER_3      0x0B600\r
+\r
+#define AUD_B_DOWN_CLUSTER_1      0x0B680\r
+#define AUD_B_DOWN_CLUSTER_2      0x0B700\r
+#define AUD_B_DOWN_CLUSTER_3      0x0B780\r
+\r
+#define AUD_C_DOWN_CLUSTER_1      0x0B800\r
+#define AUD_C_DOWN_CLUSTER_2      0x0B880\r
+#define AUD_C_DOWN_CLUSTER_3      0x0B900\r
+\r
+#define AUD_D_DOWN_CLUSTER_1      0x0B980\r
+#define AUD_D_DOWN_CLUSTER_2      0x0BA00\r
+#define AUD_D_DOWN_CLUSTER_3      0x0BA80\r
+\r
+#define TX_SRAM_POOL_FREE         0x0BB00\r
+#define TX_SRAM_END               0x0C000\r
+\r
+\r
+#define BYTES_TO_DWORDS(bcount) ((bcount) >> 2)\r
+#define BYTES_TO_QWORDS(bcount) ((bcount) >> 3)\r
+#define BYTES_TO_OWORDS(bcount) ((bcount) >> 4)\r
+\r
+#define VID_IQ_SIZE_DW             BYTES_TO_DWORDS(VID_IQ_SIZE)\r
+#define VID_CDT_SIZE_QW            BYTES_TO_QWORDS(VID_CDT_SIZE)\r
+#define VID_CLUSTER_SIZE_OW        BYTES_TO_OWORDS(VID_CLUSTER_SIZE)\r
+\r
+#define AUDIO_IQ_SIZE_DW           BYTES_TO_DWORDS(AUDIO_IQ_SIZE)\r
+#define AUDIO_CDT_SIZE_QW          BYTES_TO_QWORDS(AUDIO_CDT_SIZE)\r
+#define AUDIO_CLUSTER_SIZE_QW      BYTES_TO_QWORDS(AUDIO_CLUSTER_SIZE)\r
+\r
+#define MBIF_IQ_SIZE_DW            BYTES_TO_DWORDS(MBIF_IQ_SIZE)\r
+#define MBIF_CDT_SIZE_QW           BYTES_TO_QWORDS(MBIF_CDT_SIZE)\r
+#define MBIF_CLUSTER_SIZE_OW       BYTES_TO_OWORDS(MBIF_CLUSTER_SIZE)\r
+\r
+\r
+#endif\r
+\r
diff --git a/drivers/staging/cx25821/cx25821-video-upstream-ch2.c b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c
new file mode 100644 (file)
index 0000000..ca91b83
--- /dev/null
@@ -0,0 +1,847 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.com>\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+\r
+#include "cx25821-video.h"\r
+#include "cx25821-video-upstream-ch2.h"     \r
+\r
+#include <linux/fs.h> \r
+#include <linux/errno.h>\r
+#include <linux/kernel.h>\r
+#include <linux/init.h>\r
+#include <linux/module.h>\r
+#include <linux/syscalls.h>\r
+#include <linux/file.h>\r
+#include <linux/fcntl.h>\r
+#include <asm/uaccess.h>\r
+\r
+\r
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");\r
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");\r
+MODULE_LICENSE("GPL");\r
+\r
+\r
+static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR;\r
+\r
+\r
+static __le32 *cx25821_update_riscprogram_ch2( struct cx25821_dev *dev,\r
+                                             __le32 *rp, unsigned int offset, unsigned int bpl, \r
+                                             u32 sync_line, unsigned int lines, int fifo_enable, int field_type)\r
+{\r
+    unsigned int line, i;\r
+    int dist_betwn_starts = bpl * 2;        \r
+    \r
+        \r
+    *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);     \r
+    \r
+    \r
+    if( USE_RISC_NOOP_VIDEO )\r
+    {\r
+        for( i = 0; i < NUM_NO_OPS; i++ )\r
+        {\r
+            *(rp++) = cpu_to_le32(RISC_NOOP);\r
+        }\r
+    }\r
+    \r
+    /* scan lines */\r
+    for (line = 0; line < lines; line++) \r
+    {       \r
+        *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); \r
+        *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2+offset);       \r
+        *(rp++) = cpu_to_le32(0); /* bits 63-32 */  \r
+        \r
+        if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC_ch2) )\r
+        {\r
+            offset += dist_betwn_starts;    \r
+        }               \r
+    }\r
+\r
+    return rp;\r
+}\r
+\r
+static __le32 *cx25821_risc_field_upstream_ch2( struct cx25821_dev *dev,\r
+                                           __le32 *rp, \r
+                                           dma_addr_t databuf_phys_addr,\r
+                                           unsigned int offset, u32 sync_line, unsigned int bpl, \r
+                                           unsigned int lines, int fifo_enable, int field_type)\r
+{\r
+    unsigned int line, i;\r
+    struct sram_channel *sram_ch = &dev->sram_channels[dev->_channel2_upstream_select];\r
+    int dist_betwn_starts = bpl * 2;        \r
+    \r
+            \r
+    /* sync instruction */\r
+    if (sync_line != NO_SYNC_LINE)\r
+    { \r
+        *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);      \r
+    }\r
+\r
+    \r
+    if( USE_RISC_NOOP_VIDEO )\r
+    {\r
+        for( i = 0; i < NUM_NO_OPS; i++ )\r
+        {\r
+            *(rp++) = cpu_to_le32(RISC_NOOP);\r
+        }\r
+    }\r
+    \r
+    /* scan lines */\r
+    for (line = 0; line < lines; line++) \r
+    {       \r
+        *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); \r
+        *(rp++) = cpu_to_le32(databuf_phys_addr+offset);          \r
+        *(rp++) = cpu_to_le32(0); /* bits 63-32 */  \r
+        \r
+        \r
+        if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC_ch2) )\r
+        {\r
+            offset += dist_betwn_starts;    \r
+        }\r
+             \r
+\r
+        // check if we need to enable the FIFO after the first 4 lines \r
+        // For the upstream video channel, the risc engine will enable the FIFO. \r
+        if ( fifo_enable && line == 3 )\r
+        {\r
+            *(rp++) = RISC_WRITECR;\r
+            *(rp++) = sram_ch->dma_ctl;\r
+            *(rp++) = FLD_VID_FIFO_EN;\r
+            *(rp++) = 0x00000001;\r
+        }        \r
+    }\r
+        \r
+    return rp;\r
+}\r
+\r
+int cx25821_risc_buffer_upstream_ch2( struct cx25821_dev *dev, struct pci_dev *pci, \r
+                                  unsigned int top_offset, \r
+                                  unsigned int bpl, unsigned int lines)\r
+{\r
+    __le32 *rp;\r
+    int fifo_enable = 0;\r
+    int singlefield_lines = lines >> 1;             //get line count for single field\r
+    int odd_num_lines     = singlefield_lines;\r
+    int frame = 0;\r
+    int frame_size = 0;\r
+    int databuf_offset = 0;\r
+    int risc_program_size = 0;\r
+    int risc_flag = RISC_CNT_RESET;\r
+    unsigned int bottom_offset = bpl;\r
+    dma_addr_t   risc_phys_jump_addr;\r
+\r
+              \r
+    if( dev->_isNTSC_ch2 )\r
+    {\r
+        odd_num_lines = singlefield_lines + 1;\r
+        risc_program_size = FRAME1_VID_PROG_SIZE;\r
+        frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;\r
+    }\r
+    else\r
+    {    \r
+        risc_program_size = PAL_VID_PROG_SIZE;  \r
+        frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;  \r
+    }\r
+  \r
+        \r
+    /* Virtual address of Risc buffer program */\r
+    rp = dev->_dma_virt_addr_ch2;\r
+    \r
+    for( frame = 0; frame < NUM_FRAMES; frame++ )\r
+    {        \r
+        databuf_offset = frame_size * frame;        \r
+        \r
+        \r
+        if (UNSET != top_offset)\r
+        {\r
+            fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;      \r
+            rp = cx25821_risc_field_upstream_ch2(dev, rp, dev->_data_buf_phys_addr_ch2 + databuf_offset, top_offset, 0, bpl, odd_num_lines, fifo_enable, ODD_FIELD);\r
+        }\r
+        \r
+        fifo_enable = FIFO_DISABLE;     \r
+        \r
+        \r
+        //Even field\r
+        rp = cx25821_risc_field_upstream_ch2(dev, rp, dev->_data_buf_phys_addr_ch2 + databuf_offset, bottom_offset, 0x200, bpl, singlefield_lines, fifo_enable, EVEN_FIELD);  \r
+\r
+        \r
+        if( frame == 0 )\r
+        {\r
+            risc_flag = RISC_CNT_RESET; \r
+            risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 + risc_program_size;    \r
+        }\r
+        else\r
+        {\r
+            risc_flag = RISC_CNT_INC;\r
+            risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2;\r
+        }\r
+                        \r
+\r
+        // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ \r
+        *(rp++)  = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag);      \r
+        *(rp++)  = cpu_to_le32(risc_phys_jump_addr);            \r
+        *(rp++)  = cpu_to_le32(0);     \r
+    }\r
+    \r
+    return 0;\r
+}\r
+\r
+\r
+void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev)\r
+{    \r
+    struct sram_channel *sram_ch = &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_J];  \r
+    u32 tmp = 0;\r
+    \r
+    if( !dev->_is_running_ch2 )\r
+    {\r
+        printk("cx25821: No video file is currently running so return!\n");\r
+        return;\r
+    }\r
+\r
+    //Disable RISC interrupts    \r
+    tmp = cx_read( sram_ch->int_msk ); \r
+    cx_write( sram_ch->int_msk, tmp & ~_intr_msk); \r
+    \r
+    //Turn OFF risc and fifo \r
+    tmp = cx_read( sram_ch->dma_ctl );\r
+    cx_write( sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN) );  \r
+\r
+    //Clear data buffer memory\r
+    if( dev->_data_buf_virt_addr_ch2 )\r
+        memset( dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2 );                     \r
+        \r
+    dev->_is_running_ch2     = 0;\r
+    dev->_is_first_frame_ch2 = 0;\r
+    dev->_frame_count_ch2    = 0;\r
+    dev->_file_status_ch2    = END_OF_FILE;  \r
+    \r
+    if( dev->_irq_queues_ch2 )\r
+    {\r
+        kfree(dev->_irq_queues_ch2); \r
+        dev->_irq_queues_ch2 = NULL; \r
+    }\r
+    \r
+    if( dev->_filename_ch2 != NULL )\r
+        kfree(dev->_filename_ch2);  \r
+\r
+    tmp = cx_read( VID_CH_MODE_SEL );\r
+    cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00);  \r
+}\r
+\r
+void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev)\r
+{     \r
+    if( dev->_is_running_ch2 )\r
+    {\r
+        cx25821_stop_upstream_video_ch2(dev);\r
+    }\r
+    \r
+    if (dev->_dma_virt_addr_ch2) \r
+    {\r
+        pci_free_consistent(dev->pci, dev->_risc_size_ch2, dev->_dma_virt_addr_ch2, dev->_dma_phys_addr_ch2);\r
+        dev->_dma_virt_addr_ch2 = NULL;\r
+    }\r
+    \r
+    if (dev->_data_buf_virt_addr_ch2) \r
+    {\r
+        pci_free_consistent(dev->pci, dev->_data_buf_size_ch2, dev->_data_buf_virt_addr_ch2, dev->_data_buf_phys_addr_ch2);\r
+        dev->_data_buf_virt_addr_ch2 = NULL;\r
+    }\r
+}\r
+\r
+\r
+int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch )\r
+{\r
+    struct file * myfile;      \r
+    int frame_index_temp = dev->_frame_index_ch2;\r
+    int i = 0;\r
+    int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;             \r
+    int frame_size = 0;\r
+    int frame_offset = 0;\r
+    ssize_t vfs_read_retval = 0;\r
+    char mybuf[line_size];      \r
+    loff_t file_offset;                     \r
+    loff_t pos;\r
+    mm_segment_t old_fs;\r
+        \r
+\r
+    if( dev->_file_status_ch2 == END_OF_FILE )   \r
+        return 0;\r
+        \r
+    if( dev->_isNTSC_ch2 )\r
+    {\r
+        frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;\r
+    }\r
+    else\r
+    { \r
+        frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;\r
+    }\r
+    \r
+    frame_offset = (frame_index_temp > 0) ? frame_size : 0; \r
+    file_offset = dev->_frame_count_ch2 * frame_size; \r
+    \r
+        \r
+    myfile = filp_open( dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0 );\r
+    \r
+    \r
+    if (IS_ERR(myfile)) \r
+    {\r
+        const int open_errno = -PTR_ERR(myfile);\r
+        printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename_ch2, open_errno);\r
+        return PTR_ERR(myfile);        \r
+    } \r
+    else \r
+    {   \r
+        if( !(myfile->f_op) )\r
+        {            \r
+            printk("%s: File has no file operations registered!", __func__);\r
+            filp_close(myfile, NULL);\r
+            return -EIO;\r
+        }\r
+        \r
+        \r
+        if( !myfile->f_op->read )\r
+        {            \r
+            printk("%s: File has no READ operations registered!", __func__);\r
+            filp_close(myfile, NULL);\r
+            return -EIO;\r
+        }\r
+        \r
+        pos = myfile->f_pos;            \r
+        old_fs = get_fs();      \r
+        set_fs(KERNEL_DS);\r
+                \r
+           \r
+        for( i = 0; i < dev->_lines_count_ch2; i++ )\r
+        {\r
+            pos = file_offset;      \r
+            \r
+            vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos);     \r
+              \r
+            if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr_ch2 != NULL )   \r
+            {\r
+                memcpy( (void*)(dev->_data_buf_virt_addr_ch2+frame_offset/4), mybuf, vfs_read_retval);  \r
+            }            \r
+            \r
+            file_offset += vfs_read_retval;\r
+            frame_offset += vfs_read_retval;\r
+\r
+            if( vfs_read_retval < line_size )\r
+            {      \r
+                printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ );\r
+                break;\r
+            }      \r
+        }\r
+        \r
+        if( i > 0 )         \r
+            dev->_frame_count_ch2++;       \r
+    \r
+        dev->_file_status_ch2 = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;      \r
+\r
+        \r
+        set_fs(old_fs);                 \r
+        filp_close(myfile, NULL);          \r
+    }\r
+    \r
+    return 0;\r
+}\r
+\r
+static void cx25821_vidups_handler_ch2(struct work_struct *work)\r
+{\r
+    struct cx25821_dev *dev = container_of(work, struct cx25821_dev, _irq_work_entry_ch2);\r
+       \r
+    if( !dev )\r
+    {\r
+        printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ );\r
+        return;\r
+    }\r
+    \r
+    cx25821_get_frame_ch2( dev, &dev->sram_channels[dev->_channel2_upstream_select] );\r
+}\r
+\r
+\r
+int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)\r
+{\r
+    struct file * myfile;    \r
+    int i = 0, j = 0;\r
+    int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;     \r
+    ssize_t vfs_read_retval = 0;\r
+    char mybuf[line_size];\r
+    loff_t pos;\r
+    loff_t offset = (unsigned long)0;\r
+    mm_segment_t old_fs;\r
+        \r
+\r
+    myfile = filp_open( dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0 );\r
+    \r
+    \r
+    if (IS_ERR(myfile)) \r
+    {\r
+        const int open_errno = -PTR_ERR(myfile);\r
+        printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename_ch2, open_errno);\r
+        return PTR_ERR(myfile);\r
+    } \r
+    else \r
+    {\r
+        if( !(myfile->f_op) )\r
+        {            \r
+            printk("%s: File has no file operations registered!", __func__);\r
+            filp_close(myfile, NULL);\r
+            return -EIO;\r
+        }\r
+        \r
+        \r
+        if( !myfile->f_op->read )\r
+        {            \r
+            printk("%s: File has no READ operations registered!  Returning.", __func__);\r
+            filp_close(myfile, NULL);\r
+            return -EIO;\r
+        }\r
+        \r
+        pos = myfile->f_pos;\r
+        old_fs = get_fs();      \r
+        set_fs(KERNEL_DS);\r
+                \r
+        \r
+        for( j = 0; j < NUM_FRAMES; j++ )       \r
+        {          \r
+            for( i = 0; i < dev->_lines_count_ch2; i++ )\r
+            {\r
+                pos = offset;\r
+\r
+                vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos);                \r
+                \r
+                if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr_ch2 != NULL ) \r
+                {\r
+                    memcpy( (void*)(dev->_data_buf_virt_addr_ch2+offset/4), mybuf, vfs_read_retval); \r
+                }\r
+                \r
+                \r
+                offset += vfs_read_retval;\r
+\r
+                if( vfs_read_retval < line_size )\r
+                {      \r
+                    printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ );\r
+                    break;\r
+                }      \r
+            }\r
+            \r
+            if( i > 0 )     \r
+                dev->_frame_count_ch2++;\r
+            \r
+            if( vfs_read_retval < line_size )\r
+            {\r
+                break;\r
+            }\r
+        }\r
+\r
+        dev->_file_status_ch2 = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;          \r
+            \r
+        set_fs(old_fs);        \r
+        myfile->f_pos = 0;\r
+        filp_close(myfile, NULL);        \r
+    }\r
+    \r
+    return 0;\r
+}\r
+\r
+\r
+static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev,\r
+                                           struct sram_channel *sram_ch,\r
+                                           int bpl)\r
+{\r
+    int ret = 0;\r
+    dma_addr_t dma_addr;\r
+    dma_addr_t data_dma_addr;   \r
+        \r
+       \r
+    if( dev->_dma_virt_addr_ch2 != NULL )\r
+    {    \r
+        pci_free_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, dev->_dma_virt_addr_ch2, dev->_dma_phys_addr_ch2);\r
+    }\r
+    \r
+    dev->_dma_virt_addr_ch2 = pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, &dma_addr);\r
+    dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2;      \r
+    dev->_dma_phys_start_addr_ch2 = dma_addr;        \r
+    dev->_dma_phys_addr_ch2 = dma_addr;\r
+    dev->_risc_size_ch2     = dev->upstream_riscbuf_size_ch2;\r
+       \r
+  \r
+    if (!dev->_dma_virt_addr_ch2)\r
+    {\r
+        printk("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n");\r
+        return -ENOMEM;\r
+    }\r
+\r
+\r
+    //Iniitize at this address until n bytes to 0\r
+    memset( dev->_dma_virt_addr_ch2, 0, dev->_risc_size_ch2 );\r
+\r
+    \r
+    if( dev->_data_buf_virt_addr_ch2 != NULL )\r
+    {    \r
+        pci_free_consistent(dev->pci, dev->upstream_databuf_size_ch2, dev->_data_buf_virt_addr_ch2, dev->_data_buf_phys_addr_ch2);\r
+    }\r
+    \r
+    //For Video Data buffer allocation  \r
+    dev->_data_buf_virt_addr_ch2 = pci_alloc_consistent(dev->pci, dev->upstream_databuf_size_ch2, &data_dma_addr);\r
+    dev->_data_buf_phys_addr_ch2 = data_dma_addr;\r
+    dev->_data_buf_size_ch2      = dev->upstream_databuf_size_ch2;\r
+       \r
+    if (!dev->_data_buf_virt_addr_ch2)\r
+    {\r
+        printk("cx25821: FAILED to allocate memory for data buffer! Returning.\n");\r
+        return -ENOMEM;\r
+    }\r
+  \r
\r
+    //Initialize at this address until n bytes to 0\r
+    memset( dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2 );\r
+    \r
+    \r
+    ret = cx25821_openfile_ch2(dev, sram_ch);     \r
+    if( ret < 0 )\r
+        return ret;\r
+                                           \r
+    \r
+    //Creating RISC programs\r
+    ret = cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0,  bpl, dev->_lines_count_ch2 );                                \r
+    if (ret < 0)\r
+    {\r
+        printk(KERN_INFO "cx25821: Failed creating Video Upstream Risc programs! \n");\r
+        goto error;\r
+    }\r
+       \r
+    return 0;\r
+\r
+error:\r
+    return ret;\r
+}\r
+\r
+int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, u32 status)\r
+{\r
+    u32 int_msk_tmp;\r
+    struct sram_channel *channel = &dev->sram_channels[chan_num];\r
+    int singlefield_lines = NTSC_FIELD_HEIGHT; \r
+    int line_size_in_bytes = Y422_LINE_SZ;  \r
+    int odd_risc_prog_size = 0;    \r
+    dma_addr_t   risc_phys_jump_addr;\r
+    __le32 * rp;\r
+\r
+    \r
+    \r
+    if (status & FLD_VID_SRC_RISC1)      \r
+    {\r
+        // We should only process one program per call\r
+        u32 prog_cnt = cx_read( channel->gpcnt );\r
+    \r
+        //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers\r
+        int_msk_tmp = cx_read(channel->int_msk); \r
+        cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); \r
+        cx_write( channel->int_stat, _intr_msk ); \r
+        \r
+        spin_lock(&dev->slock);     \r
+            \r
+        dev->_frame_index_ch2 = prog_cnt;\r
+\r
+        queue_work(dev->_irq_queues_ch2, &dev->_irq_work_entry_ch2);         \r
+               \r
+        \r
+        if ( dev->_is_first_frame_ch2 )\r
+        {\r
+            dev->_is_first_frame_ch2 = 0;\r
+    \r
+            if( dev->_isNTSC_ch2 )\r
+            {\r
+                singlefield_lines += 1;\r
+                odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE;\r
+            }\r
+            else\r
+            {\r
+                singlefield_lines = PAL_FIELD_HEIGHT; \r
+                odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE;  \r
+            }\r
+\r
+            \r
+            if( dev->_dma_virt_start_addr_ch2 != NULL )\r
+            {\r
+                line_size_in_bytes = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;\r
+                risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 + odd_risc_prog_size;        \r
+                \r
+                rp = cx25821_update_riscprogram_ch2(dev, dev->_dma_virt_start_addr_ch2, TOP_OFFSET, line_size_in_bytes, 0x0, singlefield_lines, FIFO_DISABLE, ODD_FIELD);                        \r
+\r
+                // Jump to Even Risc program of 1st Frame \r
+                *(rp++)  = cpu_to_le32(RISC_JUMP);      \r
+                *(rp++)  = cpu_to_le32(risc_phys_jump_addr);            \r
+                *(rp++)  = cpu_to_le32(0); \r
+            }\r
+        }\r
+        \r
+        spin_unlock(&dev->slock);       \r
+    }\r
+\r
+        \r
+    if( dev->_file_status_ch2 == END_OF_FILE )\r
+    {                       \r
+        printk("cx25821: EOF Channel 2 Framecount = %d\n", dev->_frame_count_ch2 );\r
+        return -1;\r
+    }\r
+    \r
+    //ElSE, set the interrupt mask register, re-enable irq. \r
+    int_msk_tmp = cx_read( channel->int_msk );\r
+    cx_write( channel->int_msk, int_msk_tmp |= _intr_msk ); \r
+       \r
+    return 0;\r
+}\r
+\r
+static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id)\r
+{\r
+    struct cx25821_dev *dev = dev_id;\r
+    u32 msk_stat, vid_status;\r
+    int handled = 0;    \r
+    int channel_num = 0;\r
+    struct sram_channel *sram_ch;\r
+    \r
+    \r
+    if( !dev )\r
+        return -1;\r
+\r
+    channel_num = VID_UPSTREAM_SRAM_CHANNEL_J;\r
+         \r
+    sram_ch = &dev->sram_channels[channel_num];     \r
+\r
+    msk_stat   = cx_read(sram_ch->int_mstat);     \r
+    vid_status = cx_read(sram_ch->int_stat);  \r
+    \r
+    // Only deal with our interrupt\r
+    if(vid_status)\r
+    {\r
+        handled = cx25821_video_upstream_irq_ch2(dev, channel_num, vid_status);     \r
+    }\r
+    \r
+    \r
+    if( handled < 0 )\r
+    {    \r
+        cx25821_stop_upstream_video_ch2(dev);             \r
+    }\r
+    else\r
+    {\r
+        handled += handled;    \r
+    }\r
+\r
+    return IRQ_RETVAL(handled);\r
+}\r
+\r
+\r
+static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev, struct sram_channel *ch, int pix_format)\r
+{\r
+    int width = WIDTH_D1;               \r
+    int height = dev->_lines_count_ch2; \r
+    int num_lines, odd_num_lines;\r
+    u32 value;\r
+    int vip_mode = PIXEL_ENGINE_VIP1;\r
+       \r
+        \r
+    value = ( (pix_format & 0x3) << 12 ) | ( vip_mode & 0x7 );\r
+    value &= 0xFFFFFFEF;\r
+    value |= dev->_isNTSC_ch2 ? 0 : 0x10;\r
+    cx_write( ch->vid_fmt_ctl, value );\r
+    \r
+    // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format\r
+    cx_write( ch->vid_active_ctl1, width );\r
+    \r
+    num_lines = (height / 2) & 0x3FF;\r
+    odd_num_lines = num_lines;\r
+\r
+    if(dev->_isNTSC_ch2)\r
+    {\r
+        odd_num_lines += 1; \r
+    }\r
+\r
+    value = (num_lines << 16) | odd_num_lines;\r
+    \r
+    // set number of active lines in field 0 (top) and field 1 (bottom)\r
+    cx_write( ch->vid_active_ctl2, value );    \r
+\r
+    cx_write( ch->vid_cdt_size, VID_CDT_SIZE >> 3 );\r
+}\r
+\r
+\r
+int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev,\r
+                                     struct sram_channel *sram_ch)\r
+{\r
+    u32 tmp = 0;\r
+    int err = 0;\r
+    \r
+    \r
+    // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C\r
+    tmp = cx_read( VID_CH_MODE_SEL );\r
+    cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF);  \r
+       \r
+    \r
+    // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds.\r
+    cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr_ch2);\r
+    cx_write(sram_ch->cmds_start +  4, 0); /* Risc IPC High 64 bits 63-32 */\r
+    \r
+    /* reset counter */\r
+    cx_write(sram_ch->gpcnt_ctl, 3); \r
+\r
+    // Clear our bits from the interrupt status register.  \r
+    cx_write( sram_ch->int_stat, _intr_msk );\r
+\r
+    \r
+    //Set the interrupt mask register, enable irq.  \r
+    cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));\r
+    tmp = cx_read( sram_ch->int_msk );\r
+    cx_write( sram_ch->int_msk, tmp |= _intr_msk );    \r
+    \r
+    \r
+    err = request_irq(dev->pci->irq, cx25821_upstream_irq_ch2, IRQF_SHARED | IRQF_DISABLED, dev->name, dev);\r
+    if (err < 0) \r
+    {\r
+        printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq);\r
+        goto fail_irq;\r
+    } \r
+    \r
+    // Start the DMA  engine\r
+    tmp = cx_read( sram_ch->dma_ctl );\r
+    cx_set( sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN );  \r
+\r
+    dev->_is_running_ch2 = 1; \r
+    dev->_is_first_frame_ch2 = 1;          \r
+    \r
+    return 0;\r
+    \r
+\r
+fail_irq:\r
+    cx25821_dev_unregister(dev);  \r
+    return err;\r
+}\r
+\r
+\r
+int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, int pixel_format)\r
+{\r
+    struct sram_channel *sram_ch; \r
+    u32 tmp;      \r
+    int retval = 0;\r
+    int err = 0;    \r
+    int data_frame_size = 0;\r
+    int risc_buffer_size = 0;\r
+    int str_length = 0;\r
+    \r
+    if( dev->_is_running_ch2 ) \r
+    {\r
+        printk("Video Channel is still running so return!\n");\r
+        return 0;\r
+    }\r
+    \r
+    dev->_channel2_upstream_select = channel_select;      \r
+    sram_ch = &dev->sram_channels[channel_select];   \r
+    \r
+    \r
+    INIT_WORK(&dev->_irq_work_entry_ch2, cx25821_vidups_handler_ch2);\r
+    dev->_irq_queues_ch2 = create_singlethread_workqueue("cx25821_workqueue2");   \r
+\r
+    if(!dev->_irq_queues_ch2)\r
+    {\r
+        printk("cx25821: create_singlethread_workqueue() for Video FAILED!\n");\r
+        return -ENOMEM;\r
+    }\r
+    \r
+    // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C\r
+    tmp = cx_read( VID_CH_MODE_SEL );\r
+    cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF);       \r
+    \r
+          \r
+    dev->_is_running_ch2   = 0;    \r
+    dev->_frame_count_ch2  = 0;\r
+    dev->_file_status_ch2  = RESET_STATUS;  \r
+    dev->_lines_count_ch2  = dev->_isNTSC_ch2 ? 480 : 576; \r
+    dev->_pixel_format_ch2 = pixel_format;       \r
+    dev->_line_size_ch2    = (dev->_pixel_format_ch2 == PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;   \r
+    data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;        \r
+    risc_buffer_size = dev->_isNTSC_ch2 ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;\r
+    \r
+        \r
+    if( dev->input_filename_ch2 )\r
+    {\r
+        str_length = strlen(dev->input_filename_ch2);\r
+        dev->_filename_ch2 = (char *) kmalloc(str_length + 1, GFP_KERNEL);\r
+        \r
+        if( !dev->_filename_ch2 )\r
+            goto error;\r
+            \r
+        memcpy(dev->_filename_ch2, dev->input_filename_ch2, str_length + 1);    \r
+    }\r
+    else\r
+    {\r
+        str_length = strlen(dev->_defaultname_ch2);       \r
+        dev->_filename_ch2 = (char *) kmalloc(str_length + 1, GFP_KERNEL);\r
+        \r
+        if( !dev->_filename_ch2 )\r
+            goto error;\r
+            \r
+        memcpy(dev->_filename_ch2, dev->_defaultname_ch2, str_length + 1);\r
+    }\r
+        \r
+    \r
+    //Default if filename is empty string \r
+    if( strcmp(dev->input_filename_ch2,"") == 0)        \r
+    {\r
+        if( dev->_isNTSC_ch2 )\r
+        {\r
+            dev->_filename_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? "/root/vid411.yuv" : "/root/vidtest.yuv";\r
+        }\r
+        else\r
+        {\r
+            dev->_filename_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? "/root/pal411.yuv" : "/root/pal422.yuv";    \r
+        }\r
+    }\r
+        \r
+        \r
+    retval = cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size_ch2, 0);   \r
+    \r
+    \r
+    /* setup fifo + format */\r
+    cx25821_set_pixelengine_ch2(dev, sram_ch, dev->_pixel_format_ch2);       \r
+\r
+    dev->upstream_riscbuf_size_ch2 = risc_buffer_size * 2;      \r
+    dev->upstream_databuf_size_ch2 = data_frame_size * 2;       \r
\r
+     \r
+    //Allocating buffers and prepare RISC program\r
+    retval = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch, dev->_line_size_ch2);\r
+    if (retval < 0) \r
+    {\r
+        printk(KERN_ERR "%s: Failed to set up Video upstream buffers!\n", dev->name);\r
+        goto error;\r
+    }\r
+    \r
+      \r
+    cx25821_start_video_dma_upstream_ch2(dev, sram_ch);                                     \r
+    \r
+    return 0;\r
+    \r
+error:\r
+    cx25821_dev_unregister(dev);\r
+    \r
+    return err;\r
+}\r
+       \r
diff --git a/drivers/staging/cx25821/cx25821-video-upstream-ch2.h b/drivers/staging/cx25821/cx25821-video-upstream-ch2.h
new file mode 100644 (file)
index 0000000..71de874
--- /dev/null
@@ -0,0 +1,107 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.com>\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+#include <linux/mutex.h>\r
+#include <linux/workqueue.h>\r
+\r
+\r
+#define OPEN_FILE_1           0\r
+#define NUM_PROGS             8\r
+#define NUM_FRAMES            2\r
+#define ODD_FIELD             0\r
+#define EVEN_FIELD            1 \r
+#define TOP_OFFSET            0\r
+#define FIFO_DISABLE          0\r
+#define FIFO_ENABLE           1\r
+#define TEST_FRAMES           5\r
+#define END_OF_FILE           0\r
+#define IN_PROGRESS           1\r
+#define RESET_STATUS          -1\r
+#define NUM_NO_OPS            5\r
+\r
+\r
+\r
+// PAL and NTSC line sizes and number of lines.\r
+#define WIDTH_D1              720\r
+#define NTSC_LINES_PER_FRAME  480\r
+#define PAL_LINES_PER_FRAME   576\r
+#define PAL_LINE_SZ           1440\r
+#define Y422_LINE_SZ          1440\r
+#define Y411_LINE_SZ          1080\r
+#define NTSC_FIELD_HEIGHT     240\r
+#define NTSC_ODD_FLD_LINES    241\r
+#define PAL_FIELD_HEIGHT      288\r
+\r
+#define FRAME_SIZE_NTSC_Y422    (NTSC_LINES_PER_FRAME * Y422_LINE_SZ)\r
+#define FRAME_SIZE_NTSC_Y411    (NTSC_LINES_PER_FRAME * Y411_LINE_SZ)\r
+#define FRAME_SIZE_PAL_Y422     (PAL_LINES_PER_FRAME * Y422_LINE_SZ)\r
+#define FRAME_SIZE_PAL_Y411     (PAL_LINES_PER_FRAME * Y411_LINE_SZ)\r
+\r
+#define NTSC_DATA_BUF_SZ        (Y422_LINE_SZ * NTSC_LINES_PER_FRAME)\r
+#define PAL_DATA_BUF_SZ         (Y422_LINE_SZ * PAL_LINES_PER_FRAME)\r
+\r
+#define RISC_WRITECR_INSTRUCTION_SIZE   16\r
+#define RISC_SYNC_INSTRUCTION_SIZE      4\r
+#define JUMP_INSTRUCTION_SIZE           12\r
+#define MAXSIZE_NO_OPS                  36\r
+#define DWORD_SIZE                      4\r
+\r
+\r
+\r
+#define USE_RISC_NOOP_VIDEO   1\r
+\r
+#ifdef USE_RISC_NOOP_VIDEO\r
+#define PAL_US_VID_PROG_SIZE      ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +   \\r
+                                    RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE)\r
+                                    \r
+#define PAL_RISC_BUF_SIZE         (2 * PAL_US_VID_PROG_SIZE)\r
+\r
+#define PAL_VID_PROG_SIZE         ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \\r
+                                    RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) \r
+\r
+#define ODD_FLD_PAL_PROG_SIZE     ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \\r
+                                    RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE) \r
+\r
+#define NTSC_US_VID_PROG_SIZE     ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \\r
+                                    JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE)   \r
+                                    \r
+#define NTSC_RISC_BUF_SIZE        (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))         \r
+\r
+#define FRAME1_VID_PROG_SIZE      ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \\r
+                                    RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE)   \r
+#define ODD_FLD_NTSC_PROG_SIZE    ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \\r
+                                    RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE)    \r
+#endif\r
+\r
+\r
+#ifndef USE_RISC_NOOP_VIDEO\r
+#define PAL_US_VID_PROG_SIZE      ((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE )\r
+#define PAL_RISC_BUF_SIZE         ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE) )\r
+#define PAL_VID_PROG_SIZE         ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \\r
+                                    RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) \r
+#define ODD_FLD_PAL_PROG_SIZE     ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE )\r
+#define ODD_FLD_NTSC_PROG_SIZE    ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE )\r
+#define NTSC_US_VID_PROG_SIZE     ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)   \r
+#define NTSC_RISC_BUF_SIZE        (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) )     \r
+#define FRAME1_VID_PROG_SIZE      ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \\r
+                                    RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE )\r
+#endif\r
diff --git a/drivers/staging/cx25821/cx25821-video-upstream.c b/drivers/staging/cx25821/cx25821-video-upstream.c
new file mode 100644 (file)
index 0000000..14d204a
--- /dev/null
@@ -0,0 +1,923 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.com>\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+\r
+#include "cx25821-video.h"\r
+#include "cx25821-video-upstream.h"\r
+\r
+#include <linux/fs.h> \r
+#include <linux/errno.h>\r
+#include <linux/kernel.h>\r
+#include <linux/init.h>\r
+#include <linux/module.h>\r
+#include <linux/syscalls.h>\r
+#include <linux/file.h>\r
+#include <linux/fcntl.h>\r
+#include <asm/uaccess.h>\r
+\r
+\r
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");\r
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");\r
+MODULE_LICENSE("GPL");\r
+\r
+\r
+static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR;\r
+    \r
+int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev,\r
+                                        struct sram_channel *ch,\r
+                                        unsigned int bpl, u32 risc)\r
+{\r
+    unsigned int i, lines;\r
+    u32 cdt;\r
+    \r
+    \r
+    if (ch->cmds_start == 0) {\r
+        cx_write(ch->ptr1_reg, 0);\r
+        cx_write(ch->ptr2_reg, 0);\r
+        cx_write(ch->cnt2_reg, 0);\r
+        cx_write(ch->cnt1_reg, 0);\r
+        return 0;\r
+    } \r
+\r
+    bpl   = (bpl + 7) & ~7; /* alignment */\r
+    cdt   = ch->cdt;\r
+    lines = ch->fifo_size / bpl;\r
+    \r
+    if (lines > 4)  \r
+    {\r
+        lines = 4;\r
+    }\r
+    \r
+    BUG_ON(lines < 2);\r
+\r
+\r
+    /* write CDT */\r
+    for (i = 0; i < lines; i++) {\r
+        cx_write(cdt + 16*i, ch->fifo_start + bpl*i);\r
+        cx_write(cdt + 16*i +  4, 0);\r
+        cx_write(cdt + 16*i +  8, 0);\r
+        cx_write(cdt + 16*i + 12, 0);\r
+    }\r
+\r
+    /* write CMDS */    \r
+    cx_write(ch->cmds_start + 0, risc);         \r
+    \r
+    cx_write(ch->cmds_start +  4, 0); \r
+    cx_write(ch->cmds_start +  8, cdt);             \r
+    cx_write(ch->cmds_start + 12, (lines*16) >> 3);       \r
+    cx_write(ch->cmds_start + 16, ch->ctrl_start);  \r
+                                               \r
+\r
+    cx_write(ch->cmds_start + 20, VID_IQ_SIZE_DW);     \r
+\r
+    for (i = 24; i < 80; i += 4)\r
+        cx_write(ch->cmds_start + i, 0);\r
+\r
+    /* fill registers */\r
+    cx_write(ch->ptr1_reg, ch->fifo_start);\r
+    cx_write(ch->ptr2_reg, cdt);\r
+    cx_write(ch->cnt2_reg, (lines*16) >> 3);        \r
+    cx_write(ch->cnt1_reg, (bpl >> 3) - 1);         \r
+\r
+    return 0;\r
+}\r
+\r
+static __le32 *cx25821_update_riscprogram( struct cx25821_dev *dev,\r
+                                             __le32 *rp, unsigned int offset, unsigned int bpl, \r
+                                             u32 sync_line, unsigned int lines, int fifo_enable, int field_type)\r
+{\r
+    unsigned int line, i;\r
+    int dist_betwn_starts = bpl * 2;        \r
+    \r
+    \r
+    *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);   \r
+    \r
+    \r
+    if( USE_RISC_NOOP_VIDEO )\r
+    {\r
+        for( i = 0; i < NUM_NO_OPS; i++ )\r
+        {\r
+            *(rp++) = cpu_to_le32(RISC_NOOP);\r
+        }\r
+    }\r
+    \r
+    /* scan lines */\r
+    for (line = 0; line < lines; line++) \r
+    {       \r
+        *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); \r
+        *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr+offset);       \r
+        *(rp++) = cpu_to_le32(0); /* bits 63-32 */  \r
+        \r
+        if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC) )\r
+        {\r
+            offset += dist_betwn_starts;    \r
+        }   \r
+    }\r
+\r
+    return rp;\r
+}\r
+\r
+static __le32 *cx25821_risc_field_upstream( struct cx25821_dev *dev, __le32 *rp, \r
+                                           dma_addr_t databuf_phys_addr,\r
+                                           unsigned int offset, u32 sync_line,\r
+                                           unsigned int bpl, unsigned int lines, int fifo_enable, int field_type)\r
+{\r
+    unsigned int line, i; \r
+    struct sram_channel *sram_ch = &dev->sram_channels[dev->_channel_upstream_select];\r
+    int dist_betwn_starts = bpl * 2;        \r
+    \r
+            \r
+    /* sync instruction */\r
+    if (sync_line != NO_SYNC_LINE)\r
+    {\r
+        *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);       \r
+    }\r
+\r
+    \r
+    if( USE_RISC_NOOP_VIDEO )\r
+    {\r
+        for( i = 0; i < NUM_NO_OPS; i++ )\r
+        {\r
+            *(rp++) = cpu_to_le32(RISC_NOOP);\r
+        }\r
+    }\r
+    \r
+    /* scan lines */\r
+    for (line = 0; line < lines; line++) \r
+    {       \r
+        *(rp++) = cpu_to_le32(RISC_READ|RISC_SOL|RISC_EOL|bpl); \r
+        *(rp++) = cpu_to_le32(databuf_phys_addr+offset);        \r
+        *(rp++) = cpu_to_le32(0); /* bits 63-32 */  \r
+        \r
+        \r
+        if ( (lines <= NTSC_FIELD_HEIGHT) || (line < (NTSC_FIELD_HEIGHT-1)) || !(dev->_isNTSC) )\r
+        {\r
+            offset += dist_betwn_starts;    //to skip the other field line\r
+        }\r
+             \r
+\r
+        // check if we need to enable the FIFO after the first 4 lines \r
+        // For the upstream video channel, the risc engine will enable the FIFO. \r
+        if ( fifo_enable && line == 3 )\r
+        {\r
+            *(rp++) = RISC_WRITECR;\r
+            *(rp++) = sram_ch->dma_ctl;\r
+            *(rp++) = FLD_VID_FIFO_EN;\r
+            *(rp++) = 0x00000001;\r
+        }        \r
+    }\r
+        \r
+    return rp;\r
+}\r
+\r
+int cx25821_risc_buffer_upstream( struct cx25821_dev *dev, \r
+                                  struct pci_dev *pci, \r
+                                  unsigned int top_offset, \r
+                                  unsigned int bpl, unsigned int lines)\r
+{\r
+    __le32 *rp;\r
+    int fifo_enable = 0;\r
+    int singlefield_lines = lines >> 1;             //get line count for single field\r
+    int odd_num_lines     = singlefield_lines;\r
+    int frame = 0;\r
+    int frame_size = 0;\r
+    int databuf_offset = 0;\r
+    int risc_program_size = 0;\r
+    int risc_flag = RISC_CNT_RESET;\r
+    unsigned int bottom_offset = bpl;\r
+    dma_addr_t   risc_phys_jump_addr;\r
+              \r
+    if( dev->_isNTSC )\r
+    {\r
+        odd_num_lines = singlefield_lines + 1;\r
+        risc_program_size = FRAME1_VID_PROG_SIZE;\r
+        frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;\r
+    }\r
+    else\r
+    {\r
+        risc_program_size = PAL_VID_PROG_SIZE;  \r
+        frame_size = (bpl == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;  \r
+    }\r
+       \r
+        \r
+    /* Virtual address of Risc buffer program */\r
+    rp = dev->_dma_virt_addr;\r
+    \r
+    for( frame = 0; frame < NUM_FRAMES; frame++ )\r
+    {        \r
+        databuf_offset = frame_size * frame;     \r
+        \r
+        if (UNSET != top_offset)\r
+        {\r
+            fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;      \r
+            rp = cx25821_risc_field_upstream(dev, rp, dev->_data_buf_phys_addr+databuf_offset, top_offset, 0, bpl, odd_num_lines, fifo_enable, ODD_FIELD);\r
+        }\r
+\r
+        \r
+        fifo_enable = FIFO_DISABLE;     \r
+        \r
+        \r
+        //Even Field\r
+        rp = cx25821_risc_field_upstream(dev, rp, dev->_data_buf_phys_addr+databuf_offset, bottom_offset, 0x200, bpl, singlefield_lines, fifo_enable, EVEN_FIELD);  \r
+\r
+        \r
+        if( frame == 0 )\r
+        {\r
+            risc_flag = RISC_CNT_RESET;   \r
+            risc_phys_jump_addr = dev->_dma_phys_start_addr + risc_program_size;        \r
+        }\r
+        else\r
+        {\r
+            risc_phys_jump_addr = dev->_dma_phys_start_addr;\r
+            risc_flag = RISC_CNT_INC;\r
+        }\r
+                \r
+\r
+        // Loop to 2ndFrameRISC or to Start of Risc program & generate IRQ \r
+        *(rp++)  = cpu_to_le32(RISC_JUMP|RISC_IRQ1|risc_flag);      \r
+        *(rp++)  = cpu_to_le32(risc_phys_jump_addr);            \r
+        *(rp++)  = cpu_to_le32(0);    \r
+    }\r
+    \r
+    return 0;\r
+}\r
+\r
+\r
+void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev)\r
+{    \r
+    struct sram_channel *sram_ch = &dev->sram_channels[VID_UPSTREAM_SRAM_CHANNEL_I];\r
+    u32 tmp = 0;\r
+    \r
+    if( !dev->_is_running )\r
+    {\r
+        printk("cx25821: No video file is currently running so return!\n");\r
+        return;\r
+    }\r
+        \r
+    //Disable RISC interrupts    \r
+    tmp = cx_read( sram_ch->int_msk ); \r
+    cx_write( sram_ch->int_msk, tmp & ~_intr_msk); \r
+    \r
+    //Turn OFF risc and fifo enable\r
+    tmp = cx_read( sram_ch->dma_ctl );\r
+    cx_write( sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN) );  \r
+\r
+    //Clear data buffer memory\r
+    if( dev->_data_buf_virt_addr )\r
+        memset( dev->_data_buf_virt_addr, 0, dev->_data_buf_size ); \r
+        \r
+    dev->_is_running     = 0;\r
+    dev->_is_first_frame = 0;\r
+    dev->_frame_count    = 0;\r
+    dev->_file_status    = END_OF_FILE;  \r
+\r
+    if( dev->_irq_queues )\r
+    {\r
+        kfree(dev->_irq_queues); \r
+        dev->_irq_queues = NULL; \r
+    }\r
+    \r
+    if( dev->_filename != NULL )\r
+        kfree(dev->_filename);  \r
+\r
+    tmp = cx_read( VID_CH_MODE_SEL );\r
+    cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00);  \r
+}\r
+\r
+void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev)\r
+{        \r
+    if( dev->_is_running )     \r
+    {\r
+        cx25821_stop_upstream_video_ch1(dev);\r
+    }\r
+    \r
+    if (dev->_dma_virt_addr) \r
+    {\r
+        pci_free_consistent(dev->pci, dev->_risc_size, dev->_dma_virt_addr, dev->_dma_phys_addr);\r
+        dev->_dma_virt_addr = NULL;\r
+    }\r
+    \r
+    if (dev->_data_buf_virt_addr) \r
+    {\r
+        pci_free_consistent(dev->pci, dev->_data_buf_size, dev->_data_buf_virt_addr, dev->_data_buf_phys_addr);\r
+        dev->_data_buf_virt_addr = NULL;\r
+    }\r
+}\r
+\r
+\r
+int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch )\r
+{\r
+    struct file * myfile;        \r
+    int frame_index_temp = dev->_frame_index;\r
+    int i = 0;\r
+    int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;             \r
+    int frame_size = 0;\r
+    int frame_offset = 0;\r
+    ssize_t vfs_read_retval = 0;\r
+    char mybuf[line_size];      \r
+    loff_t file_offset;                     \r
+    loff_t pos;\r
+    mm_segment_t old_fs;\r
+        \r
+\r
+    if( dev->_file_status == END_OF_FILE )   \r
+        return 0;\r
+        \r
+    if( dev->_isNTSC )\r
+    {\r
+        frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;\r
+    }\r
+    else\r
+    { \r
+        frame_size = (line_size == Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;\r
+    }\r
+    \r
+    frame_offset = (frame_index_temp > 0) ? frame_size : 0; \r
+    file_offset = dev->_frame_count * frame_size; \r
+    \r
+          \r
+    myfile = filp_open( dev->_filename, O_RDONLY | O_LARGEFILE, 0 );\r
+    \r
+    \r
+    if (IS_ERR(myfile)) \r
+    {\r
+        const int open_errno = -PTR_ERR(myfile);\r
+        printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename, open_errno);\r
+        return PTR_ERR(myfile);\r
+    } \r
+    else \r
+    {   \r
+        if( !(myfile->f_op) )\r
+        {            \r
+            printk("%s: File has no file operations registered!", __func__);\r
+            filp_close(myfile, NULL);\r
+            return -EIO;\r
+        }\r
+        \r
+        \r
+        if( !myfile->f_op->read )\r
+        {            \r
+            printk("%s: File has no READ operations registered!", __func__);\r
+            filp_close(myfile, NULL);\r
+            return -EIO;\r
+        }\r
+        \r
+        pos = myfile->f_pos;            \r
+        old_fs = get_fs();      \r
+        set_fs(KERNEL_DS);\r
+                \r
+           \r
+        for( i = 0; i < dev->_lines_count; i++ )\r
+        {\r
+            pos = file_offset;      \r
+            \r
+            vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos);     \r
+              \r
+            if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr != NULL )   \r
+            {\r
+                memcpy( (void*)(dev->_data_buf_virt_addr+frame_offset/4), mybuf, vfs_read_retval);   \r
+            }            \r
+            \r
+            file_offset += vfs_read_retval;\r
+            frame_offset += vfs_read_retval;\r
+\r
+            if( vfs_read_retval < line_size )\r
+            {      \r
+                printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ );\r
+                break;\r
+            }      \r
+        }\r
+        \r
+        if( i > 0 )         \r
+            dev->_frame_count++;       \r
+    \r
+        dev->_file_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;      \r
+\r
+        \r
+        set_fs(old_fs);                 \r
+        filp_close(myfile, NULL);          \r
+    }\r
+    \r
+    return 0;\r
+}\r
+\r
+static void cx25821_vidups_handler(struct work_struct *work)\r
+{\r
+    struct cx25821_dev *dev = container_of(work, struct cx25821_dev, _irq_work_entry); \r
+       \r
+    if( !dev )\r
+    {\r
+        printk("ERROR %s(): since container_of(work_struct) FAILED! \n", __func__ );\r
+        return;\r
+    }\r
+    \r
+    cx25821_get_frame( dev, &dev->sram_channels[dev->_channel_upstream_select] );\r
+}\r
+\r
+\r
+int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)\r
+{\r
+    struct file * myfile;  \r
+    int i = 0, j = 0;\r
+    int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;     \r
+    ssize_t vfs_read_retval = 0;\r
+    char mybuf[line_size];\r
+    loff_t pos;\r
+    loff_t offset = (unsigned long)0;\r
+    mm_segment_t old_fs;\r
+        \r
+\r
+    myfile = filp_open( dev->_filename, O_RDONLY | O_LARGEFILE, 0 );\r
+    \r
+    \r
+    if (IS_ERR(myfile)) \r
+    {\r
+        const int open_errno = -PTR_ERR(myfile);\r
+        printk("%s(): ERROR opening file(%s) with errno = %d! \n", __func__, dev->_filename, open_errno);\r
+        return PTR_ERR(myfile);\r
+    } \r
+    else \r
+    {   \r
+        if( !(myfile->f_op) )\r
+        {            \r
+            printk("%s: File has no file operations registered!", __func__);\r
+            filp_close(myfile, NULL);\r
+            return -EIO;\r
+        }\r
+        \r
+        \r
+        if( !myfile->f_op->read )\r
+        {            \r
+            printk("%s: File has no READ operations registered!  Returning.", __func__);\r
+            filp_close(myfile, NULL);\r
+            return -EIO;\r
+        }\r
+        \r
+        pos = myfile->f_pos;\r
+        old_fs = get_fs();  \r
+        set_fs(KERNEL_DS);\r
+                \r
+        \r
+        for( j = 0; j < NUM_FRAMES; j++ )       \r
+        {          \r
+            for( i = 0; i < dev->_lines_count; i++ )\r
+            {\r
+                pos = offset;\r
+\r
+                vfs_read_retval = vfs_read(myfile, mybuf, line_size, &pos);                \r
+                \r
+                if( vfs_read_retval > 0 && vfs_read_retval == line_size && dev->_data_buf_virt_addr != NULL ) \r
+                {                                        \r
+                    memcpy( (void*)(dev->_data_buf_virt_addr+offset/4), mybuf, vfs_read_retval);   \r
+                }\r
+                \r
+                \r
+                offset += vfs_read_retval;\r
+\r
+                if( vfs_read_retval < line_size )\r
+                {      \r
+                    printk(KERN_INFO "Done: exit %s() since no more bytes to read from Video file.\n", __func__ );\r
+                    break;\r
+                }      \r
+            }\r
+            \r
+            if( i > 0 )     \r
+                dev->_frame_count++;\r
+            \r
+            if( vfs_read_retval < line_size )\r
+            {\r
+                break;\r
+            }\r
+        }\r
+                 \r
+\r
+        dev->_file_status = (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE;  \r
+        \r
+        set_fs(old_fs);        \r
+        myfile->f_pos = 0;\r
+        filp_close(myfile, NULL);        \r
+    }\r
+    \r
+    return 0;\r
+}\r
+\r
+\r
+int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,\r
+                                           struct sram_channel *sram_ch,\r
+                                           int bpl)\r
+{\r
+    int ret = 0;\r
+    dma_addr_t dma_addr;\r
+    dma_addr_t data_dma_addr;        \r
+       \r
+    if( dev->_dma_virt_addr != NULL )\r
+    {    \r
+        pci_free_consistent(dev->pci, dev->upstream_riscbuf_size, dev->_dma_virt_addr, dev->_dma_phys_addr);\r
+    }\r
+    \r
+    \r
+    dev->_dma_virt_addr = pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size, &dma_addr);\r
+    dev->_dma_virt_start_addr = dev->_dma_virt_addr;      \r
+    dev->_dma_phys_start_addr = dma_addr;        \r
+    dev->_dma_phys_addr = dma_addr;\r
+    dev->_risc_size     = dev->upstream_riscbuf_size;\r
+       \r
+  \r
+    if (!dev->_dma_virt_addr)\r
+    {\r
+        printk("cx25821: FAILED to allocate memory for Risc buffer! Returning.\n");\r
+        return -ENOMEM;\r
+    }\r
+\r
\r
+    //Clear memory at address \r
+    memset( dev->_dma_virt_addr, 0, dev->_risc_size );\r
+\r
+    \r
+    if( dev->_data_buf_virt_addr != NULL )\r
+    {    \r
+        pci_free_consistent(dev->pci, dev->upstream_databuf_size, dev->_data_buf_virt_addr, dev->_data_buf_phys_addr);\r
+    }\r
+    \r
+    //For Video Data buffer allocation  \r
+    dev->_data_buf_virt_addr = pci_alloc_consistent(dev->pci, dev->upstream_databuf_size, &data_dma_addr);\r
+    dev->_data_buf_phys_addr = data_dma_addr;\r
+    dev->_data_buf_size      = dev->upstream_databuf_size;\r
+       \r
+    if (!dev->_data_buf_virt_addr)\r
+    {\r
+        printk("cx25821: FAILED to allocate memory for data buffer! Returning.\n");\r
+        return -ENOMEM;\r
+    }\r
+  \r
+    \r
+    //Clear memory at address \r
+    memset( dev->_data_buf_virt_addr, 0, dev->_data_buf_size );\r
+   \r
+    \r
+    ret = cx25821_openfile(dev, sram_ch);     \r
+    if( ret < 0 )\r
+        return ret;\r
+                                           \r
+    \r
+    //Create RISC programs\r
+    ret = cx25821_risc_buffer_upstream(dev, dev->pci, 0,  bpl, dev->_lines_count );                                \r
+    if (ret < 0)\r
+    {\r
+        printk(KERN_INFO "cx25821: Failed creating Video Upstream Risc programs! \n");\r
+        goto error;\r
+    }\r
+       \r
+    return 0;\r
+\r
+error:\r
+    return ret;\r
+}\r
+\r
+int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, u32 status)\r
+{\r
+    u32 int_msk_tmp;\r
+    struct sram_channel *channel = &dev->sram_channels[chan_num];\r
+    int singlefield_lines = NTSC_FIELD_HEIGHT; \r
+    int line_size_in_bytes = Y422_LINE_SZ;  \r
+    int odd_risc_prog_size = 0;    \r
+    dma_addr_t   risc_phys_jump_addr;\r
+    __le32 * rp;\r
+\r
+    \r
+    \r
+    if (status & FLD_VID_SRC_RISC1)      \r
+    {\r
+        // We should only process one program per call\r
+        u32 prog_cnt = cx_read( channel->gpcnt );\r
+    \r
+        //Since we've identified our IRQ, clear our bits from the interrupt mask and interrupt status registers\r
+        int_msk_tmp = cx_read(channel->int_msk); \r
+        cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); \r
+        cx_write( channel->int_stat, _intr_msk ); \r
+        \r
+        spin_lock(&dev->slock);     \r
+            \r
+        dev->_frame_index = prog_cnt;\r
+\r
+        queue_work(dev->_irq_queues, &dev->_irq_work_entry);      \r
+               \r
+        \r
+        if ( dev->_is_first_frame )\r
+        {\r
+            dev->_is_first_frame = 0;          \r
+    \r
+            if( dev->_isNTSC )\r
+            {\r
+                singlefield_lines += 1;\r
+                odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE;\r
+            }\r
+            else\r
+            {\r
+                singlefield_lines = PAL_FIELD_HEIGHT; \r
+                odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE;  \r
+            }\r
+\r
+\r
+            if( dev->_dma_virt_start_addr != NULL )\r
+            {\r
+                line_size_in_bytes = (dev->_pixel_format == PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ;\r
+                risc_phys_jump_addr = dev->_dma_phys_start_addr + odd_risc_prog_size;        \r
+                \r
+                rp = cx25821_update_riscprogram(dev, dev->_dma_virt_start_addr, TOP_OFFSET, line_size_in_bytes, 0x0, singlefield_lines, FIFO_DISABLE, ODD_FIELD);  \r
+                \r
+                // Jump to Even Risc program of 1st Frame \r
+                *(rp++)  = cpu_to_le32(RISC_JUMP);      \r
+                *(rp++)  = cpu_to_le32(risc_phys_jump_addr);            \r
+                *(rp++)  = cpu_to_le32(0); \r
+            }\r
+        }\r
+        \r
+        spin_unlock(&dev->slock);       \r
+    }\r
+    else        \r
+    {\r
+        if(status & FLD_VID_SRC_UF)\r
+            printk("%s: Video Received Underflow Error Interrupt!\n", __func__);\r
+\r
+        if(status & FLD_VID_SRC_SYNC)\r
+            printk("%s: Video Received Sync Error Interrupt!\n", __func__);\r
+\r
+        if(status & FLD_VID_SRC_OPC_ERR)\r
+            printk("%s: Video Received OpCode Error Interrupt!\n", __func__);\r
+    }\r
+        \r
+        \r
+    if( dev->_file_status == END_OF_FILE )\r
+    {                       \r
+        printk("cx25821: EOF Channel 1 Framecount = %d\n", dev->_frame_count );\r
+        return -1;\r
+    }\r
+    \r
+    //ElSE, set the interrupt mask register, re-enable irq. \r
+    int_msk_tmp = cx_read( channel->int_msk );\r
+    cx_write( channel->int_msk, int_msk_tmp |= _intr_msk ); \r
+    \r
+    return 0;\r
+}\r
+\r
+static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id)\r
+{\r
+    struct cx25821_dev *dev = dev_id;\r
+    u32 msk_stat, vid_status;\r
+    int handled = 0;    \r
+    int channel_num = 0;\r
+    struct sram_channel *sram_ch;\r
+    \r
+    \r
+    if( !dev )\r
+        return -1;\r
+        \r
+    channel_num = VID_UPSTREAM_SRAM_CHANNEL_I;\r
+    \r
+    sram_ch = &dev->sram_channels[channel_num];     \r
+\r
+    msk_stat   = cx_read(sram_ch->int_mstat);     \r
+    vid_status = cx_read(sram_ch->int_stat);\r
+    \r
+    // Only deal with our interrupt\r
+    if(vid_status)\r
+    {\r
+        handled = cx25821_video_upstream_irq(dev, channel_num, vid_status);     \r
+    }        \r
+    \r
+    if( handled < 0 )\r
+    {   \r
+        cx25821_stop_upstream_video_ch1(dev);\r
+    }\r
+    else\r
+    {\r
+        handled += handled;    \r
+    }\r
+\r
+    return IRQ_RETVAL(handled);\r
+}\r
+\r
+\r
+void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch, int pix_format)\r
+{\r
+    int width = WIDTH_D1;               \r
+    int height = dev->_lines_count; \r
+    int num_lines, odd_num_lines;\r
+    u32 value;\r
+    int vip_mode = OUTPUT_FRMT_656;        \r
+        \r
+  \r
+    value = ( (pix_format & 0x3) << 12 ) | ( vip_mode & 0x7 );\r
+    value &= 0xFFFFFFEF;\r
+    value |= dev->_isNTSC ? 0 : 0x10;\r
+    cx_write( ch->vid_fmt_ctl, value );\r
+\r
+    \r
+    // set number of active pixels in each line. Default is 720 pixels in both NTSC and PAL format\r
+    cx_write( ch->vid_active_ctl1, width );\r
+    \r
+    num_lines = (height / 2) & 0x3FF;\r
+    odd_num_lines = num_lines;\r
+\r
+    if(dev->_isNTSC)\r
+    {\r
+        odd_num_lines += 1; \r
+    }\r
+\r
+    value = (num_lines << 16) | odd_num_lines;\r
+    \r
+    // set number of active lines in field 0 (top) and field 1 (bottom)\r
+    cx_write( ch->vid_active_ctl2, value );    \r
+\r
+    cx_write( ch->vid_cdt_size, VID_CDT_SIZE >> 3 );\r
+}\r
+\r
+\r
+int cx25821_start_video_dma_upstream(struct cx25821_dev *dev,\r
+                                     struct sram_channel *sram_ch)\r
+{\r
+    u32 tmp = 0;\r
+    int err = 0;\r
\r
+    \r
+    // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C\r
+    tmp = cx_read( VID_CH_MODE_SEL );\r
+    cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF);  \r
+       \r
+    \r
+    // Set the physical start address of the RISC program in the initial program counter(IPC) member of the cmds.\r
+    cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr);\r
+    cx_write(sram_ch->cmds_start +  4, 0); /* Risc IPC High 64 bits 63-32 */\r
+    \r
+    /* reset counter */\r
+    cx_write(sram_ch->gpcnt_ctl, 3); \r
+\r
+    // Clear our bits from the interrupt status register.  \r
+    cx_write( sram_ch->int_stat, _intr_msk );\r
+\r
+    \r
+    //Set the interrupt mask register, enable irq.  \r
+    cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));\r
+    tmp = cx_read( sram_ch->int_msk );\r
+    cx_write( sram_ch->int_msk, tmp |= _intr_msk );    \r
+    \r
+    \r
+    err = request_irq(dev->pci->irq, cx25821_upstream_irq, IRQF_SHARED | IRQF_DISABLED, dev->name, dev);\r
+    if (err < 0) \r
+    {\r
+        printk(KERN_ERR "%s: can't get upstream IRQ %d\n", dev->name, dev->pci->irq);\r
+        goto fail_irq;\r
+    } \r
+    \r
+    \r
+    // Start the DMA  engine\r
+    tmp = cx_read( sram_ch->dma_ctl );\r
+    cx_set( sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN );  \r
+\r
+    dev->_is_running = 1; \r
+    dev->_is_first_frame = 1;                 \r
+    \r
+    return 0;    \r
+\r
+fail_irq:\r
+    cx25821_dev_unregister(dev);  \r
+    return err;\r
+}\r
+\r
+\r
+int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, int pixel_format)\r
+{\r
+    struct sram_channel *sram_ch; \r
+    u32 tmp;      \r
+    int retval = 0;\r
+    int err = 0;    \r
+    int data_frame_size = 0;\r
+    int risc_buffer_size = 0;\r
+    int str_length = 0;\r
+\r
+\r
+    if( dev->_is_running ) \r
+    {\r
+        printk("Video Channel is still running so return!\n");\r
+        return 0;\r
+    }\r
+    \r
+\r
+    dev->_channel_upstream_select = channel_select;      \r
+    sram_ch = &dev->sram_channels[channel_select];   \r
+    \r
+    \r
+    INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler);\r
+    dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue");   \r
+\r
+    if(!dev->_irq_queues)\r
+    {\r
+        printk("cx25821: create_singlethread_workqueue() for Video FAILED!\n");\r
+        return -ENOMEM;\r
+    }\r
+    \r
+    // 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for channel A-C\r
+    tmp = cx_read( VID_CH_MODE_SEL );\r
+    cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF);       \r
+    \r
+          \r
+    dev->_is_running   = 0;    \r
+    dev->_frame_count  = 0;\r
+    dev->_file_status  = RESET_STATUS;  \r
+    dev->_lines_count  = dev->_isNTSC ? 480 : 576; \r
+    dev->_pixel_format = pixel_format;       \r
+    dev->_line_size    = (dev->_pixel_format == PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;   \r
+    data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;        \r
+    risc_buffer_size = dev->_isNTSC ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;\r
+    \r
+            \r
+    if( dev->input_filename )\r
+    {\r
+        str_length = strlen(dev->input_filename);\r
+        dev->_filename = (char *) kmalloc(str_length + 1, GFP_KERNEL);\r
+        \r
+        if( !dev->_filename )\r
+            goto error;\r
+            \r
+        memcpy(dev->_filename, dev->input_filename, str_length + 1);    \r
+    }\r
+    else\r
+    {\r
+        str_length = strlen(dev->_defaultname);       \r
+        dev->_filename = (char *) kmalloc(str_length + 1, GFP_KERNEL);\r
+        \r
+        if( !dev->_filename )\r
+            goto error;\r
+            \r
+        memcpy(dev->_filename, dev->_defaultname, str_length + 1);\r
+    }\r
+       \r
+    \r
+    //Default if filename is empty string \r
+    if( strcmp(dev->input_filename,"") == 0)        \r
+    {\r
+        if( dev->_isNTSC )\r
+        {\r
+            dev->_filename = (dev->_pixel_format == PIXEL_FRMT_411) ? "/root/vid411.yuv" : "/root/vidtest.yuv";\r
+        }\r
+        else\r
+        {\r
+            dev->_filename = (dev->_pixel_format == PIXEL_FRMT_411) ? "/root/pal411.yuv" : "/root/pal422.yuv";    \r
+        }\r
+    }\r
+    \r
+    dev->_is_running   = 0;    \r
+    dev->_frame_count  = 0;\r
+    dev->_file_status  = RESET_STATUS;  \r
+    dev->_lines_count  = dev->_isNTSC ? 480 : 576; \r
+    dev->_pixel_format = pixel_format;       \r
+    dev->_line_size    = (dev->_pixel_format == PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;     \r
+   \r
+    retval = cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size, 0);         \r
+    \r
+    /* setup fifo + format */\r
+    cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format);       \r
+\r
+    dev->upstream_riscbuf_size = risc_buffer_size * 2;      \r
+    dev->upstream_databuf_size = data_frame_size * 2;       \r
\r
+     \r
+    //Allocating buffers and prepare RISC program\r
+    retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size);\r
+    if (retval < 0) \r
+    {\r
+        printk(KERN_ERR "%s: Failed to set up Video upstream buffers!\n", dev->name);\r
+        goto error;\r
+    }\r
+    \r
+      \r
+    cx25821_start_video_dma_upstream(dev, sram_ch);                                     \r
+\r
+    return 0;\r
+    \r
+error:\r
+    cx25821_dev_unregister(dev);\r
+    \r
+    return err;\r
+}\r
+       \r
diff --git a/drivers/staging/cx25821/cx25821-video-upstream.h b/drivers/staging/cx25821/cx25821-video-upstream.h
new file mode 100644 (file)
index 0000000..632ccc6
--- /dev/null
@@ -0,0 +1,113 @@
+/*\r
+ *  Driver for the Conexant CX25821 PCIe bridge\r
+ *\r
+ *  Copyright (C) 2009 Conexant Systems Inc. \r
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.com>\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ */\r
+\r
+#include <linux/mutex.h>\r
+#include <linux/workqueue.h>\r
+\r
+#define OUTPUT_FRMT_656       0\r
+#define OPEN_FILE_1           0\r
+#define NUM_PROGS             8\r
+#define NUM_FRAMES            2\r
+#define ODD_FIELD             0\r
+#define EVEN_FIELD            1 \r
+#define TOP_OFFSET            0\r
+#define FIFO_DISABLE          0\r
+#define FIFO_ENABLE           1\r
+#define TEST_FRAMES           5\r
+#define END_OF_FILE           0\r
+#define IN_PROGRESS           1\r
+#define RESET_STATUS          -1\r
+#define NUM_NO_OPS            5\r
+\r
+\r
+\r
+// PAL and NTSC line sizes and number of lines.\r
+#define WIDTH_D1              720\r
+#define NTSC_LINES_PER_FRAME  480\r
+#define PAL_LINES_PER_FRAME   576\r
+#define PAL_LINE_SZ           1440\r
+#define Y422_LINE_SZ          1440\r
+#define Y411_LINE_SZ          1080\r
+#define NTSC_FIELD_HEIGHT     240\r
+#define NTSC_ODD_FLD_LINES    241\r
+#define PAL_FIELD_HEIGHT      288\r
+\r
+#define FRAME_SIZE_NTSC_Y422    (NTSC_LINES_PER_FRAME * Y422_LINE_SZ)\r
+#define FRAME_SIZE_NTSC_Y411    (NTSC_LINES_PER_FRAME * Y411_LINE_SZ)\r
+#define FRAME_SIZE_PAL_Y422     (PAL_LINES_PER_FRAME * Y422_LINE_SZ)\r
+#define FRAME_SIZE_PAL_Y411     (PAL_LINES_PER_FRAME * Y411_LINE_SZ)\r
+\r
+#define NTSC_DATA_BUF_SZ        (Y422_LINE_SZ * NTSC_LINES_PER_FRAME)\r
+#define PAL_DATA_BUF_SZ         (Y422_LINE_SZ * PAL_LINES_PER_FRAME)\r
+\r
+#define RISC_WRITECR_INSTRUCTION_SIZE   16\r
+#define RISC_SYNC_INSTRUCTION_SIZE      4\r
+#define JUMP_INSTRUCTION_SIZE           12\r
+#define MAXSIZE_NO_OPS                  36\r
+#define DWORD_SIZE                      4\r
+\r
+\r
+#define USE_RISC_NOOP_VIDEO   1\r
+\r
+#ifdef USE_RISC_NOOP_VIDEO\r
+#define PAL_US_VID_PROG_SIZE        ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +   \\r
+                                      RISC_SYNC_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE)\r
+                                    \r
+#define PAL_RISC_BUF_SIZE           (2 * PAL_US_VID_PROG_SIZE)\r
+\r
+#define PAL_VID_PROG_SIZE           ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \\r
+                                      RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) \r
+\r
+#define ODD_FLD_PAL_PROG_SIZE       ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \\r
+                                      RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE)  \r
+                                      \r
+#define ODD_FLD_NTSC_PROG_SIZE      ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \\r
+                                      RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE)  \r
+                                      \r
+#define NTSC_US_VID_PROG_SIZE       ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \\r
+                                      JUMP_INSTRUCTION_SIZE + NUM_NO_OPS*DWORD_SIZE)   \r
+                                    \r
+#define NTSC_RISC_BUF_SIZE          (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))         \r
+\r
+#define FRAME1_VID_PROG_SIZE        ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \\r
+                                      RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + 2*NUM_NO_OPS*DWORD_SIZE) \r
+                                      \r
+#endif\r
+\r
+\r
+#ifndef USE_RISC_NOOP_VIDEO\r
+#define PAL_US_VID_PROG_SIZE        ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \\r
+                                      RISC_SYNC_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)\r
+                                    \r
+#define PAL_RISC_BUF_SIZE           (2 * PAL_US_VID_PROG_SIZE)\r
+\r
+#define PAL_VID_PROG_SIZE           ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \\r
+                                      RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) \r
+\r
+#define ODD_FLD_PAL_PROG_SIZE       ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE )\r
+#define ODD_FLD_NTSC_PROG_SIZE      ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE )\r
+\r
+#define NTSC_US_VID_PROG_SIZE       ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)   \r
+#define NTSC_RISC_BUF_SIZE          ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) )     \r
+#define FRAME1_VID_PROG_SIZE        ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \\r
+                                      RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE )\r
+#endif  \r
diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c
new file mode 100644 (file)
index 0000000..512cbe3
--- /dev/null
@@ -0,0 +1,1337 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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 "cx25821-video.h"
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
+MODULE_LICENSE("GPL");
+
+static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+
+MODULE_PARM_DESC(video_nr, "video device numbers");
+MODULE_PARM_DESC(radio_nr, "radio device numbers");
+
+static unsigned int video_debug=VIDEO_DEBUG;
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
+
+static unsigned int irq_debug;
+module_param(irq_debug, int, 0644);
+MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]");
+
+unsigned int vid_limit = 16;
+module_param(vid_limit, int, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
+static void init_controls(struct cx25821_dev *dev, int chan_num);
+
+#define FORMAT_FLAGS_PACKED       0x01
+
+struct cx25821_fmt formats[] = {
+    {
+        .name     = "8 bpp, gray",
+        .fourcc   = V4L2_PIX_FMT_GREY,
+        .depth    = 8,
+        .flags    = FORMAT_FLAGS_PACKED,
+    }, {
+        .name     = "4:1:1, packed, Y41P",      
+        .fourcc   = V4L2_PIX_FMT_Y41P,       
+        .depth    = 12,
+        .flags    = FORMAT_FLAGS_PACKED,
+    }, {
+        .name     = "4:2:2, packed, YUYV",
+        .fourcc   = V4L2_PIX_FMT_YUYV,
+        .depth    = 16,
+        .flags    = FORMAT_FLAGS_PACKED,
+    }, {
+        .name     = "4:2:2, packed, UYVY",
+        .fourcc   = V4L2_PIX_FMT_UYVY,
+        .depth    = 16,
+        .flags    = FORMAT_FLAGS_PACKED,
+    },{
+        .name     = "4:2:0, YUV",           
+        .fourcc   = V4L2_PIX_FMT_YUV420,
+        .depth    = 12,
+        .flags    = FORMAT_FLAGS_PACKED,
+    },
+};
+
+
+int get_format_size(void)
+{
+   return ARRAY_SIZE(formats);
+}
+
+
+struct cx25821_fmt *format_by_fourcc(unsigned int fourcc)
+{
+    unsigned int i;
+
+    if( fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P )
+    {
+        return formats+1;       
+    }
+            
+    for (i = 0; i < ARRAY_SIZE(formats); i++)
+        if (formats[i].fourcc == fourcc)
+            return formats+i;
+
+    printk(KERN_ERR "%s(0x%08x) NOT FOUND\n", __func__, fourcc);
+    return NULL;
+}
+
+void dump_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q)
+{
+    struct cx25821_buffer *buf;
+    struct list_head *item;
+    dprintk(1, "%s()\n", __func__);
+
+    if (!list_empty(&q->active)) {
+        list_for_each(item, &q->active)
+            buf = list_entry(item, struct cx25821_buffer, vb.queue);
+     }
+
+    if (!list_empty(&q->queued))
+    {
+        list_for_each(item, &q->queued)
+            buf = list_entry(item, struct cx25821_buffer, vb.queue);
+     }
+
+}
+
+
+void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, u32 count)
+{
+    struct cx25821_buffer *buf;
+    int bc;
+
+    for (bc = 0;; bc++) {
+        if (list_empty(&q->active))
+        {
+            dprintk(1, "bc=%d (=0: active empty)\n", bc);
+            break;
+        }
+
+        buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+
+        /* count comes from the hw and it is 16bit wide --
+         * this trick handles wrap-arounds correctly for
+         * up to 32767 buffers in flight... */
+        if ((s16) (count - buf->count) < 0)
+        {
+            break;
+        }
+        
+        do_gettimeofday(&buf->vb.ts);
+        buf->vb.state = VIDEOBUF_DONE;
+        list_del(&buf->vb.queue);
+        wake_up(&buf->vb.done);
+    }
+
+    if (list_empty(&q->active))
+        del_timer(&q->timeout);
+    else
+        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+    if (bc != 1)
+        printk(KERN_ERR "%s: %d buffers handled (should be 1)\n", __func__, bc);
+}
+
+#ifdef TUNER_FLAG
+int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm)
+{
+    dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", __func__,
+        (unsigned int)norm,
+        v4l2_norm_to_name(norm));
+        
+    dev->tvnorm = norm;
+
+    /* Tell the internal A/V decoder */    
+    cx25821_call_all(dev, core, s_std, norm);
+    
+    return 0;
+}
+#endif
+
+struct video_device *cx25821_vdev_init(struct cx25821_dev *dev,
+                    struct pci_dev *pci,
+                    struct video_device *template,
+                    char *type)
+{
+    struct video_device *vfd;
+    dprintk(1, "%s()\n", __func__);
+
+    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;
+    snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, cx25821_boards[dev->board].name);
+    return vfd;
+}
+
+/*
+static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl)
+{
+    int i;
+
+    if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1)
+        return -EINVAL;
+    for (i = 0; i < CX25821_CTLS; i++)
+        if (cx25821_ctls[i].v.id == qctrl->id)
+            break;
+    if (i == CX25821_CTLS) {
+        *qctrl = no_ctl;
+        return 0;
+    }
+    *qctrl = cx25821_ctls[i].v;
+    return 0;
+}
+*/
+
+// resource management
+int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit)
+{
+    dprintk(1, "%s()\n", __func__);
+    if (fh->resources & bit)
+        /* have it already allocated */
+        return 1;
+
+    /* is it free? */
+    mutex_lock(&dev->lock);
+    if (dev->resources & bit) {
+        /* no, someone else uses it */
+        mutex_unlock(&dev->lock);
+        return 0;
+    }
+    /* it's free, grab it */
+    fh->resources  |= bit;
+    dev->resources |= bit;
+    dprintk(1, "res: get %d\n", bit);
+    mutex_unlock(&dev->lock);
+    return 1;
+}
+
+int res_check(struct cx25821_fh *fh, unsigned int bit)
+{
+    return fh->resources & bit;
+}
+
+int res_locked(struct cx25821_dev *dev, unsigned int bit)
+{
+    return dev->resources & bit;
+}
+
+void res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bits)
+{
+    BUG_ON((fh->resources & bits) != bits);
+    dprintk(1, "%s()\n", __func__);
+
+    mutex_lock(&dev->lock);
+    fh->resources  &= ~bits;
+    dev->resources &= ~bits;
+    dprintk(1, "res: put %d\n", bits);
+    mutex_unlock(&dev->lock);
+}
+
+int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input)
+{
+    struct v4l2_routing route;
+    memset(&route, 0, sizeof(route));
+
+    dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", __func__,
+        input, INPUT(input)->vmux,
+        INPUT(input)->gpio0, INPUT(input)->gpio1,
+        INPUT(input)->gpio2, INPUT(input)->gpio3);
+    dev->input = input;
+
+    route.input = INPUT(input)->vmux;
+    
+    /* Tell the internal A/V decoder */
+    cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0);  
+    
+    return 0;
+}
+
+int cx25821_start_video_dma(struct cx25821_dev *dev,
+                   struct cx25821_dmaqueue *q,
+                   struct cx25821_buffer *buf,
+                   struct sram_channel *channel)
+{
+    int tmp = 0;
+
+    /* setup fifo + format */
+    cx25821_sram_channel_setup(dev, channel, buf->bpl, buf->risc.dma);
+
+    /* reset counter */
+    cx_write(channel->gpcnt_ctl, 3);
+    q->count = 1;
+
+    /* enable irq */
+    cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1<<channel->i));
+    cx_set(channel->int_msk, 0x11);
+
+    /* start dma */
+    cx_write(channel->dma_ctl, 0x11);  /* FIFO and RISC enable */
+
+    /* make sure upstream setting if any is reversed */
+    tmp = cx_read( VID_CH_MODE_SEL );
+    cx_write( VID_CH_MODE_SEL, tmp & 0xFFFFFE00);  
+
+    return 0;
+}
+
+
+int cx25821_restart_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, struct sram_channel *channel)
+{
+    struct cx25821_buffer *buf, *prev;
+    struct list_head *item;
+
+    if (!list_empty(&q->active)) {
+        buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+
+        cx25821_start_video_dma(dev, q, buf, channel);
+
+        list_for_each(item, &q->active) {
+            buf = list_entry(item, struct cx25821_buffer, vb.queue);
+            buf->count    = q->count++;
+        }
+
+        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+        return 0;
+    }
+
+    prev = NULL;
+    for (;;) {
+        if (list_empty(&q->queued))
+            return 0;
+
+        buf = list_entry(q->queued.next, struct cx25821_buffer, vb.queue);
+
+        if (NULL == prev) {
+            list_move_tail(&buf->vb.queue, &q->active);
+            cx25821_start_video_dma(dev, q, buf, channel);
+            buf->vb.state = VIDEOBUF_ACTIVE;
+            buf->count    = q->count++;
+            mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+        } else if (prev->vb.width  == buf->vb.width  &&
+               prev->vb.height == buf->vb.height &&
+               prev->fmt       == buf->fmt) {
+            list_move_tail(&buf->vb.queue, &q->active);
+            buf->vb.state = VIDEOBUF_ACTIVE;
+            buf->count    = q->count++;
+            prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+            prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */
+        } else {
+            return 0;
+        }
+        prev = buf;
+    }
+}
+
+void cx25821_vid_timeout(unsigned long data)
+{
+    struct cx25821_data     *timeout_data = (struct cx25821_data *)data;
+    struct cx25821_dev      *dev = timeout_data->dev;
+    struct sram_channel     *channel = timeout_data->channel;
+    struct cx25821_dmaqueue *q = &dev->vidq[channel->i];
+    struct cx25821_buffer   *buf;
+    unsigned long flags;
+
+    //cx25821_sram_channel_dump(dev, channel);
+    cx_clear(channel->dma_ctl, 0x11);
+
+    spin_lock_irqsave(&dev->slock, flags);
+    while (!list_empty(&q->active)) {
+        buf = list_entry(q->active.next, struct cx25821_buffer, vb.queue);
+        list_del(&buf->vb.queue);
+
+        buf->vb.state = VIDEOBUF_ERROR;
+        wake_up(&buf->vb.done);
+    }
+
+    cx25821_restart_video_queue(dev, q, channel);
+    spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
+{
+    u32 count=0;
+    int handled = 0;
+    u32 mask;
+    struct sram_channel *channel = &dev->sram_channels[chan_num];
+
+    mask   = cx_read(channel->int_msk);
+    if (0 == (status & mask))
+        return handled;
+
+    cx_write(channel->int_stat, status);
+
+    /* risc op code error */
+    if (status & (1 << 16)) {
+        printk(KERN_WARNING "%s, %s: video risc op code error\n", dev->name, channel->name);
+        cx_clear(channel->dma_ctl, 0x11);
+        cx25821_sram_channel_dump(dev, channel);
+    }
+
+    /* risc1 y */
+    if (status & FLD_VID_DST_RISC1) {
+        spin_lock(&dev->slock);
+        count = cx_read(channel->gpcnt);
+        cx25821_video_wakeup(dev, &dev->vidq[channel->i], count);
+        spin_unlock(&dev->slock);
+        handled++;
+    }
+
+    /* risc2 y */
+    if (status & 0x10) {
+        dprintk(2, "stopper video\n");
+        spin_lock(&dev->slock);
+        cx25821_restart_video_queue(dev, &dev->vidq[channel->i], channel);
+        spin_unlock(&dev->slock);
+        handled++;
+    }
+    return handled;
+}
+
+void cx25821_videoioctl_unregister(struct cx25821_dev *dev)
+{
+    if( dev->ioctl_dev )
+    {
+        if (dev->ioctl_dev->minor != -1)
+            video_unregister_device(dev->ioctl_dev);
+        else
+            video_device_release(dev->ioctl_dev);
+
+        dev->ioctl_dev = NULL;
+    }
+}
+        
+void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num)
+{
+    cx_clear(PCI_INT_MSK, 1);
+
+    if (dev->video_dev[chan_num]) {
+        if (-1 != dev->video_dev[chan_num]->minor)
+            video_unregister_device(dev->video_dev[chan_num]);
+        else
+            video_device_release(dev->video_dev[chan_num]);
+
+        dev->video_dev[chan_num] = NULL;
+
+        btcx_riscmem_free(dev->pci, &dev->vidq[chan_num].stopper);
+
+        printk(KERN_WARNING "device %d released!\n", chan_num);
+    }
+
+}
+
+
+int cx25821_video_register(struct cx25821_dev *dev, int chan_num, struct video_device *video_template)
+{
+    int err;
+
+    spin_lock_init(&dev->slock);
+
+    //printk(KERN_WARNING "Channel %d\n", chan_num);
+
+#ifdef TUNER_FLAG
+    dev->tvnorm = video_template->current_norm;
+#endif
+
+    /* init video dma queues */
+    dev->timeout_data[chan_num].dev     = dev;
+    dev->timeout_data[chan_num].channel = &dev->sram_channels[chan_num];
+    INIT_LIST_HEAD(&dev->vidq[chan_num].active);
+    INIT_LIST_HEAD(&dev->vidq[chan_num].queued);
+    dev->vidq[chan_num].timeout.function = cx25821_vid_timeout;
+    dev->vidq[chan_num].timeout.data = (unsigned long)&dev->timeout_data[chan_num];
+    init_timer(&dev->vidq[chan_num].timeout);
+    cx25821_risc_stopper(dev->pci, &dev->vidq[chan_num].stopper, dev->sram_channels[chan_num].dma_ctl, 0x11, 0);
+
+    
+    /* register v4l devices */
+    dev->video_dev[chan_num] = cx25821_vdev_init(dev, dev->pci, video_template, "video");
+    err = video_register_device(dev->video_dev[chan_num], VFL_TYPE_GRABBER, video_nr[dev->nr]);
+
+    if (err < 0) {
+        goto fail_unreg;
+    }
+
+    //set PCI interrupt
+    cx_set(PCI_INT_MSK, 0xff);
+
+
+    /* initial device configuration */
+    mutex_lock(&dev->lock);
+#ifdef TUNER_FLAG
+    cx25821_set_tvnorm(dev, dev->tvnorm);
+#endif
+    mutex_unlock(&dev->lock);
+
+    init_controls(dev, chan_num);
+
+    return 0;
+
+fail_unreg:
+    cx25821_video_unregister(dev, chan_num);
+    return err;
+}
+
+int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+    struct cx25821_fh *fh = q->priv_data;
+
+    *size = fh->fmt->depth*fh->width*fh->height >> 3;
+
+
+    if (0 == *count)
+        *count = 32;
+
+    while (*size * *count > vid_limit * 1024 * 1024)
+        (*count)--;
+
+    return 0;
+}
+
+int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field)
+{
+    struct cx25821_fh *fh  = q->priv_data;
+    struct cx25821_dev *dev = fh->dev;
+    struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb);
+    int rc, init_buffer = 0;
+    u32 line0_offset, line1_offset;
+    struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+    int bpl_local = LINE_SIZE_D1;
+    int channel_opened = 0;
+
+
+    BUG_ON(NULL == fh->fmt);
+    if (fh->width  < 48 || fh->width  > 720 ||
+        fh->height < 32 || fh->height > 576)
+        return -EINVAL;
+
+    buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
+
+    if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+        return -EINVAL;
+
+
+    if (buf->fmt       != fh->fmt    ||
+        buf->vb.width  != fh->width  ||
+        buf->vb.height != fh->height ||
+        buf->vb.field  != field) {
+        buf->fmt       = fh->fmt;
+        buf->vb.width  = fh->width;
+        buf->vb.height = fh->height;
+        buf->vb.field  = field;
+        init_buffer = 1;
+    }
+
+    if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+        init_buffer = 1;
+        rc = videobuf_iolock(q, &buf->vb, NULL);
+        if (0 != rc)
+                {
+            printk(KERN_DEBUG "videobuf_iolock failed!\n");
+            goto fail;
+                }
+    }
+
+    dprintk(1, "init_buffer=%d\n", init_buffer);
+
+    if (init_buffer) {
+        
+        channel_opened = dev->channel_opened;       
+        channel_opened = (channel_opened < 0 || channel_opened > 7) ? 7 : channel_opened;
+        
+        if( dev->pixel_formats[channel_opened] == PIXEL_FRMT_411 )
+            buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3;
+        else
+            buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width);
+
+            
+        if( dev->pixel_formats[channel_opened] == PIXEL_FRMT_411 )
+        {
+            bpl_local = buf->bpl;
+        }
+        else 
+        {
+            bpl_local = buf->bpl;   //Default
+            
+            if( channel_opened >= 0 && channel_opened <= 7 )
+            {
+                if( dev->use_cif_resolution[channel_opened] )
+                {
+                    if( dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK )
+                        bpl_local = 352 << 1;
+                    else
+                        bpl_local = dev->cif_width[channel_opened] << 1;
+                }
+            }
+        }
+        
+         
+        switch (buf->vb.field) {
+            case V4L2_FIELD_TOP:
+                cx25821_risc_buffer(dev->pci, &buf->risc,
+                         dma->sglist, 0, UNSET,
+                         buf->bpl, 0, buf->vb.height);
+                break;
+            case V4L2_FIELD_BOTTOM:
+                cx25821_risc_buffer(dev->pci, &buf->risc,
+                         dma->sglist, UNSET, 0,
+                         buf->bpl, 0, buf->vb.height);
+                break;
+            case V4L2_FIELD_INTERLACED:
+                /* All other formats are top field first */
+                line0_offset = 0;
+                line1_offset = buf->bpl;
+                dprintk(1, "top field first\n");
+                
+                cx25821_risc_buffer(dev->pci, &buf->risc,
+                        dma->sglist, line0_offset,
+                        bpl_local, bpl_local, bpl_local,
+                        buf->vb.height >> 1);
+                break;
+            case V4L2_FIELD_SEQ_TB:
+                cx25821_risc_buffer(dev->pci, &buf->risc,
+                         dma->sglist,
+                         0, buf->bpl * (buf->vb.height >> 1),
+                         buf->bpl, 0,
+                         buf->vb.height >> 1);
+                break;
+            case V4L2_FIELD_SEQ_BT:
+                cx25821_risc_buffer(dev->pci, &buf->risc,
+                         dma->sglist,
+                         buf->bpl * (buf->vb.height >> 1), 0,
+                         buf->bpl, 0,
+                         buf->vb.height >> 1);
+                break;
+            default:
+                BUG();
+        }
+    }
+
+    dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
+        buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth, fh->fmt->name,
+        (unsigned long)buf->risc.dma);
+
+    buf->vb.state = VIDEOBUF_PREPARED;
+
+    return 0;
+
+ fail:
+    cx25821_free_buffer(q, buf);
+    return rc;
+}
+
+
+void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+    struct cx25821_buffer *buf = container_of(vb, struct cx25821_buffer, vb);
+
+    cx25821_free_buffer(q, buf);
+}
+
+
+struct videobuf_queue *get_queue(struct cx25821_fh *fh)
+{
+    switch (fh->type) {
+    case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+        return &fh->vidq;
+    default:
+        BUG();
+        return NULL;
+    }
+}
+
+int get_resource(struct cx25821_fh *fh, int resource)
+{
+    switch (fh->type) {
+    case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+        return resource;
+    default:
+        BUG();
+        return 0;
+    }
+}
+
+
+int video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+    struct cx25821_fh *fh = file->private_data;
+
+    return videobuf_mmap_mapper(get_queue(fh), vma);
+}
+
+/* VIDEO IOCTLS                                                       */
+int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+    struct cx25821_fh *fh   = priv;
+
+    f->fmt.pix.width        = fh->width;
+    f->fmt.pix.height       = fh->height;
+    f->fmt.pix.field        = fh->vidq.field;
+    f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+    f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3;
+    f->fmt.pix.sizeimage    = f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+    return 0;
+}
+
+int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+    struct cx25821_fmt *fmt;
+    enum v4l2_field   field;
+    unsigned int      maxw, maxh;
+
+    fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+    if (NULL == fmt)
+        return -EINVAL;
+
+    field = f->fmt.pix.field;
+    maxw  = 720;
+    maxh  = 576;
+
+    if (V4L2_FIELD_ANY == field) {
+        field = (f->fmt.pix.height > maxh/2)
+            ? V4L2_FIELD_INTERLACED
+            : V4L2_FIELD_TOP;
+    }
+
+    switch (field) {
+    case V4L2_FIELD_TOP:
+    case V4L2_FIELD_BOTTOM:
+        maxh = maxh / 2;
+        break;
+    case V4L2_FIELD_INTERLACED:
+        break;
+    default:
+        return -EINVAL;
+    }
+
+    f->fmt.pix.field = field;
+    if (f->fmt.pix.height < 32)
+        f->fmt.pix.height  = 32;
+    if (f->fmt.pix.height > maxh)
+        f->fmt.pix.height = maxh;
+    if (f->fmt.pix.width < 48)
+        f->fmt.pix.width = 48;
+    if (f->fmt.pix.width > maxw)
+        f->fmt.pix.width = maxw;
+    f->fmt.pix.width &= ~0x03;
+    f->fmt.pix.bytesperline  = (f->fmt.pix.width * fmt->depth) >> 3;
+    f->fmt.pix.sizeimage     = f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+    return 0;
+}
+
+
+
+int vidioc_querycap(struct file *file, void  *priv, struct v4l2_capability *cap)
+{
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+
+    strcpy(cap->driver, "cx25821");
+    strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card));
+    sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
+    cap->version = CX25821_VERSION_CODE;
+    cap->capabilities =
+        V4L2_CAP_VIDEO_CAPTURE |
+        V4L2_CAP_READWRITE     |
+        V4L2_CAP_STREAMING;
+    if (UNSET != dev->tuner_type)
+        cap->capabilities |= V4L2_CAP_TUNER;
+    return 0;
+}
+
+int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv, struct v4l2_fmtdesc *f)
+{
+    if (unlikely(f->index >= ARRAY_SIZE(formats)))
+        return -EINVAL;
+
+    strlcpy(f->description, formats[f->index].name, sizeof(f->description));
+    f->pixelformat = formats[f->index].fourcc;
+
+    return 0;
+}
+
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
+{
+    struct cx25821_fh *fh = priv;
+    struct videobuf_queue *q;
+    struct v4l2_requestbuffers req;
+    unsigned int i;
+    int err;
+
+    q = get_queue(fh);
+    memset(&req, 0, sizeof(req));
+    req.type   = q->type;
+    req.count  = 8;
+    req.memory = V4L2_MEMORY_MMAP;
+    err = videobuf_reqbufs(q, &req);
+    if (err < 0)
+        return err;
+
+    mbuf->frames = req.count;
+    mbuf->size   = 0;
+    for (i = 0; i < mbuf->frames; i++) {
+        mbuf->offsets[i]  = q->bufs[i]->boff;
+        mbuf->size       += q->bufs[i]->bsize;
+    }
+    return 0;
+}
+#endif
+
+int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p)
+{
+    struct cx25821_fh *fh = priv;
+    return videobuf_reqbufs(get_queue(fh), p);
+}
+
+int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+    struct cx25821_fh *fh = priv;
+    return videobuf_querybuf(get_queue(fh), p);
+}
+
+int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+    struct cx25821_fh *fh = priv;
+    return videobuf_qbuf(get_queue(fh), p);
+}
+
+int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p)
+{
+       struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev;
+
+       *p = v4l2_prio_max(&dev->prio);
+
+       return 0;
+}
+
+int vidioc_s_priority(struct file *file, void *f,
+                                       enum v4l2_priority prio)
+{
+       struct cx25821_fh *fh = f;
+       struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev;
+
+       return v4l2_prio_change(&dev->prio, &fh->prio, prio);
+}
+
+
+#ifdef TUNER_FLAG
+int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+    int err;
+
+    dprintk(1, "%s()\n", __func__);
+    
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    if( dev->tvnorm == *tvnorms )
+    {
+        return 0;
+    }
+
+    mutex_lock(&dev->lock);
+    cx25821_set_tvnorm(dev, *tvnorms);
+    mutex_unlock(&dev->lock);
+
+    medusa_set_videostandard(dev);
+
+    return 0;
+}
+#endif
+
+int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i)
+{
+    static const char *iname[] = {
+        [CX25821_VMUX_COMPOSITE] = "Composite",
+        [CX25821_VMUX_SVIDEO]     = "S-Video",
+        [CX25821_VMUX_DEBUG]      = "for debug only",
+    };
+    unsigned int n;
+    dprintk(1, "%s()\n", __func__);
+
+    n = i->index;
+    if (n > 2)
+        return -EINVAL;
+
+    if (0 == INPUT(n)->type)
+        return -EINVAL;
+
+    memset(i, 0, sizeof(*i));
+    i->index = n;
+    i->type  = V4L2_INPUT_TYPE_CAMERA;
+    strcpy(i->name, iname[INPUT(n)->type]);
+
+    i->std = CX25821_NORMS;
+    return 0;
+}
+
+int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i)
+{
+    struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+    dprintk(1, "%s()\n", __func__);
+    return cx25821_enum_input(dev, i);
+}
+
+int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{   
+    struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+    
+    *i = dev->input;
+    dprintk(1, "%s() returns %d\n", __func__, *i);
+    return 0;
+}
+
+
+int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+    int err;
+
+    dprintk(1, "%s(%d)\n", __func__, i);
+
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    if (i > 2) {
+        dprintk(1, "%s() -EINVAL\n", __func__);
+        return -EINVAL;
+    }
+
+    mutex_lock(&dev->lock);
+    cx25821_video_mux(dev, i);
+    mutex_unlock(&dev->lock);
+    return 0;
+}
+
+#ifdef TUNER_FLAG
+int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+
+    f->frequency = dev->freq;
+
+    cx25821_call_all(dev, tuner, g_frequency, f);
+
+    return 0;
+}
+
+int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f)
+{
+    mutex_lock(&dev->lock);
+    dev->freq = f->frequency;
+
+    cx25821_call_all(dev, tuner, s_frequency, f);
+
+    /* When changing channels it is required to reset TVAUDIO */
+    msleep(10);
+
+    mutex_unlock(&dev->lock);
+
+    return 0;
+}
+
+int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+    int err;
+
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    return  cx25821_set_freq(dev, f);
+}
+#endif
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+int vidioc_g_register(struct file *file, void *fh,
+                struct v4l2_dbg_register *reg)
+{
+    struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev;
+
+    if (!v4l2_chip_match_host(&reg->match))
+        return -EINVAL;
+
+    cx25821_call_all(dev, core, g_register, reg);
+
+    return 0;
+}
+
+int vidioc_s_register(struct file *file, void *fh,
+                struct v4l2_dbg_register *reg)
+{
+    struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev;
+
+    if (!v4l2_chip_match_host(&reg->match))
+        return -EINVAL;
+
+    cx25821_call_all(dev, core, s_register, reg);
+
+    return 0;
+}
+
+#endif
+
+
+#ifdef TUNER_FLAG
+int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+    struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+    if (unlikely(UNSET == dev->tuner_type))
+        return -EINVAL;
+    if (0 != t->index)
+        return -EINVAL;
+
+    strcpy(t->name, "Television");
+    t->type       = V4L2_TUNER_ANALOG_TV;
+    t->capability = V4L2_TUNER_CAP_NORM;
+    t->rangehigh  = 0xffffffffUL;
+
+    t->signal = 0xffff ; /* LOCKED */
+    return 0;
+}
+
+int vidioc_s_tuner(struct file *file, void *priv,
+                struct v4l2_tuner *t)
+{
+    struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+    struct cx25821_fh *fh = priv;
+    int err;
+
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    dprintk(1, "%s()\n", __func__);
+    if (UNSET == dev->tuner_type)
+        return -EINVAL;
+    if (0 != t->index)
+        return -EINVAL;
+
+    return 0;
+}
+
+#endif
+// ******************************************************************************************
+static const struct v4l2_queryctrl no_ctl = {
+       .name  = "42",
+       .flags = V4L2_CTRL_FLAG_DISABLED,
+};
+
+static struct v4l2_queryctrl cx25821_ctls[] = {
+       /* --- video --- */
+       {
+               .id            = V4L2_CID_BRIGHTNESS,
+               .name          = "Brightness",
+               .minimum       = 0,
+               .maximum       = 10000,
+               .step          = 1,
+               .default_value = 6200,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_CONTRAST,
+               .name          = "Contrast",
+               .minimum       = 0,
+               .maximum       = 10000,
+               .step          = 1,
+               .default_value = 5000,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_SATURATION,
+               .name          = "Saturation",
+               .minimum       = 0,
+               .maximum       = 10000,
+               .step          = 1,
+               .default_value = 5000,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_HUE,
+               .name          = "Hue",
+               .minimum       = 0,
+               .maximum       = 10000,
+               .step          = 1,
+               .default_value = 5000,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       }
+};
+static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls);
+
+static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl)
+{
+       int i;
+
+       if (qctrl->id < V4L2_CID_BASE ||
+           qctrl->id >= V4L2_CID_LASTP1)
+               return -EINVAL;
+       for (i = 0; i < CX25821_CTLS; i++)
+               if (cx25821_ctls[i].id == qctrl->id)
+                       break;
+       if (i == CX25821_CTLS) {
+               *qctrl = no_ctl;
+               return 0;
+       }
+       *qctrl = cx25821_ctls[i];
+       return 0;
+}
+
+int vidioc_queryctrl(struct file *file, void *priv,
+                               struct v4l2_queryctrl *qctrl)
+{      
+       return cx25821_ctrl_query(qctrl);
+}
+
+/* ------------------------------------------------------------------ */
+/* VIDEO CTRL IOCTLS                                                  */
+
+static const struct v4l2_queryctrl* ctrl_by_id(unsigned int id)
+{
+       unsigned int i;
+
+       for (i = 0; i < CX25821_CTLS; i++)
+               if (cx25821_ctls[i].id == id)
+                       return cx25821_ctls+i;
+       return NULL;
+}
+
+int vidioc_g_ctrl(struct file *file, 
+                  void *priv,
+                 struct v4l2_control *ctl)
+{
+        struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+        const struct v4l2_queryctrl* ctrl;
+
+       ctrl = ctrl_by_id(ctl->id);
+
+       if (NULL == ctrl)
+               return -EINVAL;
+       switch (ctl->id) 
+        {
+           case V4L2_CID_BRIGHTNESS:
+               ctl->value = dev->ctl_bright;
+               break;
+           case V4L2_CID_HUE:
+               ctl->value = dev->ctl_hue;
+               break;
+           case V4L2_CID_CONTRAST:
+               ctl->value = dev->ctl_contrast;
+               break;
+           case V4L2_CID_SATURATION:
+               ctl->value = dev->ctl_saturation;
+               break;
+        }
+       return 0;
+}
+
+int cx25821_set_control(struct cx25821_dev *dev,
+                 struct v4l2_control *ctl, int chan_num)
+{
+        int err;
+        const struct v4l2_queryctrl* ctrl;
+
+       err = -EINVAL;
+
+       ctrl = ctrl_by_id(ctl->id);
+
+        if (NULL == ctrl)
+               return err;
+
+        switch (ctrl->type) 
+        {
+           case V4L2_CTRL_TYPE_BOOLEAN:
+           case V4L2_CTRL_TYPE_MENU:
+           case V4L2_CTRL_TYPE_INTEGER:
+               if (ctl->value < ctrl->minimum)
+                       ctl->value = ctrl->minimum;
+               if (ctl->value > ctrl->maximum)
+                       ctl->value = ctrl->maximum;
+               break;
+           default:
+               /* nothing */;
+       };
+
+        switch (ctl->id) 
+        {
+           case V4L2_CID_BRIGHTNESS:
+               dev->ctl_bright = ctl->value;
+               medusa_set_brightness(dev, ctl->value, chan_num);
+               break;
+           case V4L2_CID_HUE:
+               dev->ctl_hue = ctl->value;
+               medusa_set_hue(dev, ctl->value, chan_num);
+               break;
+           case V4L2_CID_CONTRAST:
+               dev->ctl_contrast = ctl->value;
+               medusa_set_contrast(dev, ctl->value, chan_num);
+               break;
+           case V4L2_CID_SATURATION:
+               dev->ctl_saturation = ctl->value;
+               medusa_set_saturation(dev, ctl->value, chan_num);
+               break;
+        }
+
+        err = 0;
+
+       return err;
+}
+
+static void init_controls(struct cx25821_dev *dev, int chan_num)
+{
+       struct v4l2_control ctrl;
+       int i;
+       for (i = 0; i < CX25821_CTLS; i++) {
+               ctrl.id = cx25821_ctls[i].id;
+               ctrl.value = cx25821_ctls[i].default_value;
+
+               cx25821_set_control(dev, &ctrl, chan_num);
+       }
+}
+
+int vidioc_cropcap(struct file *file, 
+                   void *priv,
+                  struct v4l2_cropcap *cropcap)
+{
+       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+       
+       if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       cropcap->bounds.top = cropcap->bounds.left = 0;
+       cropcap->bounds.width = 720;
+       cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480;
+       cropcap->pixelaspect.numerator = dev->tvnorm == V4L2_STD_PAL_BG ? 59 : 10;
+       cropcap->pixelaspect.denominator = dev->tvnorm == V4L2_STD_PAL_BG ? 54 : 11;
+       cropcap->defrect = cropcap->bounds;
+       return 0;
+}
+
+int vidioc_s_crop(struct file *file, 
+                  void *priv,
+                 struct v4l2_crop *crop)
+{
+    struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+    struct cx25821_fh *fh = priv;
+    int err;
+
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+    // vidioc_s_crop not supported
+    return -EINVAL;
+}
+
+int vidioc_g_crop(struct file *file, 
+                  void *priv,
+                 struct v4l2_crop *crop)
+{
+    // vidioc_g_crop not supported
+    return -EINVAL;
+}
+
+int vidioc_querystd(struct file *file, 
+                   void *priv,
+                  v4l2_std_id *norm)
+{
+    // medusa does not support video standard sensing of current input
+    *norm = CX25821_NORMS;
+
+    return 0;
+}
+
+int is_valid_width(u32 width, v4l2_std_id tvnorm)
+{
+    if(tvnorm == V4L2_STD_PAL_BG)
+    {
+       if (width == 352 || width == 720)
+            return 1;
+        else
+            return 0;
+    }
+    
+    if(tvnorm == V4L2_STD_NTSC_M)
+    {
+        if (width == 320 || width == 352 || width == 720)
+            return 1;
+        else
+            return 0;
+    }
+    return 0;
+}
+
+int is_valid_height(u32 height, v4l2_std_id tvnorm)
+{
+    if(tvnorm == V4L2_STD_PAL_BG)
+    { 
+        if (height == 576 || height == 288)
+            return 1;
+        else
+            return 0;
+    }
+
+    if(tvnorm == V4L2_STD_NTSC_M)
+    {
+        if (height == 480 || height == 240)
+            return 1;
+        else
+            return 0;
+    }
+
+    return 0;
+}
+
diff --git a/drivers/staging/cx25821/cx25821-video.h b/drivers/staging/cx25821/cx25821-video.h
new file mode 100644 (file)
index 0000000..fa2ec78
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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.
+ */
+
+#ifndef CX25821_VIDEO_H_
+#define CX25821_VIDEO_H_
+
+
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <asm/div64.h>
+
+#include "cx25821.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+/* Include V4L1 specific functions. Should be removed soon */
+#include <linux/videodev.h>
+#endif
+
+#define TUNER_FLAG
+
+#define VIDEO_DEBUG 0
+
+#define dprintk(level, fmt, arg...)\
+    do { if (VIDEO_DEBUG >= level)\
+        printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+    } while (0)
+
+
+//For IOCTL to identify running upstream
+#define UPSTREAM_START_VIDEO        700
+#define UPSTREAM_STOP_VIDEO         701
+#define UPSTREAM_START_AUDIO        702
+#define UPSTREAM_STOP_AUDIO         703
+#define UPSTREAM_DUMP_REGISTERS     702
+#define SET_VIDEO_STD               800
+#define SET_PIXEL_FORMAT            1000
+#define ENABLE_CIF_RESOLUTION       1001
+
+#define REG_READ                   900
+#define REG_WRITE                  901
+#define MEDUSA_READ                910
+#define MEDUSA_WRITE           911
+
+extern struct sram_channel *channel0;
+extern struct sram_channel *channel1;
+extern struct sram_channel *channel2;
+extern struct sram_channel *channel3;
+extern struct sram_channel *channel4;
+extern struct sram_channel *channel5;
+extern struct sram_channel *channel6;
+extern struct sram_channel *channel7;
+extern struct sram_channel *channel9;
+extern struct sram_channel *channel10;
+extern struct sram_channel *channel11;
+extern struct video_device cx25821_video_template0;
+extern struct video_device cx25821_video_template1;
+extern struct video_device cx25821_video_template2;
+extern struct video_device cx25821_video_template3;
+extern struct video_device cx25821_video_template4;
+extern struct video_device cx25821_video_template5;
+extern struct video_device cx25821_video_template6;
+extern struct video_device cx25821_video_template7;
+extern struct video_device cx25821_video_template9;
+extern struct video_device cx25821_video_template10;
+extern struct video_device cx25821_video_template11;
+extern struct video_device cx25821_videoioctl_template;
+//extern const u32 *ctrl_classes[];
+
+extern  unsigned int vid_limit;
+
+#define FORMAT_FLAGS_PACKED       0x01
+extern struct cx25821_fmt formats[];
+extern struct cx25821_fmt *format_by_fourcc(unsigned int fourcc);
+extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM];
+
+extern void dump_video_queue(struct cx25821_dev *dev, struct cx25821_dmaqueue *q);
+extern void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, u32 count);
+
+#ifdef TUNER_FLAG
+extern int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm);
+#endif
+
+
+extern int res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bit);
+extern int res_check(struct cx25821_fh *fh, unsigned int bit);
+extern int res_locked(struct cx25821_dev *dev, unsigned int bit);
+extern void res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, unsigned int bits);
+extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input);
+extern int cx25821_start_video_dma(struct cx25821_dev *dev,
+                   struct cx25821_dmaqueue *q,
+                   struct cx25821_buffer *buf,
+                   struct sram_channel *channel);
+
+extern int cx25821_set_scale(struct cx25821_dev *dev, unsigned int width, unsigned int height, enum v4l2_field field);
+extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status);
+extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num);
+extern int cx25821_video_register(struct cx25821_dev *dev, int chan_num, struct video_device *video_template);
+extern int get_format_size(void);
+
+extern int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size);
+extern int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field);
+extern void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb);
+extern struct videobuf_queue *get_queue(struct cx25821_fh *fh);
+extern int get_resource(struct cx25821_fh *fh, int resource);
+extern int video_mmap(struct file *file, struct vm_area_struct *vma);
+extern int vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f);
+extern int vidioc_querycap(struct file *file, void  *priv, struct v4l2_capability *cap);
+extern int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv, struct v4l2_fmtdesc *f);
+extern int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf);
+extern int vidioc_reqbufs(struct file *file, void *priv, struct v4l2_requestbuffers *p);
+extern int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p);
+extern int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p);
+extern int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms);
+extern int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i);
+extern int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i);
+extern int vidioc_g_input(struct file *file, void *priv, unsigned int *i);
+extern int vidioc_s_input(struct file *file, void *priv, unsigned int i);
+extern int vidioc_g_ctrl(struct file *file, void *priv, struct v4l2_control *ctl);
+extern int vidioc_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f);
+extern int vidioc_g_frequency(struct file *file, void *priv, struct v4l2_frequency *f);
+extern int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f);
+extern int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f);
+extern int vidioc_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg);
+extern int vidioc_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg);
+extern int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t);
+extern int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t);
+
+extern int is_valid_width(u32 width, v4l2_std_id tvnorm);
+extern int is_valid_height(u32 height, v4l2_std_id tvnorm);
+
+extern int vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p);
+extern int vidioc_s_priority(struct file *file, void *f, enum v4l2_priority prio);
+
+extern int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qctrl);
+extern int cx25821_set_control(struct cx25821_dev *dev, struct v4l2_control *ctrl, int chan_num);
+
+extern int vidioc_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap);
+extern int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop);
+extern int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop);
+
+extern int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm);
+#endif
diff --git a/drivers/staging/cx25821/cx25821-video0.c b/drivers/staging/cx25821/cx25821-video0.c
new file mode 100644 (file)
index 0000000..9dbd740
--- /dev/null
@@ -0,0 +1,457 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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 "cx25821-video.h"
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+    struct cx25821_buffer   *buf = container_of(vb, struct cx25821_buffer, vb);
+    struct cx25821_buffer   *prev;
+    struct cx25821_fh       *fh   = vq->priv_data;
+    struct cx25821_dev      *dev  = fh->dev;
+    struct cx25821_dmaqueue *q    = &dev->vidq[SRAM_CH00];
+
+    /* add jump to stopper */
+    buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+    buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+    buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+    dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+    if (!list_empty(&q->queued)) {
+        list_add_tail(&buf->vb.queue, &q->queued);
+        buf->vb.state = VIDEOBUF_QUEUED;
+        dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i);
+
+    } else if (list_empty(&q->active)) {
+        list_add_tail(&buf->vb.queue, &q->active);
+        cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH00]);
+        buf->vb.state = VIDEOBUF_ACTIVE;
+        buf->count    = q->count++;
+        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+        dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+                                buf, buf->vb. i, buf->count, q->count);
+    } else {
+        prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+        if (prev->vb.width  == buf->vb.width  &&
+            prev->vb.height == buf->vb.height &&
+            prev->fmt       == buf->fmt) {
+            list_add_tail(&buf->vb.queue, &q->active);
+            buf->vb.state = VIDEOBUF_ACTIVE;
+            buf->count    = q->count++;
+            prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+            /* 64 bit bits 63-32 */
+            prev->risc.jmp[2] = cpu_to_le32(0);
+            dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",  buf, buf->vb.i, buf->count);
+
+        } else {
+            list_add_tail(&buf->vb.queue, &q->queued);
+            buf->vb.state = VIDEOBUF_QUEUED;
+            dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i);
+        }
+    }
+
+    if (list_empty(&q->active))
+    {
+       dprintk(2, "active queue empty!\n");
+    }
+}
+
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+    .buf_setup    = buffer_setup,
+    .buf_prepare  = buffer_prepare,
+    .buf_queue    = buffer_queue,
+    .buf_release  = buffer_release,
+};
+
+
+static int video_open(struct file *file)
+{
+    int minor = video_devdata(file)->minor;
+    struct cx25821_dev *h, *dev = NULL;
+    struct cx25821_fh *fh;
+    struct list_head *list;
+    enum v4l2_buf_type type = 0;
+    u32 pix_format;
+
+    lock_kernel();
+    list_for_each(list, &cx25821_devlist)
+    {
+        h = list_entry(list, struct cx25821_dev, devlist);
+
+        if (h->video_dev[SRAM_CH00] && h->video_dev[SRAM_CH00]->minor == minor)
+        {
+            dev  = h;
+            type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        }
+    }
+
+    if (NULL == dev) {
+        unlock_kernel();
+        return -ENODEV;
+    }
+
+    printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+    /* allocate + initialize per filehandle data */
+    fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+    if (NULL == fh) {
+        unlock_kernel();
+        return -ENOMEM;
+    }
+
+    file->private_data = fh;
+    fh->dev      = dev;
+    fh->type     = type;
+    fh->width    = 720;
+
+    if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+        fh->height = 576;
+    else
+        fh->height = 480;
+
+    dev->channel_opened = SRAM_CH00;
+    pix_format          = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+    fh->fmt             = format_by_fourcc(pix_format);
+    
+    v4l2_prio_open(&dev->prio,&fh->prio);
+
+    videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+                &dev->pci->dev, &dev->slock,
+                V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                V4L2_FIELD_INTERLACED,
+                sizeof(struct cx25821_buffer),
+                fh);
+
+    dprintk(1, "post videobuf_queue_init()\n");
+    unlock_kernel();
+
+    return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+    struct cx25821_fh *fh = file->private_data;
+
+    switch (fh->type)
+    {
+        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+            if (res_locked(fh->dev, RESOURCE_VIDEO0))
+                return -EBUSY;
+
+            return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK);
+
+        default:
+            BUG();
+            return 0;
+    }
+}
+
+static unsigned int video_poll(struct file *file, struct poll_table_struct *wait)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_buffer *buf;
+
+    if (res_check(fh, RESOURCE_VIDEO0)) {
+        /* streaming capture */
+        if (list_empty(&fh->vidq.stream))
+            return POLLERR;
+        buf = list_entry(fh->vidq.stream.next,
+            struct cx25821_buffer, vb.stream);
+    } else {
+        /* read() capture */
+        buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+        if (NULL == buf)
+            return POLLERR;
+    }
+
+    poll_wait(file, &buf->vb.done, wait);
+    if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)
+    {       
+        if( buf->vb.state == VIDEOBUF_DONE )
+        {            
+            struct cx25821_dev *dev = fh->dev;
+            
+            if( dev && dev->use_cif_resolution[SRAM_CH00] )
+            {
+                u8 cam_id = *((char*)buf->vb.baddr+3); 
+                memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2));                      
+                *((char*)buf->vb.baddr+3) = cam_id;
+            }
+        }
+        
+        return POLLIN|POLLRDNORM;
+    }
+    
+    return 0;
+}
+
+
+static int video_release(struct file *file)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev;
+
+    //stop the risc engine and fifo
+    cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */
+
+    /* stop video capture */
+    if (res_check(fh, RESOURCE_VIDEO0)) {
+        videobuf_queue_cancel(&fh->vidq);
+        res_free(dev, fh, RESOURCE_VIDEO0);
+    }
+
+    if (fh->vidq.read_buf) {
+        buffer_release(&fh->vidq, fh->vidq.read_buf);
+        kfree(fh->vidq.read_buf);
+    }
+
+    videobuf_mmap_free(&fh->vidq);
+
+    v4l2_prio_close(&dev->prio,&fh->prio);
+    file->private_data = NULL;
+    kfree(fh);
+
+    return 0;
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+
+    if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(i != fh->type))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO0))))
+    {
+        return -EBUSY;
+    }
+
+    return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+    int err, res;
+
+    if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+        return -EINVAL;
+    if (i != fh->type)
+        return -EINVAL;
+
+    res = get_resource(fh, RESOURCE_VIDEO0);
+    err = videobuf_streamoff(get_queue(fh));
+    if (err < 0)
+        return err;
+    res_free(dev, fh, res);
+    return 0;
+}
+
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    int err;    
+    int pix_format = PIXEL_FRMT_422;
+    
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    dprintk(2, "%s()\n", __func__);
+    err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+    if (0 != err)
+        return err;
+
+    fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+    fh->vidq.field = f->fmt.pix.field;
+
+    // check if width and height is valid based on set standard
+    if (is_valid_width(f->fmt.pix.width, dev->tvnorm))
+    {
+        fh->width      = f->fmt.pix.width;
+    }
+
+    if (is_valid_height(f->fmt.pix.height, dev->tvnorm))
+    {
+        fh->height     = f->fmt.pix.height;
+    }
+
+    if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+       pix_format = PIXEL_FRMT_411;
+    else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+        pix_format = PIXEL_FRMT_422;
+    else
+        return -EINVAL;
+
+    cx25821_set_pixel_format( dev, SRAM_CH00, pix_format ); 
+    // check if cif resolution
+    if (fh->width == 320 || fh->width == 352)
+    {
+        dev->use_cif_resolution[SRAM_CH00] = 1;
+    }else
+    {
+        dev->use_cif_resolution[SRAM_CH00] = 0;
+    }
+    dev->cif_width[SRAM_CH00]          = fh->width;
+    medusa_set_resolution( dev, fh->width, SRAM_CH00 ); 
+
+    dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field);
+    cx25821_call_all(dev, video, s_fmt, f);
+
+    return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+    int ret_val = 0;
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+
+    ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); 
+
+    p->sequence = dev->vidq[SRAM_CH00].count;
+
+    return ret_val;
+}
+
+static int vidioc_log_status (struct file *file, void *priv)
+{
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    char name[32 + 2];
+
+    struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH00];  
+    u32 tmp = 0;
+
+    snprintf(name, sizeof(name), "%s/2", dev->name);
+    printk(KERN_INFO "%s/2: ============  START LOG STATUS  ============\n",
+              dev->name);
+    cx25821_call_all(dev, core, log_status);
+    tmp = cx_read(sram_ch->dma_ctl);
+    printk(KERN_INFO "Video input 0 is %s\n", (tmp & 0x11)?"streaming" : "stopped");
+    printk(KERN_INFO "%s/2: =============  END LOG STATUS  =============\n",
+              dev->name);
+    return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+       struct cx25821_fh *fh = priv;
+        struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+        int err;
+
+        if (fh) {
+               err = v4l2_prio_check(&dev->prio, &fh->prio);
+               if (0 != err)
+                       return err;
+       }
+
+       return cx25821_set_control(dev, ctl, SRAM_CH00);
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+    .owner         = THIS_MODULE,
+    .open          = video_open,
+    .release       = video_release,
+    .read          = video_read,
+    .poll          = video_poll,
+    .mmap          = video_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_reqbufs           = vidioc_reqbufs,
+    .vidioc_querybuf          = vidioc_querybuf,
+    .vidioc_qbuf              = vidioc_qbuf,
+    .vidioc_dqbuf             = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+    .vidioc_s_std             = vidioc_s_std,
+    .vidioc_querystd          = vidioc_querystd,
+#endif
+    .vidioc_cropcap           = vidioc_cropcap,
+    .vidioc_s_crop            = vidioc_s_crop,
+    .vidioc_g_crop            = vidioc_g_crop,
+    .vidioc_enum_input        = vidioc_enum_input,
+    .vidioc_g_input           = vidioc_g_input,
+    .vidioc_s_input           = vidioc_s_input,
+    .vidioc_g_ctrl            = vidioc_g_ctrl,
+    .vidioc_s_ctrl            = vidioc_s_ctrl,
+    .vidioc_queryctrl        = vidioc_queryctrl,
+    .vidioc_streamon          = vidioc_streamon,
+    .vidioc_streamoff         = vidioc_streamoff,
+    .vidioc_log_status        = vidioc_log_status,
+    .vidioc_g_priority       = vidioc_g_priority,
+    .vidioc_s_priority       = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+    .vidiocgmbuf          = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+    .vidioc_g_tuner       = vidioc_g_tuner,
+    .vidioc_s_tuner       = vidioc_s_tuner,
+    .vidioc_g_frequency   = vidioc_g_frequency,
+    .vidioc_s_frequency   = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+    .vidioc_g_register    = vidioc_g_register,
+    .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template0 = {
+    .name                 = "cx25821-video",
+    .fops                 = &video_fops,
+    .minor                = -1,
+    .ioctl_ops            = &video_ioctl_ops,
+    .tvnorms              = CX25821_NORMS,
+    .current_norm         = V4L2_STD_NTSC_M,
+};
+
+
+
diff --git a/drivers/staging/cx25821/cx25821-video1.c b/drivers/staging/cx25821/cx25821-video1.c
new file mode 100644 (file)
index 0000000..44db119
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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 "cx25821-video.h"
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+    struct cx25821_buffer   *buf = container_of(vb, struct cx25821_buffer, vb);
+    struct cx25821_buffer   *prev;
+    struct cx25821_fh       *fh   = vq->priv_data;
+    struct cx25821_dev      *dev  = fh->dev;
+    struct cx25821_dmaqueue *q    = &dev->vidq[SRAM_CH01];
+
+
+    /* add jump to stopper */
+    buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+    buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+    buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+    dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+    if (!list_empty(&q->queued)) {
+        list_add_tail(&buf->vb.queue, &q->queued);
+        buf->vb.state = VIDEOBUF_QUEUED;
+        dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i);
+
+    } else if (list_empty(&q->active)) {
+        list_add_tail(&buf->vb.queue, &q->active);
+        cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH01]);
+        buf->vb.state = VIDEOBUF_ACTIVE;
+        buf->count    = q->count++;
+        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+        dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+                                buf, buf->vb. i, buf->count, q->count);
+    } else {
+        prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+        if (prev->vb.width  == buf->vb.width  &&
+            prev->vb.height == buf->vb.height &&
+            prev->fmt       == buf->fmt) {
+            list_add_tail(&buf->vb.queue, &q->active);
+            buf->vb.state = VIDEOBUF_ACTIVE;
+            buf->count    = q->count++;
+            prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+            /* 64 bit bits 63-32 */
+            prev->risc.jmp[2] = cpu_to_le32(0);
+            dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",  buf, buf->vb.i, buf->count);
+
+        } else {
+            list_add_tail(&buf->vb.queue, &q->queued);
+            buf->vb.state = VIDEOBUF_QUEUED;
+            dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i);
+        }
+    }
+
+    if (list_empty(&q->active))
+    {
+       dprintk(2, "active queue empty!\n");
+    }
+}
+
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+    .buf_setup    = buffer_setup,
+    .buf_prepare  = buffer_prepare,
+    .buf_queue    = buffer_queue,
+    .buf_release  = buffer_release,
+};
+
+
+static int video_open(struct file *file)
+{
+    int minor = video_devdata(file)->minor;
+    struct cx25821_dev *h, *dev = NULL;
+    struct cx25821_fh *fh;
+    struct list_head *list;
+    enum v4l2_buf_type type = 0;
+    u32 pix_format;
+
+    lock_kernel();
+    list_for_each(list, &cx25821_devlist)
+    {
+        h = list_entry(list, struct cx25821_dev, devlist);
+
+        if (h->video_dev[SRAM_CH01] && h->video_dev[SRAM_CH01]->minor == minor) {
+            dev  = h;
+            type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        }
+    }
+
+    if (NULL == dev) {
+        unlock_kernel();
+        return -ENODEV;
+    }
+
+    printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+    /* allocate + initialize per filehandle data */
+    fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+    if (NULL == fh) {
+        unlock_kernel();
+        return -ENOMEM;
+    }
+
+    file->private_data = fh;
+    fh->dev      = dev;
+    fh->type     = type;
+    fh->width    = 720;
+
+    if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+        fh->height = 576;
+    else
+        fh->height = 480;
+
+    dev->channel_opened = SRAM_CH01;
+    pix_format          = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+    fh->fmt             = format_by_fourcc(pix_format);
+
+    v4l2_prio_open(&dev->prio,&fh->prio);
+
+    videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+                &dev->pci->dev, &dev->slock,
+                V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                V4L2_FIELD_INTERLACED,
+                sizeof(struct cx25821_buffer),
+                fh);
+
+    dprintk(1, "post videobuf_queue_init()\n");
+    unlock_kernel();
+
+    return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+    struct cx25821_fh *fh = file->private_data;
+
+    switch (fh->type)
+    {
+        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+            if (res_locked(fh->dev, RESOURCE_VIDEO1))
+                return -EBUSY;
+
+            return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK);
+
+        default:
+            BUG();
+            return 0;
+    }
+}
+
+static unsigned int video_poll(struct file *file, struct poll_table_struct *wait)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_buffer *buf;
+
+    if (res_check(fh, RESOURCE_VIDEO1)) {
+        /* streaming capture */
+        if (list_empty(&fh->vidq.stream))
+            return POLLERR;
+        buf = list_entry(fh->vidq.stream.next,
+            struct cx25821_buffer, vb.stream);
+    } else {
+        /* read() capture */
+        buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+        if (NULL == buf)
+            return POLLERR;
+    }
+
+    poll_wait(file, &buf->vb.done, wait);
+    if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)
+    {        
+        if( buf->vb.state == VIDEOBUF_DONE )
+        {            
+            struct cx25821_dev *dev = fh->dev;
+            
+            if( dev && dev->use_cif_resolution[SRAM_CH01] )
+            {
+                u8 cam_id = *((char*)buf->vb.baddr+3); 
+                memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2));                      
+                *((char*)buf->vb.baddr+3) = cam_id;
+            }
+        }
+        
+        return POLLIN|POLLRDNORM;
+    }
+    
+    return 0;
+}
+
+static int video_release(struct file *file)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev;
+
+    //stop the risc engine and fifo
+    cx_write(channel1->dma_ctl, 0);  /* FIFO and RISC disable */
+
+    /* stop video capture */
+    if (res_check(fh, RESOURCE_VIDEO1)) {
+        videobuf_queue_cancel(&fh->vidq);
+        res_free(dev, fh, RESOURCE_VIDEO1);
+    }
+
+    if (fh->vidq.read_buf) {
+        buffer_release(&fh->vidq, fh->vidq.read_buf);
+        kfree(fh->vidq.read_buf);
+    }
+
+    videobuf_mmap_free(&fh->vidq);
+
+    v4l2_prio_close(&dev->prio,&fh->prio);
+    file->private_data = NULL;
+    kfree(fh);
+
+    return 0;
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+
+    if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(i != fh->type))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO1))))
+    {
+        return -EBUSY;
+    }
+
+    return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+    int err, res;
+
+    if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+        return -EINVAL;
+    if (i != fh->type)
+        return -EINVAL;
+
+    res = get_resource(fh, RESOURCE_VIDEO1);
+    err = videobuf_streamoff(get_queue(fh));
+    if (err < 0)
+        return err;
+    res_free(dev, fh, res);
+    return 0;
+}
+
+
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    int err;    
+    int pix_format = 0;
+   
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    dprintk(2, "%s()\n", __func__);
+    err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+    if (0 != err)
+        return err;
+
+    fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+    fh->vidq.field = f->fmt.pix.field;
+
+    // check if width and height is valid based on set standard
+    if (is_valid_width(f->fmt.pix.width, dev->tvnorm))
+    {
+        fh->width      = f->fmt.pix.width;
+    }
+
+    if (is_valid_height(f->fmt.pix.height, dev->tvnorm))
+    {
+        fh->height     = f->fmt.pix.height;
+    }
+
+    if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+       pix_format = PIXEL_FRMT_411;
+    else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+        pix_format = PIXEL_FRMT_422;
+    else
+        return -EINVAL;
+
+    cx25821_set_pixel_format( dev, SRAM_CH01, pix_format ); 
+    // check if cif resolution
+    if (fh->width == 320 || fh->width == 352)
+    {
+        dev->use_cif_resolution[SRAM_CH01] = 1;
+    }else
+    {
+       dev->use_cif_resolution[SRAM_CH01] = 0;
+    }
+    dev->cif_width[SRAM_CH01]          = fh->width;
+    medusa_set_resolution( dev, fh->width, SRAM_CH01 ); 
+
+    dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field);
+    cx25821_call_all(dev, video, s_fmt, f);
+
+    return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+    int ret_val = 0;
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+
+    ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); 
+
+    p->sequence = dev->vidq[SRAM_CH01].count;
+
+    return ret_val;
+}
+
+static int vidioc_log_status (struct file *file, void *priv)
+{
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    char name[32 + 2];
+
+    struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH01];  
+    u32 tmp = 0;
+
+    snprintf(name, sizeof(name), "%s/2", dev->name);
+    printk(KERN_INFO "%s/2: ============  START LOG STATUS  ============\n",
+              dev->name);
+    cx25821_call_all(dev, core, log_status);
+    tmp = cx_read(sram_ch->dma_ctl);
+    printk(KERN_INFO "Video input 1 is %s\n", (tmp & 0x11)?"streaming" : "stopped");
+    printk(KERN_INFO "%s/2: =============  END LOG STATUS  =============\n",
+              dev->name);
+    return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+       struct cx25821_fh *fh = priv;
+        struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+        int err;
+
+        if (fh) {
+               err = v4l2_prio_check(&dev->prio, &fh->prio);
+               if (0 != err)
+                       return err;
+       }
+
+       return cx25821_set_control(dev, ctl, SRAM_CH01);
+}
+//exported stuff
+static const struct v4l2_file_operations video_fops = {
+    .owner         = THIS_MODULE,
+    .open          = video_open,
+    .release       = video_release,
+    .read          = video_read,
+    .poll          = video_poll,
+    .mmap          = video_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_reqbufs           = vidioc_reqbufs,
+    .vidioc_querybuf          = vidioc_querybuf,
+    .vidioc_qbuf              = vidioc_qbuf,
+    .vidioc_dqbuf             = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+    .vidioc_s_std             = vidioc_s_std,
+    .vidioc_querystd          = vidioc_querystd,
+#endif
+    .vidioc_cropcap           = vidioc_cropcap,
+    .vidioc_s_crop            = vidioc_s_crop,
+    .vidioc_g_crop            = vidioc_g_crop,
+    .vidioc_enum_input        = vidioc_enum_input,
+    .vidioc_g_input           = vidioc_g_input,
+    .vidioc_s_input           = vidioc_s_input,
+    .vidioc_g_ctrl            = vidioc_g_ctrl,
+    .vidioc_s_ctrl            = vidioc_s_ctrl,
+    .vidioc_queryctrl        = vidioc_queryctrl,
+    .vidioc_streamon          = vidioc_streamon,
+    .vidioc_streamoff         = vidioc_streamoff,
+    .vidioc_log_status        = vidioc_log_status,
+    .vidioc_g_priority       = vidioc_g_priority,
+    .vidioc_s_priority       = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+    .vidiocgmbuf          = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+    .vidioc_g_tuner       = vidioc_g_tuner,
+    .vidioc_s_tuner       = vidioc_s_tuner,
+    .vidioc_g_frequency   = vidioc_g_frequency,
+    .vidioc_s_frequency   = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+    .vidioc_g_register    = vidioc_g_register,
+    .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template1 = {
+    .name                 = "cx25821-video",
+    .fops                 = &video_fops,
+    .minor                = -1,
+    .ioctl_ops            = &video_ioctl_ops,
+    .tvnorms              = CX25821_NORMS,
+    .current_norm         = V4L2_STD_NTSC_M,
+};
+
+
+
diff --git a/drivers/staging/cx25821/cx25821-video2.c b/drivers/staging/cx25821/cx25821-video2.c
new file mode 100644 (file)
index 0000000..98db148
--- /dev/null
@@ -0,0 +1,459 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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 "cx25821-video.h"
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+    struct cx25821_buffer   *buf = container_of(vb, struct cx25821_buffer, vb);
+    struct cx25821_buffer   *prev;
+    struct cx25821_fh       *fh   = vq->priv_data;
+    struct cx25821_dev      *dev  = fh->dev;
+    struct cx25821_dmaqueue *q    = &dev->vidq[SRAM_CH02];
+
+
+    /* add jump to stopper */
+    buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+    buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+    buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+    dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+    if (!list_empty(&q->queued)) {
+        list_add_tail(&buf->vb.queue, &q->queued);
+        buf->vb.state = VIDEOBUF_QUEUED;
+        dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i);
+
+    } else if (list_empty(&q->active)) {
+        list_add_tail(&buf->vb.queue, &q->active);
+        cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH02]);
+        buf->vb.state = VIDEOBUF_ACTIVE;
+        buf->count    = q->count++;
+        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+        dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+                                buf, buf->vb. i, buf->count, q->count);
+    } else {
+        prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+        if (prev->vb.width  == buf->vb.width  &&
+            prev->vb.height == buf->vb.height &&
+            prev->fmt       == buf->fmt) {
+            list_add_tail(&buf->vb.queue, &q->active);
+            buf->vb.state = VIDEOBUF_ACTIVE;
+            buf->count    = q->count++;
+            prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+            /* 64 bit bits 63-32 */
+            prev->risc.jmp[2] = cpu_to_le32(0);
+            dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",  buf, buf->vb.i, buf->count);
+
+        } else {
+            list_add_tail(&buf->vb.queue, &q->queued);
+            buf->vb.state = VIDEOBUF_QUEUED;
+            dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i);
+        }
+    }
+
+    if (list_empty(&q->active))
+    {
+       dprintk(2, "active queue empty!\n");
+    }
+}
+
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+    .buf_setup    = buffer_setup,
+    .buf_prepare  = buffer_prepare,
+    .buf_queue    = buffer_queue,
+    .buf_release  = buffer_release,
+};
+
+
+static int video_open(struct file *file)
+{
+    int minor = video_devdata(file)->minor;
+    struct cx25821_dev *h, *dev = NULL;
+    struct cx25821_fh *fh;
+    struct list_head *list;
+    enum v4l2_buf_type type = 0;
+    u32 pix_format;
+
+    lock_kernel();
+    list_for_each(list, &cx25821_devlist)
+    {
+        h = list_entry(list, struct cx25821_dev, devlist);
+
+        if (h->video_dev[SRAM_CH02] && h->video_dev[SRAM_CH02]->minor == minor) {
+            dev  = h;
+            type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        }
+    }
+
+    if (NULL == dev) {
+        unlock_kernel();
+        return -ENODEV;
+    }
+
+    printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+    /* allocate + initialize per filehandle data */
+    fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+    if (NULL == fh) {
+        unlock_kernel();
+        return -ENOMEM;
+    }
+    file->private_data = fh;
+    fh->dev      = dev;
+    fh->type     = type;
+    fh->width    = 720;
+
+    if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+        fh->height = 576;
+    else
+        fh->height = 480;
+
+    dev->channel_opened = SRAM_CH02;
+    pix_format          = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+    fh->fmt             = format_by_fourcc(pix_format);
+
+    v4l2_prio_open(&dev->prio,&fh->prio);
+
+    videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+                &dev->pci->dev, &dev->slock,
+                V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                V4L2_FIELD_INTERLACED,
+                sizeof(struct cx25821_buffer),
+                fh);
+
+    dprintk(1, "post videobuf_queue_init()\n");
+    unlock_kernel();
+
+    return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+    struct cx25821_fh *fh = file->private_data;
+
+    switch (fh->type)
+    {
+        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+            if (res_locked(fh->dev, RESOURCE_VIDEO2))
+                return -EBUSY;
+
+            return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK);
+
+        default:
+            BUG();
+            return 0;
+    }
+}
+
+static unsigned int video_poll(struct file *file, struct poll_table_struct *wait)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_buffer *buf;
+
+    if (res_check(fh, RESOURCE_VIDEO2)) {
+        /* streaming capture */
+        if (list_empty(&fh->vidq.stream))
+            return POLLERR;
+        buf = list_entry(fh->vidq.stream.next,
+            struct cx25821_buffer, vb.stream);
+    } else {
+        /* read() capture */
+        buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+        if (NULL == buf)
+            return POLLERR;
+    }
+
+    poll_wait(file, &buf->vb.done, wait);
+    if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)
+    {        
+        if( buf->vb.state == VIDEOBUF_DONE )
+        {            
+            struct cx25821_dev *dev = fh->dev;
+            
+            if( dev && dev->use_cif_resolution[SRAM_CH02] )
+            {
+                u8 cam_id = *((char*)buf->vb.baddr+3); 
+                memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2));                      
+                *((char*)buf->vb.baddr+3) = cam_id;
+            }
+        }
+        
+        return POLLIN|POLLRDNORM;
+    }
+    
+    return 0;
+}
+
+
+static int video_release(struct file *file)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev;
+
+    //stop the risc engine and fifo
+    cx_write(channel2->dma_ctl, 0); /* FIFO and RISC disable */
+
+    /* stop video capture */
+    if (res_check(fh, RESOURCE_VIDEO2)) {
+        videobuf_queue_cancel(&fh->vidq);
+        res_free(dev, fh, RESOURCE_VIDEO2);
+    }
+
+    if (fh->vidq.read_buf) {
+        buffer_release(&fh->vidq, fh->vidq.read_buf);
+        kfree(fh->vidq.read_buf);
+    }
+
+    videobuf_mmap_free(&fh->vidq);
+
+    v4l2_prio_close(&dev->prio,&fh->prio);
+    file->private_data = NULL;
+    kfree(fh);
+
+    return 0;
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+
+    if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(i != fh->type))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO2))))
+    {
+        return -EBUSY;
+    }
+
+    return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+    int err, res;
+
+    if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+        return -EINVAL;
+    if (i != fh->type)
+        return -EINVAL;
+
+    res = get_resource(fh, RESOURCE_VIDEO2);
+    err = videobuf_streamoff(get_queue(fh));
+    if (err < 0)
+        return err;
+    res_free(dev, fh, res);
+    return 0;
+}
+
+
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    int err;    
+    int pix_format = 0;
+   
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    dprintk(2, "%s()\n", __func__);
+    err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+    if (0 != err)
+        return err;
+
+    fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+    fh->vidq.field = f->fmt.pix.field;
+
+    // check if width and height is valid based on set standard
+    if (is_valid_width(f->fmt.pix.width, dev->tvnorm))
+    {
+        fh->width      = f->fmt.pix.width;
+    }
+
+    if (is_valid_height(f->fmt.pix.height, dev->tvnorm))
+    {
+        fh->height     = f->fmt.pix.height;
+    }
+
+    if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+        pix_format = PIXEL_FRMT_411;
+    else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+        pix_format = PIXEL_FRMT_422;
+    else
+        return -EINVAL;
+
+    cx25821_set_pixel_format( dev, SRAM_CH02, pix_format ); 
+    // check if cif resolution
+    if (fh->width == 320 || fh->width == 352)
+    {
+        dev->use_cif_resolution[SRAM_CH02] = 1;
+    }else
+    {
+       dev->use_cif_resolution[SRAM_CH02] = 0;
+    }
+    dev->cif_width[SRAM_CH02]          = fh->width;
+    medusa_set_resolution( dev, fh->width, SRAM_CH02 ); 
+
+
+    dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field);
+    cx25821_call_all(dev, video, s_fmt, f);
+
+    return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+    int ret_val = 0;
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+
+    ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); 
+
+    p->sequence = dev->vidq[SRAM_CH02].count;
+
+    return ret_val;
+}
+
+static int vidioc_log_status (struct file *file, void *priv)
+{
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    char name[32 + 2];
+
+    struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH02];  
+    u32 tmp = 0;
+
+    snprintf(name, sizeof(name), "%s/2", dev->name);
+    printk(KERN_INFO "%s/2: ============  START LOG STATUS  ============\n",
+              dev->name);
+    
+    cx25821_call_all(dev, core, log_status);
+    
+    tmp = cx_read(sram_ch->dma_ctl);
+    printk(KERN_INFO "Video input 2 is %s\n", (tmp & 0x11)?"streaming" : "stopped");
+    printk(KERN_INFO "%s/2: =============  END LOG STATUS  =============\n",
+              dev->name);
+    return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+       struct cx25821_fh *fh = priv;
+        struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+        int err;
+
+        if (fh) {
+               err = v4l2_prio_check(&dev->prio, &fh->prio);
+               if (0 != err)
+                       return err;
+       }
+
+       return cx25821_set_control(dev, ctl, SRAM_CH02);
+}
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+    .owner         = THIS_MODULE,
+    .open          = video_open,
+    .release       = video_release,
+    .read          = video_read,
+    .poll          = video_poll,
+    .mmap          = video_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_reqbufs       = vidioc_reqbufs,
+    .vidioc_querybuf      = vidioc_querybuf,
+    .vidioc_qbuf          = vidioc_qbuf,
+    .vidioc_dqbuf         = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+    .vidioc_s_std         = vidioc_s_std,
+    .vidioc_querystd      = vidioc_querystd,
+#endif
+    .vidioc_cropcap       = vidioc_cropcap,
+    .vidioc_s_crop        = vidioc_s_crop,
+    .vidioc_g_crop        = vidioc_g_crop,
+    .vidioc_enum_input    = vidioc_enum_input,
+    .vidioc_g_input       = vidioc_g_input,
+    .vidioc_s_input       = vidioc_s_input,
+    .vidioc_g_ctrl        = vidioc_g_ctrl,
+    .vidioc_s_ctrl        = vidioc_s_ctrl,
+    .vidioc_queryctrl    = vidioc_queryctrl,
+    .vidioc_streamon      = vidioc_streamon,
+    .vidioc_streamoff     = vidioc_streamoff,
+    .vidioc_log_status    = vidioc_log_status,
+    .vidioc_g_priority   = vidioc_g_priority,
+    .vidioc_s_priority   = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+    .vidiocgmbuf          = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+    .vidioc_g_tuner       = vidioc_g_tuner,
+    .vidioc_s_tuner       = vidioc_s_tuner,
+    .vidioc_g_frequency   = vidioc_g_frequency,
+    .vidioc_s_frequency   = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+    .vidioc_g_register    = vidioc_g_register,
+    .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template2 = {
+    .name                 = "cx25821-video",
+    .fops                 = &video_fops,
+    .minor                = -1,
+    .ioctl_ops            = &video_ioctl_ops,
+    .tvnorms              = CX25821_NORMS,
+    .current_norm         = V4L2_STD_NTSC_M,
+};
+
+
+
diff --git a/drivers/staging/cx25821/cx25821-video3.c b/drivers/staging/cx25821/cx25821-video3.c
new file mode 100644 (file)
index 0000000..3dcecd2
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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 "cx25821-video.h"
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+    struct cx25821_buffer   *buf = container_of(vb, struct cx25821_buffer, vb);
+    struct cx25821_buffer   *prev;
+    struct cx25821_fh       *fh   = vq->priv_data;
+    struct cx25821_dev      *dev  = fh->dev;
+    struct cx25821_dmaqueue *q    = &dev->vidq[SRAM_CH03];
+
+
+    /* add jump to stopper */
+    buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+    buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+    buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+    dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+    if (!list_empty(&q->queued)) {
+        list_add_tail(&buf->vb.queue, &q->queued);
+        buf->vb.state = VIDEOBUF_QUEUED;
+        dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i);
+
+    } else if (list_empty(&q->active)) {
+        list_add_tail(&buf->vb.queue, &q->active);
+        cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH03]);
+        buf->vb.state = VIDEOBUF_ACTIVE;
+        buf->count    = q->count++;
+        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+        dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+                                buf, buf->vb. i, buf->count, q->count);
+    } else {
+        prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+        if (prev->vb.width  == buf->vb.width  &&
+            prev->vb.height == buf->vb.height &&
+            prev->fmt       == buf->fmt) {
+            list_add_tail(&buf->vb.queue, &q->active);
+            buf->vb.state = VIDEOBUF_ACTIVE;
+            buf->count    = q->count++;
+            prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+            /* 64 bit bits 63-32 */
+            prev->risc.jmp[2] = cpu_to_le32(0);
+            dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",  buf, buf->vb.i, buf->count);
+
+        } else {
+            list_add_tail(&buf->vb.queue, &q->queued);
+            buf->vb.state = VIDEOBUF_QUEUED;
+            dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i);
+        }
+    }
+
+    if (list_empty(&q->active))
+    {
+       dprintk(2, "active queue empty!\n");
+    }
+}
+
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+    .buf_setup    = buffer_setup,
+    .buf_prepare  = buffer_prepare,
+    .buf_queue    = buffer_queue,
+    .buf_release  = buffer_release,
+};
+
+
+static int video_open(struct file *file)
+{
+    int minor = video_devdata(file)->minor;
+    struct cx25821_dev *h, *dev = NULL;
+    struct cx25821_fh *fh;
+    struct list_head *list;
+    enum v4l2_buf_type type = 0;
+    u32 pix_format;
+
+    lock_kernel();
+    list_for_each(list, &cx25821_devlist)
+    {
+        h = list_entry(list, struct cx25821_dev, devlist);
+
+        if (h->video_dev[SRAM_CH03] && h->video_dev[SRAM_CH03]->minor == minor) {
+            dev  = h;
+            type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        }
+    }
+
+    if (NULL == dev) {
+        unlock_kernel();
+        return -ENODEV;
+    }
+
+    printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+    /* allocate + initialize per filehandle data */
+    fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+    if (NULL == fh) {
+        unlock_kernel();
+        return -ENOMEM;
+    }
+    file->private_data = fh;
+    fh->dev      = dev;
+    fh->type     = type;
+    fh->width    = 720;
+
+    if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+        fh->height = 576;
+    else
+        fh->height = 480;
+
+    dev->channel_opened = SRAM_CH03;
+    pix_format          = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+    fh->fmt             = format_by_fourcc(pix_format);
+
+    v4l2_prio_open(&dev->prio,&fh->prio);
+
+    videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+                &dev->pci->dev, &dev->slock,
+                V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                V4L2_FIELD_INTERLACED,
+                sizeof(struct cx25821_buffer),
+                fh);
+
+    dprintk(1, "post videobuf_queue_init()\n");
+    unlock_kernel();
+
+    return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+    struct cx25821_fh *fh = file->private_data;
+
+    switch (fh->type)
+    {
+        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+            if (res_locked(fh->dev, RESOURCE_VIDEO3))
+                return -EBUSY;
+
+            return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK);
+
+        default:
+            BUG();
+            return 0;
+    }
+}
+
+static unsigned int video_poll(struct file *file, struct poll_table_struct *wait)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_buffer *buf;
+
+    if (res_check(fh, RESOURCE_VIDEO3)) {
+        /* streaming capture */
+        if (list_empty(&fh->vidq.stream))
+            return POLLERR;
+        buf = list_entry(fh->vidq.stream.next,
+            struct cx25821_buffer, vb.stream);
+    } else {
+        /* read() capture */
+        buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+        if (NULL == buf)
+            return POLLERR;
+    }
+
+    poll_wait(file, &buf->vb.done, wait);
+    if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)
+    {        
+        if( buf->vb.state == VIDEOBUF_DONE )
+        {            
+            struct cx25821_dev *dev = fh->dev;
+            
+            if( dev && dev->use_cif_resolution[SRAM_CH03] )
+            {
+                u8 cam_id = *((char*)buf->vb.baddr+3); 
+                memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2));                      
+                *((char*)buf->vb.baddr+3) = cam_id;
+            }
+        }
+        
+        return POLLIN|POLLRDNORM;
+    }
+    
+    return 0;
+}
+
+
+static int video_release(struct file *file)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev;
+
+    //stop the risc engine and fifo
+    cx_write(channel3->dma_ctl, 0); /* FIFO and RISC disable */
+
+    /* stop video capture */
+    if (res_check(fh, RESOURCE_VIDEO3)) {
+        videobuf_queue_cancel(&fh->vidq);
+        res_free(dev, fh, RESOURCE_VIDEO3);
+    }
+
+    if (fh->vidq.read_buf) {
+        buffer_release(&fh->vidq, fh->vidq.read_buf);
+        kfree(fh->vidq.read_buf);
+    }
+
+    videobuf_mmap_free(&fh->vidq);
+
+    v4l2_prio_close(&dev->prio,&fh->prio);
+    file->private_data = NULL;
+    kfree(fh);
+
+    return 0;
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+
+    if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(i != fh->type))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO3))))
+    {
+        return -EBUSY;
+    }
+
+    return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+    int err, res;
+
+    if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+        return -EINVAL;
+    if (i != fh->type)
+        return -EINVAL;
+
+    res = get_resource(fh, RESOURCE_VIDEO3);
+    err = videobuf_streamoff(get_queue(fh));
+    if (err < 0)
+        return err;
+    res_free(dev, fh, res);
+    return 0;
+}
+
+
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    int err;    
+    int pix_format = 0;
+   
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    dprintk(2, "%s()\n", __func__);
+    err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+    if (0 != err)
+        return err;
+
+    fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+    fh->vidq.field = f->fmt.pix.field;
+
+    // check if width and height is valid based on set standard
+    if (is_valid_width(f->fmt.pix.width, dev->tvnorm))
+    {
+        fh->width      = f->fmt.pix.width;
+    }
+
+    if (is_valid_height(f->fmt.pix.height, dev->tvnorm))
+    {
+        fh->height     = f->fmt.pix.height;
+    }
+
+    if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+        pix_format = PIXEL_FRMT_411;
+    else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+        pix_format = PIXEL_FRMT_422;
+    else
+        return -EINVAL;
+
+    cx25821_set_pixel_format( dev, SRAM_CH03, pix_format ); 
+    // check if cif resolution
+    if (fh->width == 320 || fh->width == 352)
+    {
+        dev->use_cif_resolution[SRAM_CH03] = 1;
+    }else
+    {
+        dev->use_cif_resolution[SRAM_CH03] = 0;
+    }
+    dev->cif_width[SRAM_CH03]          = fh->width;
+    medusa_set_resolution( dev, fh->width, SRAM_CH03 ); 
+
+    dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field);
+    cx25821_call_all(dev, video, s_fmt, f);
+
+    return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+    int ret_val = 0;
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+
+    ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); 
+
+    p->sequence = dev->vidq[SRAM_CH03].count;
+
+    return ret_val;
+}
+
+static int vidioc_log_status (struct file *file, void *priv)
+{
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    char name[32 + 2];
+
+    struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH03];  
+    u32 tmp = 0;
+
+    snprintf(name, sizeof(name), "%s/2", dev->name);
+    printk(KERN_INFO "%s/2: ============  START LOG STATUS  ============\n",
+              dev->name);
+    cx25821_call_all(dev, core, log_status);
+
+    tmp = cx_read(sram_ch->dma_ctl);
+    printk(KERN_INFO "Video input 3 is %s\n", (tmp & 0x11)?"streaming" : "stopped");
+    printk(KERN_INFO "%s/2: =============  END LOG STATUS  =============\n",
+              dev->name);
+    return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+       struct cx25821_fh *fh = priv;
+        struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+        int err;
+
+        if (fh) {
+               err = v4l2_prio_check(&dev->prio, &fh->prio);
+               if (0 != err)
+                       return err;
+       }
+
+       return cx25821_set_control(dev, ctl, SRAM_CH03);
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+    .owner         = THIS_MODULE,
+    .open          = video_open,
+    .release       = video_release,
+    .read          = video_read,
+    .poll          = video_poll,
+    .mmap          = video_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_reqbufs           = vidioc_reqbufs,
+    .vidioc_querybuf          = vidioc_querybuf,
+    .vidioc_qbuf              = vidioc_qbuf,
+    .vidioc_dqbuf             = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+    .vidioc_s_std         = vidioc_s_std,
+    .vidioc_querystd      = vidioc_querystd,
+#endif
+    .vidioc_cropcap       = vidioc_cropcap,
+    .vidioc_s_crop        = vidioc_s_crop,
+    .vidioc_g_crop        = vidioc_g_crop,
+    .vidioc_enum_input    = vidioc_enum_input,
+    .vidioc_g_input       = vidioc_g_input,
+    .vidioc_s_input       = vidioc_s_input,
+    .vidioc_g_ctrl        = vidioc_g_ctrl,
+    .vidioc_s_ctrl        = vidioc_s_ctrl,
+    .vidioc_queryctrl    = vidioc_queryctrl,
+    .vidioc_streamon      = vidioc_streamon,
+    .vidioc_streamoff     = vidioc_streamoff,
+    .vidioc_log_status    = vidioc_log_status,
+    .vidioc_g_priority   = vidioc_g_priority,
+    .vidioc_s_priority   = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+    .vidiocgmbuf          = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+    .vidioc_g_tuner       = vidioc_g_tuner,
+    .vidioc_s_tuner       = vidioc_s_tuner,
+    .vidioc_g_frequency   = vidioc_g_frequency,
+    .vidioc_s_frequency   = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+    .vidioc_g_register    = vidioc_g_register,
+    .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template3 = {
+    .name                 = "cx25821-video",
+    .fops                 = &video_fops,
+    .minor                = -1,
+    .ioctl_ops            = &video_ioctl_ops,
+    .tvnorms              = CX25821_NORMS,
+    .current_norm         = V4L2_STD_NTSC_M,
+};
+
+
+
diff --git a/drivers/staging/cx25821/cx25821-video4.c b/drivers/staging/cx25821/cx25821-video4.c
new file mode 100644 (file)
index 0000000..03da364
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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 "cx25821-video.h"
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+    struct cx25821_buffer   *buf = container_of(vb, struct cx25821_buffer, vb);
+    struct cx25821_buffer   *prev;
+    struct cx25821_fh       *fh   = vq->priv_data;
+    struct cx25821_dev      *dev  = fh->dev;
+    struct cx25821_dmaqueue *q    = &dev->vidq[SRAM_CH04];
+
+    /* add jump to stopper */
+    buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+    buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+    buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+    dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+    if (!list_empty(&q->queued)) {
+        list_add_tail(&buf->vb.queue, &q->queued);
+        buf->vb.state = VIDEOBUF_QUEUED;
+        dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i);
+
+    } else if (list_empty(&q->active)) {
+        list_add_tail(&buf->vb.queue, &q->active);
+        cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH04]);
+        buf->vb.state = VIDEOBUF_ACTIVE;
+        buf->count    = q->count++;
+        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+        dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+                                buf, buf->vb. i, buf->count, q->count);
+    } else {
+        prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+        if (prev->vb.width  == buf->vb.width  &&
+            prev->vb.height == buf->vb.height &&
+            prev->fmt       == buf->fmt) {
+            list_add_tail(&buf->vb.queue, &q->active);
+            buf->vb.state = VIDEOBUF_ACTIVE;
+            buf->count    = q->count++;
+            prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+            /* 64 bit bits 63-32 */
+            prev->risc.jmp[2] = cpu_to_le32(0);
+            dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",  buf, buf->vb.i, buf->count);
+
+        } else {
+            list_add_tail(&buf->vb.queue, &q->queued);
+            buf->vb.state = VIDEOBUF_QUEUED;
+            dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i);
+        }
+    }
+
+    if (list_empty(&q->active))
+    {
+       dprintk(2, "active queue empty!\n");
+    }
+}
+
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+    .buf_setup    = buffer_setup,
+    .buf_prepare  = buffer_prepare,
+    .buf_queue    = buffer_queue,
+    .buf_release  = buffer_release,
+};
+
+
+static int video_open(struct file *file)
+{
+    int minor = video_devdata(file)->minor;
+    struct cx25821_dev *h, *dev = NULL;
+    struct cx25821_fh *fh;
+    struct list_head *list;
+    enum v4l2_buf_type type = 0;
+    u32 pix_format;
+
+    lock_kernel();
+    list_for_each(list, &cx25821_devlist)
+    {
+        h = list_entry(list, struct cx25821_dev, devlist);
+
+        if (h->video_dev[SRAM_CH04] && h->video_dev[SRAM_CH04]->minor == minor) {
+            dev  = h;
+            type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        }
+    }
+
+    if (NULL == dev) {
+        unlock_kernel();
+        return -ENODEV;
+    }
+
+    printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+    /* allocate + initialize per filehandle data */
+    fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+    if (NULL == fh) {
+        unlock_kernel();
+        return -ENOMEM;
+    }
+    file->private_data = fh;
+    fh->dev      = dev;
+    fh->type     = type;
+    fh->width    = 720;
+
+    if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+        fh->height = 576;
+    else
+        fh->height = 480;
+
+    dev->channel_opened = SRAM_CH04;
+    pix_format          = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+    fh->fmt             = format_by_fourcc(pix_format);
+
+    v4l2_prio_open(&dev->prio,&fh->prio);
+    videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+                &dev->pci->dev, &dev->slock,
+                V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                V4L2_FIELD_INTERLACED,
+                sizeof(struct cx25821_buffer),
+                fh);
+
+    dprintk(1, "post videobuf_queue_init()\n");
+    unlock_kernel();
+
+    return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+    struct cx25821_fh *fh = file->private_data;
+
+    switch (fh->type)
+    {
+        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+            if (res_locked(fh->dev, RESOURCE_VIDEO4))
+                return -EBUSY;
+
+            return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK);
+
+        default:
+            BUG();
+            return 0;
+    }
+}
+
+static unsigned int video_poll(struct file *file, struct poll_table_struct *wait)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_buffer *buf;
+
+    if (res_check(fh, RESOURCE_VIDEO4)) {
+        /* streaming capture */
+        if (list_empty(&fh->vidq.stream))
+            return POLLERR;
+        buf = list_entry(fh->vidq.stream.next,
+            struct cx25821_buffer, vb.stream);
+    } else {
+        /* read() capture */
+        buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+        if (NULL == buf)
+            return POLLERR;
+    }
+
+    poll_wait(file, &buf->vb.done, wait);
+    if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)
+    {        
+        if( buf->vb.state == VIDEOBUF_DONE )
+        {            
+            struct cx25821_dev *dev = fh->dev;
+            
+            if( dev && dev->use_cif_resolution[SRAM_CH04] )
+            {
+                u8 cam_id = *((char*)buf->vb.baddr+3); 
+                memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2));                      
+                *((char*)buf->vb.baddr+3) = cam_id;
+            }
+        }
+        
+        return POLLIN|POLLRDNORM;
+    }
+    
+    return 0;
+}
+
+
+static int video_release(struct file *file)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev;
+
+    //stop the risc engine and fifo
+    cx_write(channel4->dma_ctl, 0); /* FIFO and RISC disable */
+
+    /* stop video capture */
+    if (res_check(fh, RESOURCE_VIDEO4)) {
+        videobuf_queue_cancel(&fh->vidq);
+        res_free(dev, fh, RESOURCE_VIDEO4);
+    }
+
+    if (fh->vidq.read_buf) {
+        buffer_release(&fh->vidq, fh->vidq.read_buf);
+        kfree(fh->vidq.read_buf);
+    }
+
+    videobuf_mmap_free(&fh->vidq);
+
+    v4l2_prio_close(&dev->prio,&fh->prio);
+    file->private_data = NULL;
+    kfree(fh);
+
+    return 0;
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+
+    if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(i != fh->type))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO4))))
+    {
+        return -EBUSY;
+    }
+
+    return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+    int err, res;
+
+    if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+        return -EINVAL;
+    if (i != fh->type)
+        return -EINVAL;
+
+    res = get_resource(fh, RESOURCE_VIDEO4);
+    err = videobuf_streamoff(get_queue(fh));
+    if (err < 0)
+        return err;
+    res_free(dev, fh, res);
+    return 0;
+}
+
+
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    int err;    
+    int pix_format = 0;
+
+    // check priority
+    if (fh)
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+    dprintk(2, "%s()\n", __func__);
+    err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+    if (0 != err)
+        return err;
+
+    fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+    fh->vidq.field = f->fmt.pix.field;
+
+    // check if width and height is valid based on set standard
+    if (is_valid_width(f->fmt.pix.width, dev->tvnorm))
+    {
+        fh->width      = f->fmt.pix.width;
+    }
+
+    if (is_valid_height(f->fmt.pix.height, dev->tvnorm))
+    {
+        fh->height     = f->fmt.pix.height;
+    }
+
+    if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+        pix_format = PIXEL_FRMT_411;
+    else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+        pix_format = PIXEL_FRMT_422;
+    else
+        return -EINVAL;
+
+    cx25821_set_pixel_format( dev, SRAM_CH04, pix_format ); 
+    // check if cif resolution
+    if (fh->width == 320 || fh->width == 352)
+    {
+        dev->use_cif_resolution[SRAM_CH04] = 1; 
+    }else
+    {
+       dev->use_cif_resolution[SRAM_CH04] = 0;
+    }
+    dev->cif_width[SRAM_CH04]          = fh->width;
+    medusa_set_resolution( dev, fh->width, SRAM_CH04); 
+
+    dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field);
+    cx25821_call_all(dev, video, s_fmt, f);
+
+    return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+    int ret_val = 0;
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+
+    ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); 
+
+    p->sequence = dev->vidq[SRAM_CH04].count;
+
+    return ret_val;
+}
+
+static int vidioc_log_status (struct file *file, void *priv)
+{
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    char name[32 + 2];
+
+    struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH04];  
+    u32 tmp = 0;
+
+    snprintf(name, sizeof(name), "%s/2", dev->name);
+    printk(KERN_INFO "%s/2: ============  START LOG STATUS  ============\n",
+              dev->name);
+    cx25821_call_all(dev, core, log_status);
+
+    tmp = cx_read(sram_ch->dma_ctl);
+    printk(KERN_INFO "Video input 4 is %s\n", (tmp & 0x11)?"streaming" : "stopped");
+    printk(KERN_INFO "%s/2: =============  END LOG STATUS  =============\n",
+              dev->name);
+    return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+       struct cx25821_fh *fh = priv;
+        struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+        int err;
+
+        if (fh) {
+               err = v4l2_prio_check(&dev->prio, &fh->prio);
+               if (0 != err)
+                       return err;
+       }
+
+       return cx25821_set_control(dev, ctl, SRAM_CH04);
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+    .owner         = THIS_MODULE,
+    .open          = video_open,
+    .release       = video_release,
+    .read          = video_read,
+    .poll          = video_poll,
+    .mmap          = video_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_reqbufs       = vidioc_reqbufs,
+    .vidioc_querybuf      = vidioc_querybuf,
+    .vidioc_qbuf          = vidioc_qbuf,
+    .vidioc_dqbuf         = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+    .vidioc_s_std         = vidioc_s_std,
+    .vidioc_querystd      = vidioc_querystd,
+#endif
+    .vidioc_cropcap       = vidioc_cropcap,
+    .vidioc_s_crop        = vidioc_s_crop,
+    .vidioc_g_crop        = vidioc_g_crop,
+    .vidioc_enum_input    = vidioc_enum_input,
+    .vidioc_g_input       = vidioc_g_input,
+    .vidioc_s_input       = vidioc_s_input,
+    .vidioc_g_ctrl        = vidioc_g_ctrl,
+    .vidioc_s_ctrl        = vidioc_s_ctrl,
+    .vidioc_queryctrl    = vidioc_queryctrl,
+    .vidioc_streamon      = vidioc_streamon,
+    .vidioc_streamoff     = vidioc_streamoff,
+    .vidioc_log_status    = vidioc_log_status,
+    .vidioc_g_priority   = vidioc_g_priority,
+    .vidioc_s_priority   = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+    .vidiocgmbuf          = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+    .vidioc_g_tuner       = vidioc_g_tuner,
+    .vidioc_s_tuner       = vidioc_s_tuner,
+    .vidioc_g_frequency   = vidioc_g_frequency,
+    .vidioc_s_frequency   = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+    .vidioc_g_register    = vidioc_g_register,
+    .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template4 = {
+    .name                 = "cx25821-video",
+    .fops                 = &video_fops,
+    .minor                = -1,
+    .ioctl_ops            = &video_ioctl_ops,
+    .tvnorms              = CX25821_NORMS,
+    .current_norm         = V4L2_STD_NTSC_M,
+};
+
+
+
diff --git a/drivers/staging/cx25821/cx25821-video5.c b/drivers/staging/cx25821/cx25821-video5.c
new file mode 100644 (file)
index 0000000..1d47543
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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 "cx25821-video.h"
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+    struct cx25821_buffer   *buf = container_of(vb, struct cx25821_buffer, vb);
+    struct cx25821_buffer   *prev;
+    struct cx25821_fh       *fh   = vq->priv_data;
+    struct cx25821_dev      *dev  = fh->dev;
+    struct cx25821_dmaqueue *q    = &dev->vidq[SRAM_CH05];
+
+    /* add jump to stopper */
+    buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+    buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+    buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+    dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+    if (!list_empty(&q->queued)) {
+        list_add_tail(&buf->vb.queue, &q->queued);
+        buf->vb.state = VIDEOBUF_QUEUED;
+        dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i);
+
+    } else if (list_empty(&q->active)) {
+        list_add_tail(&buf->vb.queue, &q->active);
+        cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH05]);
+        buf->vb.state = VIDEOBUF_ACTIVE;
+        buf->count    = q->count++;
+        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+        dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+                                buf, buf->vb. i, buf->count, q->count);
+    } else {
+        prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+        if (prev->vb.width  == buf->vb.width  &&
+            prev->vb.height == buf->vb.height &&
+            prev->fmt       == buf->fmt) {
+            list_add_tail(&buf->vb.queue, &q->active);
+            buf->vb.state = VIDEOBUF_ACTIVE;
+            buf->count    = q->count++;
+            prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+            /* 64 bit bits 63-32 */
+            prev->risc.jmp[2] = cpu_to_le32(0);
+            dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",  buf, buf->vb.i, buf->count);
+
+        } else {
+            list_add_tail(&buf->vb.queue, &q->queued);
+            buf->vb.state = VIDEOBUF_QUEUED;
+            dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i);
+        }
+    }
+
+    if (list_empty(&q->active))
+    {
+       dprintk(2, "active queue empty!\n");
+    }
+}
+
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+    .buf_setup    = buffer_setup,
+    .buf_prepare  = buffer_prepare,
+    .buf_queue    = buffer_queue,
+    .buf_release  = buffer_release,
+};
+
+
+static int video_open(struct file *file)
+{
+    int minor = video_devdata(file)->minor;
+    struct cx25821_dev *h, *dev = NULL;
+    struct cx25821_fh *fh;
+    struct list_head *list;
+    enum v4l2_buf_type type = 0;
+    u32 pix_format;
+
+    lock_kernel();
+    list_for_each(list, &cx25821_devlist)
+    {
+        h = list_entry(list, struct cx25821_dev, devlist);
+
+        if (h->video_dev[SRAM_CH05] && h->video_dev[SRAM_CH05]->minor == minor) {
+            dev  = h;
+            type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        }
+    }
+
+    if (NULL == dev) {
+        unlock_kernel();
+        return -ENODEV;
+    }
+
+    printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+    /* allocate + initialize per filehandle data */
+    fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+    if (NULL == fh) {
+        unlock_kernel();
+        return -ENOMEM;
+    }
+    file->private_data = fh;
+    fh->dev      = dev;
+    fh->type     = type;
+    fh->width    = 720;
+
+    if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+        fh->height = 576;
+    else
+        fh->height = 480;
+
+    dev->channel_opened = SRAM_CH05;
+    pix_format          = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+    fh->fmt             = format_by_fourcc(pix_format);
+
+    v4l2_prio_open(&dev->prio,&fh->prio);
+
+    videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+                &dev->pci->dev, &dev->slock,
+                V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                V4L2_FIELD_INTERLACED,
+                sizeof(struct cx25821_buffer),
+                fh);
+
+    dprintk(1, "post videobuf_queue_init()\n");
+    unlock_kernel();
+
+    return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+    struct cx25821_fh *fh = file->private_data;
+
+    switch (fh->type)
+    {
+        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+            if (res_locked(fh->dev, RESOURCE_VIDEO5))
+                return -EBUSY;
+
+            return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK);
+
+        default:
+            BUG();
+            return 0;
+    }
+}
+
+static unsigned int video_poll(struct file *file, struct poll_table_struct *wait)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_buffer *buf;
+
+    if (res_check(fh, RESOURCE_VIDEO5)) {
+        /* streaming capture */
+        if (list_empty(&fh->vidq.stream))
+            return POLLERR;
+        buf = list_entry(fh->vidq.stream.next,
+            struct cx25821_buffer, vb.stream);
+    } else {
+        /* read() capture */
+        buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+        if (NULL == buf)
+            return POLLERR;
+    }
+
+    poll_wait(file, &buf->vb.done, wait);
+    if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)
+    {        
+        if( buf->vb.state == VIDEOBUF_DONE )
+        {            
+            struct cx25821_dev *dev = fh->dev;
+            
+            if( dev && dev->use_cif_resolution[SRAM_CH05] )
+            {
+                u8 cam_id = *((char*)buf->vb.baddr+3); 
+                memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2));                      
+                *((char*)buf->vb.baddr+3) = cam_id;
+            }
+        }
+        
+        return POLLIN|POLLRDNORM;
+    }
+
+    return 0;
+}
+
+
+static int video_release(struct file *file)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev;
+
+    //stop the risc engine and fifo
+    cx_write(channel5->dma_ctl, 0); /* FIFO and RISC disable */
+
+    /* stop video capture */
+    if (res_check(fh, RESOURCE_VIDEO5)) {
+        videobuf_queue_cancel(&fh->vidq);
+        res_free(dev, fh, RESOURCE_VIDEO5);
+    }
+
+    if (fh->vidq.read_buf) {
+        buffer_release(&fh->vidq, fh->vidq.read_buf);
+        kfree(fh->vidq.read_buf);
+    }
+
+    videobuf_mmap_free(&fh->vidq);
+
+    v4l2_prio_close(&dev->prio,&fh->prio);
+    file->private_data = NULL;
+    kfree(fh);
+
+    return 0;
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+
+    if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(i != fh->type))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO5))))
+    {
+        return -EBUSY;
+    }
+
+    return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+    int err, res;
+
+    if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+        return -EINVAL;
+    if (i != fh->type)
+        return -EINVAL;
+
+    res = get_resource(fh, RESOURCE_VIDEO5);
+    err = videobuf_streamoff(get_queue(fh));
+    if (err < 0)
+        return err;
+    res_free(dev, fh, res);
+    return 0;
+}
+
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    int err;    
+    int pix_format = 0;
+   
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    dprintk(2, "%s()\n", __func__);
+    err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+    if (0 != err)
+        return err;
+
+    fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+    fh->vidq.field = f->fmt.pix.field;
+
+    // check if width and height is valid based on set standard
+    if (is_valid_width(f->fmt.pix.width, dev->tvnorm))
+    {
+        fh->width      = f->fmt.pix.width;
+    }
+
+    if (is_valid_height(f->fmt.pix.height, dev->tvnorm))
+    {
+        fh->height     = f->fmt.pix.height;
+    }
+
+    if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+        pix_format = PIXEL_FRMT_411;
+    else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+        pix_format = PIXEL_FRMT_422;
+    else
+        return -EINVAL;
+
+    cx25821_set_pixel_format( dev, SRAM_CH05, pix_format ); 
+    // check if cif resolution
+    if (fh->width == 320 || fh->width == 352)
+    {
+        dev->use_cif_resolution[SRAM_CH05] = 1;
+    }else
+    {
+       dev->use_cif_resolution[SRAM_CH05] = 0;
+    }
+    dev->cif_width[SRAM_CH05]          = fh->width;
+    medusa_set_resolution( dev, fh->width, SRAM_CH05 ); 
+
+    dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field);
+    cx25821_call_all(dev, video, s_fmt, f);
+
+    return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+    int ret_val = 0;
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+
+    ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); 
+
+    p->sequence = dev->vidq[SRAM_CH05].count;
+
+    return ret_val;
+}
+static int vidioc_log_status (struct file *file, void *priv)
+{
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    char name[32 + 2];
+
+    struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH05];  
+    u32 tmp = 0;
+
+    snprintf(name, sizeof(name), "%s/2", dev->name);
+    printk(KERN_INFO "%s/2: ============  START LOG STATUS  ============\n",
+              dev->name);
+    cx25821_call_all(dev, core, log_status);
+    
+    tmp = cx_read(sram_ch->dma_ctl);
+    printk(KERN_INFO "Video input 5 is %s\n", (tmp & 0x11)?"streaming" : "stopped");
+    printk(KERN_INFO "%s/2: =============  END LOG STATUS  =============\n",
+              dev->name);
+    return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+       struct cx25821_fh *fh = priv;
+        struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+        int err;
+
+        if (fh) {
+               err = v4l2_prio_check(&dev->prio, &fh->prio);
+               if (0 != err)
+                       return err;
+       }
+
+       return cx25821_set_control(dev, ctl, SRAM_CH05);
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+    .owner         = THIS_MODULE,
+    .open          = video_open,
+    .release       = video_release,
+    .read          = video_read,
+    .poll          = video_poll,
+    .mmap          = video_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_reqbufs       = vidioc_reqbufs,
+    .vidioc_querybuf      = vidioc_querybuf,
+    .vidioc_qbuf          = vidioc_qbuf,
+    .vidioc_dqbuf         = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+    .vidioc_s_std         = vidioc_s_std,
+    .vidioc_querystd      = vidioc_querystd,
+#endif
+    .vidioc_cropcap       = vidioc_cropcap,
+    .vidioc_s_crop        = vidioc_s_crop,
+    .vidioc_g_crop        = vidioc_g_crop,
+    .vidioc_enum_input    = vidioc_enum_input,
+    .vidioc_g_input       = vidioc_g_input,
+    .vidioc_s_input       = vidioc_s_input,
+    .vidioc_g_ctrl        = vidioc_g_ctrl,
+    .vidioc_s_ctrl        = vidioc_s_ctrl,
+    .vidioc_queryctrl    = vidioc_queryctrl,
+    .vidioc_streamon      = vidioc_streamon,
+    .vidioc_streamoff     = vidioc_streamoff,
+    .vidioc_log_status    = vidioc_log_status,
+    .vidioc_g_priority   = vidioc_g_priority,
+    .vidioc_s_priority   = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+    .vidiocgmbuf          = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+    .vidioc_g_tuner       = vidioc_g_tuner,
+    .vidioc_s_tuner       = vidioc_s_tuner,
+    .vidioc_g_frequency   = vidioc_g_frequency,
+    .vidioc_s_frequency   = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+    .vidioc_g_register    = vidioc_g_register,
+    .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template5 = {
+    .name                 = "cx25821-video",
+    .fops                 = &video_fops,
+    .minor                = -1,
+    .ioctl_ops            = &video_ioctl_ops,
+    .tvnorms              = CX25821_NORMS,
+    .current_norm         = V4L2_STD_NTSC_M,
+};
+
+
+
diff --git a/drivers/staging/cx25821/cx25821-video6.c b/drivers/staging/cx25821/cx25821-video6.c
new file mode 100644 (file)
index 0000000..980565a
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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 "cx25821-video.h"
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+    struct cx25821_buffer   *buf = container_of(vb, struct cx25821_buffer, vb);
+    struct cx25821_buffer   *prev;
+    struct cx25821_fh       *fh   = vq->priv_data;
+    struct cx25821_dev      *dev  = fh->dev;
+    struct cx25821_dmaqueue *q    = &dev->vidq[SRAM_CH06];
+
+    /* add jump to stopper */
+    buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+    buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+    buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+    dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+    if (!list_empty(&q->queued)) {
+        list_add_tail(&buf->vb.queue, &q->queued);
+        buf->vb.state = VIDEOBUF_QUEUED;
+        dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i);
+
+    } else if (list_empty(&q->active)) {
+        list_add_tail(&buf->vb.queue, &q->active);
+        cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH06]);
+        buf->vb.state = VIDEOBUF_ACTIVE;
+        buf->count    = q->count++;
+        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+        dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+                                buf, buf->vb. i, buf->count, q->count);
+    } else {
+        prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+        if (prev->vb.width  == buf->vb.width  &&
+            prev->vb.height == buf->vb.height &&
+            prev->fmt       == buf->fmt) {
+            list_add_tail(&buf->vb.queue, &q->active);
+            buf->vb.state = VIDEOBUF_ACTIVE;
+            buf->count    = q->count++;
+            prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+            /* 64 bit bits 63-32 */
+            prev->risc.jmp[2] = cpu_to_le32(0);
+            dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",  buf, buf->vb.i, buf->count);
+
+        } else {
+            list_add_tail(&buf->vb.queue, &q->queued);
+            buf->vb.state = VIDEOBUF_QUEUED;
+            dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i);
+        }
+    }
+
+    if (list_empty(&q->active))
+    {
+       dprintk(2, "active queue empty!\n");
+    }
+}
+
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+    .buf_setup    = buffer_setup,
+    .buf_prepare  = buffer_prepare,
+    .buf_queue    = buffer_queue,
+    .buf_release  = buffer_release,
+};
+
+
+static int video_open(struct file *file)
+{
+    int minor = video_devdata(file)->minor;
+    struct cx25821_dev *h, *dev = NULL;
+    struct cx25821_fh *fh;
+    struct list_head *list;
+    enum v4l2_buf_type type = 0;
+    u32 pix_format;
+
+    lock_kernel();
+    list_for_each(list, &cx25821_devlist)
+    {
+        h = list_entry(list, struct cx25821_dev, devlist);
+
+        if (h->video_dev[SRAM_CH06] && h->video_dev[SRAM_CH06]->minor == minor) {
+            dev  = h;
+            type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        }
+    }
+
+    if (NULL == dev) {
+        unlock_kernel();
+        return -ENODEV;
+    }
+
+    printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+    /* allocate + initialize per filehandle data */
+    fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+    if (NULL == fh) {
+        unlock_kernel();
+        return -ENOMEM;
+    }
+    file->private_data = fh;
+    fh->dev      = dev;
+    fh->type     = type;
+    fh->width    = 720;
+
+    if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+        fh->height = 576;
+    else
+        fh->height = 480;
+
+    dev->channel_opened = SRAM_CH06;
+    pix_format          = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+    fh->fmt             = format_by_fourcc(pix_format);
+
+    v4l2_prio_open(&dev->prio,&fh->prio);
+
+    videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+                &dev->pci->dev, &dev->slock,
+                V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                V4L2_FIELD_INTERLACED,
+                sizeof(struct cx25821_buffer),
+                fh);
+
+    dprintk(1, "post videobuf_queue_init()\n");
+    unlock_kernel();
+
+    return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+    struct cx25821_fh *fh = file->private_data;
+
+    switch (fh->type)
+    {
+        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+            if (res_locked(fh->dev, RESOURCE_VIDEO6))
+                return -EBUSY;
+
+            return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK);
+
+        default:
+            BUG();
+            return 0;
+    }
+}
+
+static unsigned int video_poll(struct file *file, struct poll_table_struct *wait)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_buffer *buf;
+
+    if (res_check(fh, RESOURCE_VIDEO6)) {
+        /* streaming capture */
+        if (list_empty(&fh->vidq.stream))
+            return POLLERR;
+        buf = list_entry(fh->vidq.stream.next,
+            struct cx25821_buffer, vb.stream);
+    } else {
+        /* read() capture */
+        buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+        if (NULL == buf)
+            return POLLERR;
+    }
+
+    poll_wait(file, &buf->vb.done, wait);
+    if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)
+    {        
+        if( buf->vb.state == VIDEOBUF_DONE )
+        {            
+            struct cx25821_dev *dev = fh->dev;
+            
+            if( dev && dev->use_cif_resolution[SRAM_CH06] )
+            {
+                u8 cam_id = *((char*)buf->vb.baddr+3); 
+                memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2));                      
+                *((char*)buf->vb.baddr+3) = cam_id;
+            }
+        }
+        
+        return POLLIN|POLLRDNORM;
+    }
+    
+    return 0;
+}
+
+
+static int video_release(struct file *file)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev;
+
+    //stop the risc engine and fifo
+    cx_write(channel6->dma_ctl, 0); /* FIFO and RISC disable */
+
+    /* stop video capture */
+    if (res_check(fh, RESOURCE_VIDEO6)) {
+        videobuf_queue_cancel(&fh->vidq);
+        res_free(dev, fh, RESOURCE_VIDEO6);
+    }
+    if (fh->vidq.read_buf) {
+        buffer_release(&fh->vidq, fh->vidq.read_buf);
+        kfree(fh->vidq.read_buf);
+    }
+
+    videobuf_mmap_free(&fh->vidq);
+
+    v4l2_prio_close(&dev->prio,&fh->prio);
+    file->private_data = NULL;
+    kfree(fh);
+
+    return 0;
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+
+    if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(i != fh->type))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO6))))
+    {
+        return -EBUSY;
+    }
+
+    return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+    int err, res;
+
+    if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+        return -EINVAL;
+    if (i != fh->type)
+        return -EINVAL;
+
+    res = get_resource(fh, RESOURCE_VIDEO6);
+    err = videobuf_streamoff(get_queue(fh));
+    if (err < 0)
+        return err;
+    res_free(dev, fh, res);
+    return 0;
+}
+
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    int err;    
+    int pix_format = 0;
+   
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    dprintk(2, "%s()\n", __func__);
+    err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+    if (0 != err)
+        return err;
+
+    fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+    fh->vidq.field = f->fmt.pix.field;
+
+    // check if width and height is valid based on set standard
+    if (is_valid_width(f->fmt.pix.width, dev->tvnorm))
+    {
+        fh->width      = f->fmt.pix.width;
+    }
+
+    if (is_valid_height(f->fmt.pix.height, dev->tvnorm))
+    {
+        fh->height     = f->fmt.pix.height;
+    }
+
+    if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+        pix_format = PIXEL_FRMT_411;
+    else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+        pix_format = PIXEL_FRMT_422;
+    else
+        return -EINVAL;
+
+    cx25821_set_pixel_format( dev, SRAM_CH06, pix_format ); 
+    // check if cif resolution
+    if (fh->width == 320 || fh->width == 352)
+    {
+        dev->use_cif_resolution[SRAM_CH06] = 1;
+    }else
+    {
+       dev->use_cif_resolution[SRAM_CH06] = 0;
+    }
+    dev->cif_width[SRAM_CH06]          = fh->width;
+    medusa_set_resolution( dev, fh->width, SRAM_CH06 ); 
+
+    dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field);
+    cx25821_call_all(dev, video, s_fmt, f);
+
+    return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+    int ret_val = 0;
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+
+    ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); 
+
+    p->sequence = dev->vidq[SRAM_CH06].count;
+
+    return ret_val;
+}
+
+static int vidioc_log_status (struct file *file, void *priv)
+{
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    char name[32 + 2];
+
+    struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH06];  
+    u32 tmp = 0;
+
+    snprintf(name, sizeof(name), "%s/2", dev->name);
+    printk(KERN_INFO "%s/2: ============  START LOG STATUS  ============\n",
+              dev->name);
+    cx25821_call_all(dev, core, log_status);
+    
+    tmp = cx_read(sram_ch->dma_ctl);
+    printk(KERN_INFO "Video input 6 is %s\n", (tmp & 0x11)?"streaming" : "stopped");
+    printk(KERN_INFO "%s/2: =============  END LOG STATUS  =============\n",
+              dev->name);
+    return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+       struct cx25821_fh *fh = priv;
+        struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+        int err;
+
+        if (fh) {
+               err = v4l2_prio_check(&dev->prio, &fh->prio);
+               if (0 != err)
+                       return err;
+       }
+
+       return cx25821_set_control(dev, ctl, SRAM_CH06);
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+    .owner         = THIS_MODULE,
+    .open          = video_open,
+    .release       = video_release,
+    .read          = video_read,
+    .poll          = video_poll,
+    .mmap          = video_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_reqbufs       = vidioc_reqbufs,
+    .vidioc_querybuf      = vidioc_querybuf,
+    .vidioc_qbuf          = vidioc_qbuf,
+    .vidioc_dqbuf         = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+    .vidioc_s_std         = vidioc_s_std,
+    .vidioc_querystd      = vidioc_querystd,
+#endif
+    .vidioc_cropcap       = vidioc_cropcap,
+    .vidioc_s_crop        = vidioc_s_crop,
+    .vidioc_g_crop        = vidioc_g_crop,
+    .vidioc_enum_input    = vidioc_enum_input,
+    .vidioc_g_input       = vidioc_g_input,
+    .vidioc_s_input       = vidioc_s_input,
+    .vidioc_g_ctrl        = vidioc_g_ctrl,
+    .vidioc_s_ctrl        = vidioc_s_ctrl,
+    .vidioc_queryctrl    = vidioc_queryctrl,
+    .vidioc_streamon      = vidioc_streamon,
+    .vidioc_streamoff     = vidioc_streamoff,
+    .vidioc_log_status    = vidioc_log_status,
+    .vidioc_g_priority   = vidioc_g_priority,
+    .vidioc_s_priority   = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+    .vidiocgmbuf          = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+    .vidioc_g_tuner       = vidioc_g_tuner,
+    .vidioc_s_tuner       = vidioc_s_tuner,
+    .vidioc_g_frequency   = vidioc_g_frequency,
+    .vidioc_s_frequency   = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+    .vidioc_g_register    = vidioc_g_register,
+    .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template6 = {
+    .name                 = "cx25821-video",
+    .fops                 = &video_fops,
+    .minor                = -1,
+    .ioctl_ops            = &video_ioctl_ops,
+    .tvnorms              = CX25821_NORMS,
+    .current_norm         = V4L2_STD_NTSC_M,
+};
+
+
+
diff --git a/drivers/staging/cx25821/cx25821-video7.c b/drivers/staging/cx25821/cx25821-video7.c
new file mode 100644 (file)
index 0000000..966e369
--- /dev/null
@@ -0,0 +1,454 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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 "cx25821-video.h"
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+    struct cx25821_buffer   *buf = container_of(vb, struct cx25821_buffer, vb);
+    struct cx25821_buffer   *prev;
+    struct cx25821_fh       *fh   = vq->priv_data;
+    struct cx25821_dev      *dev  = fh->dev;
+    struct cx25821_dmaqueue *q    = &dev->vidq[SRAM_CH07];
+
+    /* add jump to stopper */
+    buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+    buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+    buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+        dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+    if (!list_empty(&q->queued)) {
+        list_add_tail(&buf->vb.queue, &q->queued);
+        buf->vb.state = VIDEOBUF_QUEUED;
+        dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i);
+
+    } else if (list_empty(&q->active)) {
+        list_add_tail(&buf->vb.queue, &q->active);
+        cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH07]);
+        buf->vb.state = VIDEOBUF_ACTIVE;
+        buf->count    = q->count++;
+        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+        dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+                                buf, buf->vb. i, buf->count, q->count);
+    } else {
+        prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+        if (prev->vb.width  == buf->vb.width  &&
+            prev->vb.height == buf->vb.height &&
+            prev->fmt       == buf->fmt) {
+            list_add_tail(&buf->vb.queue, &q->active);
+            buf->vb.state = VIDEOBUF_ACTIVE;
+            buf->count    = q->count++;
+            prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+            /* 64 bit bits 63-32 */
+            prev->risc.jmp[2] = cpu_to_le32(0);
+            dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",  buf, buf->vb.i, buf->count);
+
+        } else {
+            list_add_tail(&buf->vb.queue, &q->queued);
+            buf->vb.state = VIDEOBUF_QUEUED;
+            dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i);
+        }
+    }
+
+    if (list_empty(&q->active))
+    {
+       dprintk(2, "active queue empty!\n");
+    }
+}
+
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+    .buf_setup    = buffer_setup,
+    .buf_prepare  = buffer_prepare,
+    .buf_queue    = buffer_queue,
+    .buf_release  = buffer_release,
+};
+
+
+static int video_open(struct file *file)
+{
+    int minor = video_devdata(file)->minor;
+    struct cx25821_dev *h, *dev = NULL;
+    struct cx25821_fh *fh;
+    struct list_head *list;
+    enum v4l2_buf_type type = 0;
+    u32 pix_format;
+
+    lock_kernel();
+    list_for_each(list, &cx25821_devlist)
+    {
+        h = list_entry(list, struct cx25821_dev, devlist);
+
+        if (h->video_dev[SRAM_CH07] && h->video_dev[SRAM_CH07]->minor == minor) {
+            dev  = h;
+            type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        }
+    }
+
+    if (NULL == dev) {
+        unlock_kernel();
+        return -ENODEV;
+    }
+
+    printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+    /* allocate + initialize per filehandle data */
+    fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+    if (NULL == fh) {
+        unlock_kernel();
+        return -ENOMEM;
+    }
+    file->private_data = fh;
+    fh->dev      = dev;
+    fh->type     = type;
+    fh->width    = 720;
+
+    if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+        fh->height = 576;
+    else
+        fh->height = 480;
+
+    dev->channel_opened = SRAM_CH07;        
+    pix_format          = (dev->pixel_formats[dev->channel_opened] == PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
+    fh->fmt             = format_by_fourcc(pix_format);
+
+    v4l2_prio_open(&dev->prio,&fh->prio);
+
+    videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+                &dev->pci->dev, &dev->slock,
+                V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                V4L2_FIELD_INTERLACED,
+                sizeof(struct cx25821_buffer),
+                fh);
+
+    dprintk(1, "post videobuf_queue_init()\n");
+    unlock_kernel();
+
+    return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+    struct cx25821_fh *fh = file->private_data;
+
+    switch (fh->type)
+    {
+        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+            if (res_locked(fh->dev, RESOURCE_VIDEO7))
+                return -EBUSY;
+
+            return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK);
+
+        default:
+            BUG();
+            return 0;
+    }
+}
+
+static unsigned int video_poll(struct file *file, struct poll_table_struct *wait)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_buffer *buf;
+
+    if (res_check(fh, RESOURCE_VIDEO7)) {
+        /* streaming capture */
+        if (list_empty(&fh->vidq.stream))
+            return POLLERR;
+        buf = list_entry(fh->vidq.stream.next,
+            struct cx25821_buffer, vb.stream);
+    } else {
+        /* read() capture */
+        buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+        if (NULL == buf)
+            return POLLERR;
+    }
+
+    poll_wait(file, &buf->vb.done, wait);
+    if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)
+    {
+        if( buf->vb.state == VIDEOBUF_DONE )
+        {            
+            struct cx25821_dev *dev = fh->dev;
+            
+            if( dev && dev->use_cif_resolution[SRAM_CH07] )
+            {
+                u8 cam_id = *((char*)buf->vb.baddr+3); 
+                memcpy((char*)buf->vb.baddr, (char*)buf->vb.baddr + (fh->width * 2), (fh->width * 2));                      
+                *((char*)buf->vb.baddr+3) = cam_id;
+            }
+        }
+        
+        return POLLIN|POLLRDNORM;
+    }
+
+    return 0;
+}
+
+
+static int video_release(struct file *file)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev;
+
+    //stop the risc engine and fifo
+    cx_write(channel7->dma_ctl, 0); /* FIFO and RISC disable */
+
+    /* stop video capture */
+    if (res_check(fh, RESOURCE_VIDEO7)) {
+        videobuf_queue_cancel(&fh->vidq);
+        res_free(dev, fh, RESOURCE_VIDEO7);
+    }
+
+    if (fh->vidq.read_buf) {
+        buffer_release(&fh->vidq, fh->vidq.read_buf);
+        kfree(fh->vidq.read_buf);
+    }
+
+    videobuf_mmap_free(&fh->vidq);
+
+    v4l2_prio_close(&dev->prio,&fh->prio);
+    file->private_data = NULL;
+    kfree(fh);
+
+    return 0;
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+
+    if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(i != fh->type))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO7))))
+    {
+        return -EBUSY;
+    }
+
+    return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+    int err, res;
+
+    if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+        return -EINVAL;
+    if (i != fh->type)
+        return -EINVAL;
+
+    res = get_resource(fh, RESOURCE_VIDEO7);
+    err = videobuf_streamoff(get_queue(fh));
+    if (err < 0)
+        return err;
+    res_free(dev, fh, res);
+    return 0;
+}
+
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    int err;    
+    int pix_format = 0;
+   
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+           return err;
+    }
+
+    dprintk(2, "%s()\n", __func__);
+    err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+    if (0 != err)
+        return err;
+
+    fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+    fh->vidq.field = f->fmt.pix.field;
+
+    // check if width and height is valid based on set standard
+    if (is_valid_width(f->fmt.pix.width, dev->tvnorm))
+    {
+        fh->width      = f->fmt.pix.width;
+    }
+
+    if (is_valid_height(f->fmt.pix.height, dev->tvnorm))
+    {
+        fh->height     = f->fmt.pix.height;
+    }
+
+    if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+        pix_format = PIXEL_FRMT_411;
+    else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+        pix_format = PIXEL_FRMT_422;
+    else
+        return -EINVAL;
+
+    cx25821_set_pixel_format( dev, SRAM_CH07, pix_format ); 
+    // check if cif resolution
+    if (fh->width == 320 || fh->width == 352)
+    {
+        dev->use_cif_resolution[SRAM_CH07] = 1;
+    }else
+    {
+       dev->use_cif_resolution[SRAM_CH07] = 0;
+    }
+    dev->cif_width[SRAM_CH07]          = fh->width;
+    medusa_set_resolution( dev, fh->width, SRAM_CH07 ); 
+
+    dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field);
+    cx25821_call_all(dev, video, s_fmt, f);
+
+    return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+    int ret_val = 0;
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+
+    ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); 
+
+    p->sequence = dev->vidq[SRAM_CH07].count;
+
+    return ret_val;
+}
+static int vidioc_log_status (struct file *file, void *priv)
+{
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    char name[32 + 2];
+
+    struct sram_channel *sram_ch = &dev->sram_channels[SRAM_CH07];  
+    u32 tmp = 0;
+
+    snprintf(name, sizeof(name), "%s/2", dev->name);
+    printk(KERN_INFO "%s/2: ============  START LOG STATUS  ============\n",
+              dev->name);
+    cx25821_call_all(dev, core, log_status);
+    
+    tmp = cx_read(sram_ch->dma_ctl);
+    printk(KERN_INFO "Video input 7 is %s\n", (tmp & 0x11)?"streaming" : "stopped");
+    printk(KERN_INFO "%s/2: =============  END LOG STATUS  =============\n",
+              dev->name);
+    return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+       struct cx25821_fh *fh = priv;
+        struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+        int err;
+
+        if (fh) {
+               err = v4l2_prio_check(&dev->prio, &fh->prio);
+               if (0 != err)
+                       return err;
+       }
+
+       return cx25821_set_control(dev, ctl, SRAM_CH07);
+}
+
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+    .owner         = THIS_MODULE,
+    .open          = video_open,
+    .release       = video_release,
+    .read          = video_read,
+    .poll          = video_poll,
+    .mmap          = video_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_reqbufs       = vidioc_reqbufs,
+    .vidioc_querybuf      = vidioc_querybuf,
+    .vidioc_qbuf          = vidioc_qbuf,
+    .vidioc_dqbuf         = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+    .vidioc_s_std         = vidioc_s_std,
+    .vidioc_querystd      = vidioc_querystd,
+#endif
+    .vidioc_cropcap       = vidioc_cropcap,
+    .vidioc_s_crop        = vidioc_s_crop,
+    .vidioc_g_crop        = vidioc_g_crop,
+    .vidioc_enum_input    = vidioc_enum_input,
+    .vidioc_g_input       = vidioc_g_input,
+    .vidioc_s_input       = vidioc_s_input,
+    .vidioc_g_ctrl        = vidioc_g_ctrl,
+    .vidioc_s_ctrl        = vidioc_s_ctrl,
+    .vidioc_queryctrl    = vidioc_queryctrl,
+    .vidioc_streamon      = vidioc_streamon,
+    .vidioc_streamoff     = vidioc_streamoff,
+    .vidioc_log_status    = vidioc_log_status,
+    .vidioc_g_priority   = vidioc_g_priority,
+    .vidioc_s_priority   = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+    .vidiocgmbuf          = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+    .vidioc_g_tuner       = vidioc_g_tuner,
+    .vidioc_s_tuner       = vidioc_s_tuner,
+    .vidioc_g_frequency   = vidioc_g_frequency,
+    .vidioc_s_frequency   = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+    .vidioc_g_register    = vidioc_g_register,
+    .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template7 = {
+    .name                 = "cx25821-video",
+    .fops                 = &video_fops,
+    .minor                = -1,
+    .ioctl_ops            = &video_ioctl_ops,
+    .tvnorms              = CX25821_NORMS,
+    .current_norm         = V4L2_STD_NTSC_M,
+};
+
+
+
diff --git a/drivers/staging/cx25821/cx25821-videoioctl.c b/drivers/staging/cx25821/cx25821-videoioctl.c
new file mode 100644 (file)
index 0000000..a5363e4
--- /dev/null
@@ -0,0 +1,500 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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 "cx25821-video.h"
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+    struct cx25821_buffer   *buf = container_of(vb, struct cx25821_buffer, vb);
+    struct cx25821_buffer   *prev;
+    struct cx25821_fh       *fh   = vq->priv_data;
+    struct cx25821_dev      *dev  = fh->dev;
+    struct cx25821_dmaqueue *q    = &dev->vidq[VIDEO_IOCTL_CH];
+
+    /* add jump to stopper */
+    buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+    buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+    buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+    dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+    if (!list_empty(&q->queued)) {
+        list_add_tail(&buf->vb.queue, &q->queued);
+        buf->vb.state = VIDEOBUF_QUEUED;
+        dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i);
+
+    } else if (list_empty(&q->active)) {
+        list_add_tail(&buf->vb.queue, &q->active);
+        cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[VIDEO_IOCTL_CH]);
+        buf->vb.state = VIDEOBUF_ACTIVE;
+        buf->count    = q->count++;
+        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+        dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+                                buf, buf->vb. i, buf->count, q->count);
+    } else {
+        prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+        if (prev->vb.width  == buf->vb.width  &&
+            prev->vb.height == buf->vb.height &&
+            prev->fmt       == buf->fmt) {
+            list_add_tail(&buf->vb.queue, &q->active);
+            buf->vb.state = VIDEOBUF_ACTIVE;
+            buf->count    = q->count++;
+            prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+            /* 64 bit bits 63-32 */
+            prev->risc.jmp[2] = cpu_to_le32(0);
+            dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",  buf, buf->vb.i, buf->count);
+
+        } else {
+            list_add_tail(&buf->vb.queue, &q->queued);
+            buf->vb.state = VIDEOBUF_QUEUED;
+            dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i);
+        }
+    }
+
+    if (list_empty(&q->active))
+    {
+       dprintk(2, "active queue empty!\n");
+    }
+}
+
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+    .buf_setup    = buffer_setup,
+    .buf_prepare  = buffer_prepare,
+    .buf_queue    = buffer_queue,
+    .buf_release  = buffer_release,
+};
+
+
+static int video_open(struct file *file)
+{
+    int minor = video_devdata(file)->minor;
+    struct cx25821_dev *h, *dev = NULL;
+    struct cx25821_fh *fh;
+    struct list_head *list;
+    enum v4l2_buf_type type = 0;
+    u32 pix_format;
+
+    lock_kernel();
+    list_for_each(list, &cx25821_devlist)
+    {
+        h = list_entry(list, struct cx25821_dev, devlist);
+
+        if (h->ioctl_dev && h->ioctl_dev->minor == minor)
+        {
+            dev  = h;
+            type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        }
+    }
+
+    if (NULL == dev) {
+        unlock_kernel();
+        return -ENODEV;
+    }
+
+    printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+    /* allocate + initialize per filehandle data */
+    fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+    if (NULL == fh) {
+        unlock_kernel();
+        return -ENOMEM;
+    }
+
+    file->private_data = fh;
+    fh->dev      = dev;
+    fh->type     = type;
+    fh->width    = 720;
+
+    if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+        fh->height = 576;
+    else
+        fh->height = 480;
+
+    dev->channel_opened = VIDEO_IOCTL_CH;
+    pix_format          = V4L2_PIX_FMT_YUYV;
+    fh->fmt             = format_by_fourcc(pix_format);
+    
+    v4l2_prio_open(&dev->prio,&fh->prio);
+
+    videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+                &dev->pci->dev, &dev->slock,
+                V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                V4L2_FIELD_INTERLACED,
+                sizeof(struct cx25821_buffer),
+                fh);
+
+    dprintk(1, "post videobuf_queue_init()\n");
+    unlock_kernel();
+
+    return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+    struct cx25821_fh *fh = file->private_data;
+
+    switch (fh->type)
+    {
+        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+            if (res_locked(fh->dev, RESOURCE_VIDEO_IOCTL))
+                return -EBUSY;
+
+            return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK);
+
+        default:
+            BUG();
+            return 0;
+    }
+}
+
+static unsigned int video_poll(struct file *file, struct poll_table_struct *wait)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_buffer *buf;
+
+    if (res_check(fh, RESOURCE_VIDEO_IOCTL)) {
+        /* streaming capture */
+        if (list_empty(&fh->vidq.stream))
+            return POLLERR;
+        buf = list_entry(fh->vidq.stream.next,
+            struct cx25821_buffer, vb.stream);
+    } else {
+        /* read() capture */
+        buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+        if (NULL == buf)
+            return POLLERR;
+    }
+
+    poll_wait(file, &buf->vb.done, wait);
+    if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)       
+        return POLLIN|POLLRDNORM;
+    
+    return 0;
+}
+
+
+static int video_release(struct file *file)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev; 
+
+    /* stop video capture */
+    if (res_check(fh, RESOURCE_VIDEO_IOCTL)) {
+        videobuf_queue_cancel(&fh->vidq);
+        res_free(dev, fh, RESOURCE_VIDEO_IOCTL);
+    }
+
+    if (fh->vidq.read_buf) {
+        buffer_release(&fh->vidq, fh->vidq.read_buf);
+        kfree(fh->vidq.read_buf);
+    }
+
+    videobuf_mmap_free(&fh->vidq);
+
+    v4l2_prio_close(&dev->prio,&fh->prio);
+
+    file->private_data = NULL;
+    kfree(fh);
+
+    return 0;
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+
+    if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(i != fh->type))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO_IOCTL))))
+    {
+        return -EBUSY;
+    }
+
+    return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+    int err, res;
+
+    if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+        return -EINVAL;
+    if (i != fh->type)
+        return -EINVAL;
+
+    res = get_resource(fh, RESOURCE_VIDEO_IOCTL);
+    err = videobuf_streamoff(get_queue(fh));
+    if (err < 0)
+        return err;
+    res_free(dev, fh, res);
+    return 0;
+}
+
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    int err;
+
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    dprintk(2, "%s()\n", __func__);
+    err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+    if (0 != err)
+        return err;
+    fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+    fh->width      = f->fmt.pix.width;
+    fh->height     = f->fmt.pix.height;
+    fh->vidq.field = f->fmt.pix.field;
+    dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field);
+    cx25821_call_all(dev, video, s_fmt, f);
+    return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+    struct cx25821_fh *fh = priv;
+    return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+}
+
+static long video_ioctl_set(struct file *file, unsigned int cmd, unsigned long arg)   
+{   
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev;
+    struct downstream_user_struct *data_from_user;
+    int command;
+    int width = 720;
+    int selected_channel = 0, pix_format = 0, i = 0;
+    int cif_enable = 0, cif_width = 0;
+    u32 value = 0;
+
+    
+    data_from_user = (struct downstream_user_struct *)arg;
+    
+    if( !data_from_user )
+    {
+        printk("cx25821 in %s(): User data is INVALID. Returning.\n", __func__);
+        return 0;
+    }
+    
+    command = data_from_user->command;
+    
+    if( command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT && command != ENABLE_CIF_RESOLUTION  && 
+        command != REG_READ && command != REG_WRITE && command != MEDUSA_READ && command != MEDUSA_WRITE)
+    {
+        return 0;
+    }
+                         
+                         
+    switch(command)
+    {             
+        case SET_VIDEO_STD:    
+            dev->tvnorm = !strcmp(data_from_user->vid_stdname,"PAL") ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;          
+            medusa_set_videostandard(dev);
+            break; 
+            
+        case SET_PIXEL_FORMAT:       
+            selected_channel    = data_from_user->decoder_select;  
+            pix_format          = data_from_user->pixel_format;
+
+            if( !(selected_channel <= 7 && selected_channel >= 0) )
+            {              
+                selected_channel -= 4;
+                selected_channel = selected_channel % 8;
+            }   
+            
+            if( selected_channel >= 0 )
+                cx25821_set_pixel_format( dev, selected_channel, pix_format ); 
+                           
+            break;
+            
+        case ENABLE_CIF_RESOLUTION:    
+            selected_channel    = data_from_user->decoder_select;
+            cif_enable          = data_from_user->cif_resolution_enable;
+            cif_width           = data_from_user->cif_width;            
+            
+            if( cif_enable )
+            {
+                if( dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK )
+                    width = 352;
+                else
+                    width = (cif_width == 320 || cif_width == 352) ? cif_width : 320;
+            }
+            
+            if( !(selected_channel <= 7 && selected_channel >= 0) )
+            {
+                selected_channel -= 4;
+                selected_channel = selected_channel % 8;   
+            }
+            
+            
+            if( selected_channel <= 7 && selected_channel >= 0 )
+            {
+                dev->use_cif_resolution[selected_channel] = cif_enable;
+                dev->cif_width[selected_channel]          = width;   
+            }        
+            else
+            {
+                for( i=0; i < VID_CHANNEL_NUM; i++ )
+                {
+                    dev->use_cif_resolution[i] = cif_enable;
+                    dev->cif_width[i]          = width;     
+                }
+            }         
+
+            medusa_set_resolution( dev, width, selected_channel );        
+            break;
+        case REG_READ:
+                data_from_user->reg_data = cx_read(data_from_user->reg_address);
+            break;
+        case REG_WRITE:
+                cx_write(data_from_user->reg_address, data_from_user->reg_data);
+            break;
+        case MEDUSA_READ:
+                value = cx25821_i2c_read(&dev->i2c_bus[0], (u16)data_from_user->reg_address, &data_from_user->reg_data);
+            break;
+        case MEDUSA_WRITE:
+                cx25821_i2c_write(&dev->i2c_bus[0], (u16)data_from_user->reg_address, data_from_user->reg_data);
+            break;
+    }
+       
+    return 0;
+}
+
+static int vidioc_log_status (struct file *file, void *priv)
+{
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    char name[32 + 2];
+
+    snprintf(name, sizeof(name), "%s/2", dev->name);
+    printk(KERN_INFO "%s/2: ============  START LOG STATUS  ============\n",
+              dev->name);
+    cx25821_call_all(dev, core, log_status);
+    printk(KERN_INFO "%s/2: =============  END LOG STATUS  =============\n",
+              dev->name);
+    return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    int err;
+    
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+       return 0;
+}
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+    .owner         = THIS_MODULE,
+    .open          = video_open,
+    .release       = video_release,
+    .read          = video_read,
+    .poll          = video_poll,
+    .mmap          = video_mmap,
+    .ioctl         = video_ioctl_set,
+};
+
+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_reqbufs       = vidioc_reqbufs,
+    .vidioc_querybuf      = vidioc_querybuf,
+    .vidioc_qbuf          = vidioc_qbuf,
+    .vidioc_dqbuf         = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+    .vidioc_s_std         = vidioc_s_std,
+    .vidioc_querystd      = vidioc_querystd,
+#endif
+    .vidioc_cropcap       = vidioc_cropcap,
+    .vidioc_s_crop        = vidioc_s_crop,
+    .vidioc_g_crop        = vidioc_g_crop,
+    .vidioc_enum_input    = vidioc_enum_input,
+    .vidioc_g_input       = vidioc_g_input,
+    .vidioc_s_input       = vidioc_s_input,
+    .vidioc_g_ctrl        = vidioc_g_ctrl,
+    .vidioc_s_ctrl        = vidioc_s_ctrl,
+    .vidioc_queryctrl    = vidioc_queryctrl,
+    .vidioc_streamon      = vidioc_streamon,
+    .vidioc_streamoff     = vidioc_streamoff,
+    .vidioc_log_status    = vidioc_log_status,
+    .vidioc_g_priority   = vidioc_g_priority,
+    .vidioc_s_priority   = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+    .vidiocgmbuf          = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+    .vidioc_g_tuner       = vidioc_g_tuner,
+    .vidioc_s_tuner       = vidioc_s_tuner,
+    .vidioc_g_frequency   = vidioc_g_frequency,
+    .vidioc_s_frequency   = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+    .vidioc_g_register    = vidioc_g_register,
+    .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_videoioctl_template = {
+    .name                 = "cx25821-videoioctl",
+    .fops                 = &video_fops,
+    .minor                = -1,
+    .ioctl_ops            = &video_ioctl_ops,
+    .tvnorms              = CX25821_NORMS,
+    .current_norm         = V4L2_STD_NTSC_M,
+};
+
+
+
diff --git a/drivers/staging/cx25821/cx25821-vidups10.c b/drivers/staging/cx25821/cx25821-vidups10.c
new file mode 100644 (file)
index 0000000..4738e91
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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 "cx25821-video.h"
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+    struct cx25821_buffer   *buf = container_of(vb, struct cx25821_buffer, vb);
+    struct cx25821_buffer   *prev;
+    struct cx25821_fh       *fh   = vq->priv_data;
+    struct cx25821_dev      *dev  = fh->dev;
+    struct cx25821_dmaqueue *q    = &dev->vidq[SRAM_CH10];
+
+
+    /* add jump to stopper */
+    buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+    buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+    buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+    dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+    if (!list_empty(&q->queued)) {
+        list_add_tail(&buf->vb.queue, &q->queued);
+        buf->vb.state = VIDEOBUF_QUEUED;
+        dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i);
+
+    } else if (list_empty(&q->active)) {
+        list_add_tail(&buf->vb.queue, &q->active);
+        cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH10]);
+        buf->vb.state = VIDEOBUF_ACTIVE;
+        buf->count    = q->count++;
+        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+        dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+                                buf, buf->vb. i, buf->count, q->count);
+    } else {
+        prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+        if (prev->vb.width  == buf->vb.width  &&
+            prev->vb.height == buf->vb.height &&
+            prev->fmt       == buf->fmt) {
+            list_add_tail(&buf->vb.queue, &q->active);
+            buf->vb.state = VIDEOBUF_ACTIVE;
+            buf->count    = q->count++;
+            prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+            /* 64 bit bits 63-32 */
+            prev->risc.jmp[2] = cpu_to_le32(0);
+            dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",  buf, buf->vb.i, buf->count);
+
+        } else {
+            list_add_tail(&buf->vb.queue, &q->queued);
+            buf->vb.state = VIDEOBUF_QUEUED;
+            dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i);
+        }
+    }
+
+    if (list_empty(&q->active))
+    {
+       dprintk(2, "active queue empty!\n");
+    }
+}
+
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+    .buf_setup    = buffer_setup,
+    .buf_prepare  = buffer_prepare,
+    .buf_queue    = buffer_queue,
+    .buf_release  = buffer_release,
+};
+
+
+static int video_open(struct file *file)
+{
+    int minor = video_devdata(file)->minor;
+    struct cx25821_dev *h, *dev = NULL;
+    struct cx25821_fh *fh;
+    struct list_head *list;
+    enum v4l2_buf_type type = 0;
+
+    lock_kernel();
+    list_for_each(list, &cx25821_devlist)
+    {
+        h = list_entry(list, struct cx25821_dev, devlist);
+
+        if (h->video_dev[SRAM_CH10] && h->video_dev[SRAM_CH10]->minor == minor) {
+            dev  = h;
+            type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        }
+    }
+
+    if (NULL == dev) {
+        unlock_kernel();
+        return -ENODEV;
+    }
+
+    printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+    /* allocate + initialize per filehandle data */
+    fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+    if (NULL == fh) {
+        unlock_kernel();
+        return -ENOMEM;
+    }
+
+    file->private_data = fh;
+    fh->dev      = dev;
+    fh->type     = type;
+    fh->width    = 720;
+
+    if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+        fh->height = 576;
+    else
+        fh->height = 480;
+
+    
+    dev->channel_opened = 9;
+    fh->fmt             = format_by_fourcc(V4L2_PIX_FMT_YUYV);
+
+    v4l2_prio_open(&dev->prio,&fh->prio);
+
+    videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+                &dev->pci->dev, &dev->slock,
+                V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                V4L2_FIELD_INTERLACED,
+                sizeof(struct cx25821_buffer),
+                fh);
+
+    dprintk(1, "post videobuf_queue_init()\n");
+    unlock_kernel();
+
+    return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+    struct cx25821_fh *fh = file->private_data;
+
+    switch (fh->type)
+    {
+        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+            if (res_locked(fh->dev, RESOURCE_VIDEO10))
+                return -EBUSY;
+
+            return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK);
+
+        default:
+            BUG();
+            return 0;
+    }
+}
+
+static unsigned int video_poll(struct file *file, struct poll_table_struct *wait)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_buffer *buf;
+
+    if (res_check(fh, RESOURCE_VIDEO10)) {
+        /* streaming capture */
+        if (list_empty(&fh->vidq.stream))
+            return POLLERR;
+        buf = list_entry(fh->vidq.stream.next,
+            struct cx25821_buffer, vb.stream);
+    } else {
+        /* read() capture */
+        buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+        if (NULL == buf)
+            return POLLERR;
+    }
+
+    poll_wait(file, &buf->vb.done, wait);
+    if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)
+        return POLLIN|POLLRDNORM;
+    return 0;
+}
+
+static int video_release(struct file *file)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev;
+
+    //stop the risc engine and fifo
+    //cx_write(channel10->dma_ctl, 0);  
+
+    /* stop video capture */
+    if (res_check(fh, RESOURCE_VIDEO10)) {
+        videobuf_queue_cancel(&fh->vidq);
+        res_free(dev, fh, RESOURCE_VIDEO10);
+    }
+
+    if (fh->vidq.read_buf) {
+        buffer_release(&fh->vidq, fh->vidq.read_buf);
+        kfree(fh->vidq.read_buf);
+    }
+
+    videobuf_mmap_free(&fh->vidq);
+
+    v4l2_prio_close(&dev->prio,&fh->prio);
+
+    file->private_data = NULL;
+    kfree(fh);
+
+    return 0;
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+
+    if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(i != fh->type))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO10))))
+    {
+        return -EBUSY;
+    }
+
+    return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+    int err, res;
+
+    if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+        return -EINVAL;
+    if (i != fh->type)
+        return -EINVAL;
+
+    res = get_resource(fh, RESOURCE_VIDEO10);
+    err = videobuf_streamoff(get_queue(fh));
+    if (err < 0)
+        return err;
+    res_free(dev, fh, res);
+    return 0;
+}
+
+
+static long video_ioctl_upstream10(struct file *file, unsigned int cmd, unsigned long arg) 
+{   
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev;
+    int command = 0;
+    struct upstream_user_struct *data_from_user;
+     
+
+    data_from_user = (struct upstream_user_struct *)arg;    
+    
+    if( !data_from_user )
+    {
+        printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__);
+        return 0;
+    }
+            
+    command = data_from_user->command;
+    
+    if( command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO )
+    {
+        return 0;
+    }
+    
+    dev->input_filename_ch2     = data_from_user->input_filename;
+    dev->input_audiofilename    = data_from_user->input_filename;
+    dev->vid_stdname_ch2        = data_from_user->vid_stdname;
+    dev->pixel_format_ch2       = data_from_user->pixel_format;
+    dev->channel_select_ch2     = data_from_user->channel_select;
+    dev->command_ch2            = data_from_user->command;
+    
+    
+    switch(command)
+    {   
+        case UPSTREAM_START_VIDEO:
+            cx25821_start_upstream_video_ch2(dev, data_from_user);
+            break;
+
+        case UPSTREAM_STOP_VIDEO:   
+            cx25821_stop_upstream_video_ch2(dev);
+            break;            
+    }
+       
+    return 0;
+}
+
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    int err;
+
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    dprintk(2, "%s()\n", __func__);
+    err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+    if (0 != err)
+        return err;
+    fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+    fh->width      = f->fmt.pix.width;
+    fh->height     = f->fmt.pix.height;
+    fh->vidq.field = f->fmt.pix.field;
+    dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field);
+    cx25821_call_all(dev, video, s_fmt, f);
+    return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+    struct cx25821_fh *fh = priv;
+    return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_log_status (struct file *file, void *priv)
+{
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    char name[32 + 2];
+
+    snprintf(name, sizeof(name), "%s/2", dev->name);
+    printk(KERN_INFO "%s/2: ============  START LOG STATUS  ============\n",
+              dev->name);
+    cx25821_call_all(dev, core, log_status);
+    printk(KERN_INFO "%s/2: =============  END LOG STATUS  =============\n",
+              dev->name);
+    return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    int err;
+
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    return 0;
+}
+
+//exported stuff
+static const struct v4l2_file_operations video_fops = {
+    .owner         = THIS_MODULE,
+    .open          = video_open,
+    .release       = video_release,
+    .read          = video_read,
+    .poll          = video_poll,
+    .mmap          = video_mmap,
+    .ioctl         = video_ioctl_upstream10, 
+};
+
+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_reqbufs       = vidioc_reqbufs,
+    .vidioc_querybuf      = vidioc_querybuf,
+    .vidioc_qbuf          = vidioc_qbuf,
+    .vidioc_dqbuf         = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+    .vidioc_s_std         = vidioc_s_std,
+    .vidioc_querystd      = vidioc_querystd,
+#endif
+    .vidioc_cropcap       = vidioc_cropcap,
+    .vidioc_s_crop        = vidioc_s_crop,
+    .vidioc_g_crop        = vidioc_g_crop,
+    .vidioc_enum_input    = vidioc_enum_input,
+    .vidioc_g_input       = vidioc_g_input,
+    .vidioc_s_input       = vidioc_s_input,
+    .vidioc_g_ctrl        = vidioc_g_ctrl,
+    .vidioc_s_ctrl        = vidioc_s_ctrl,
+    .vidioc_queryctrl    = vidioc_queryctrl,
+    .vidioc_streamon      = vidioc_streamon,
+    .vidioc_streamoff     = vidioc_streamoff,
+    .vidioc_log_status    = vidioc_log_status,
+    .vidioc_g_priority   = vidioc_g_priority,
+    .vidioc_s_priority   = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+    .vidiocgmbuf          = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+    .vidioc_g_tuner       = vidioc_g_tuner,
+    .vidioc_s_tuner       = vidioc_s_tuner,
+    .vidioc_g_frequency   = vidioc_g_frequency,
+    .vidioc_s_frequency   = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+    .vidioc_g_register    = vidioc_g_register,
+    .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template10 = {
+    .name                 = "cx25821-upstream10",
+    .fops                 = &video_fops,
+    .minor                = -1,
+    .ioctl_ops            = &video_ioctl_ops,
+    .tvnorms              = CX25821_NORMS,
+    .current_norm         = V4L2_STD_NTSC_M,
+};
+
+
+
diff --git a/drivers/staging/cx25821/cx25821-vidups9.c b/drivers/staging/cx25821/cx25821-vidups9.c
new file mode 100644 (file)
index 0000000..7832fd1
--- /dev/null
@@ -0,0 +1,441 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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 "cx25821-video.h"
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+    struct cx25821_buffer   *buf = container_of(vb, struct cx25821_buffer, vb);
+    struct cx25821_buffer   *prev;
+    struct cx25821_fh       *fh   = vq->priv_data;
+    struct cx25821_dev      *dev  = fh->dev;
+    struct cx25821_dmaqueue *q    = &dev->vidq[SRAM_CH09];
+
+    /* add jump to stopper */
+    buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+    buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+    buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+    dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+    if (!list_empty(&q->queued)) {
+        list_add_tail(&buf->vb.queue, &q->queued);
+        buf->vb.state = VIDEOBUF_QUEUED;
+        dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, buf->vb.i);
+
+    } else if (list_empty(&q->active)) {
+        list_add_tail(&buf->vb.queue, &q->active);
+        cx25821_start_video_dma(dev, q, buf, &dev->sram_channels[SRAM_CH09]);
+        buf->vb.state = VIDEOBUF_ACTIVE;
+        buf->count    = q->count++;
+        mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+        dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+                                buf, buf->vb. i, buf->count, q->count);
+    } else {
+        prev = list_entry(q->active.prev, struct cx25821_buffer, vb.queue);
+        if (prev->vb.width  == buf->vb.width  &&
+            prev->vb.height == buf->vb.height &&
+            prev->fmt       == buf->fmt) {
+            list_add_tail(&buf->vb.queue, &q->active);
+            buf->vb.state = VIDEOBUF_ACTIVE;
+            buf->count    = q->count++;
+            prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+            /* 64 bit bits 63-32 */
+            prev->risc.jmp[2] = cpu_to_le32(0);
+            dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",  buf, buf->vb.i, buf->count);
+
+        } else {
+            list_add_tail(&buf->vb.queue, &q->queued);
+            buf->vb.state = VIDEOBUF_QUEUED;
+            dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, buf->vb.i);
+        }
+    }
+
+    if (list_empty(&q->active))
+    {
+       dprintk(2, "active queue empty!\n");
+    }
+}
+
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+    .buf_setup    = buffer_setup,
+    .buf_prepare  = buffer_prepare,
+    .buf_queue    = buffer_queue,
+    .buf_release  = buffer_release,
+};
+
+
+static int video_open(struct file *file)
+{
+    int minor = video_devdata(file)->minor;
+    struct cx25821_dev *h, *dev = NULL;
+    struct cx25821_fh *fh;
+    struct list_head *list;
+    enum v4l2_buf_type type = 0;
+
+    lock_kernel();
+    list_for_each(list, &cx25821_devlist)
+    {
+        h = list_entry(list, struct cx25821_dev, devlist);
+
+        if (h->video_dev[SRAM_CH09] && h->video_dev[SRAM_CH09]->minor == minor)
+        {
+            dev  = h;
+            type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        }
+    }
+
+    if (NULL == dev) {
+        unlock_kernel();
+        return -ENODEV;
+    }
+
+    printk("open minor=%d type=%s\n", minor, v4l2_type_names[type]);
+
+    /* allocate + initialize per filehandle data */
+    fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+    if (NULL == fh) {
+        unlock_kernel();
+        return -ENOMEM;
+    }
+
+    file->private_data = fh;
+    fh->dev      = dev;
+    fh->type     = type;
+    fh->width    = 720;
+
+    if(dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+        fh->height = 576;
+    else
+        fh->height = 480;
+
+    dev->channel_opened = 8;
+    fh->fmt             = format_by_fourcc(V4L2_PIX_FMT_YUYV);
+
+    v4l2_prio_open(&dev->prio,&fh->prio);
+
+    videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops,
+                &dev->pci->dev, &dev->slock,
+                V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                V4L2_FIELD_INTERLACED,
+                sizeof(struct cx25821_buffer),
+                fh);
+
+    dprintk(1, "post videobuf_queue_init()\n");
+    unlock_kernel();
+
+    return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+    struct cx25821_fh *fh = file->private_data;
+
+    switch (fh->type)
+    {
+        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+            if (res_locked(fh->dev, RESOURCE_VIDEO9))
+                return -EBUSY;
+
+            return videobuf_read_one(&fh->vidq, data, count, ppos, file->f_flags & O_NONBLOCK);
+
+        default:
+            BUG();
+            return 0;
+    }
+}
+
+static unsigned int video_poll(struct file *file, struct poll_table_struct *wait)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_buffer *buf;
+
+    if (res_check(fh, RESOURCE_VIDEO9)) {
+        /* streaming capture */
+        if (list_empty(&fh->vidq.stream))
+            return POLLERR;
+        buf = list_entry(fh->vidq.stream.next,
+            struct cx25821_buffer, vb.stream);
+    } else {
+        /* read() capture */
+        buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+        if (NULL == buf)
+            return POLLERR;
+    }
+
+    poll_wait(file, &buf->vb.done, wait);
+    if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR)
+        return POLLIN|POLLRDNORM;
+    return 0;
+}
+
+
+static int video_release(struct file *file)
+{
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev;
+
+    //stop the risc engine and fifo
+    //cx_write(channel9->dma_ctl, 0); 
+
+    /* stop video capture */
+    if (res_check(fh, RESOURCE_VIDEO9)) {
+        videobuf_queue_cancel(&fh->vidq);
+        res_free(dev, fh, RESOURCE_VIDEO9);
+    }
+
+    if (fh->vidq.read_buf) {
+        buffer_release(&fh->vidq, fh->vidq.read_buf);
+        kfree(fh->vidq.read_buf);
+    }
+
+    videobuf_mmap_free(&fh->vidq);
+
+    v4l2_prio_close(&dev->prio,&fh->prio);
+
+    file->private_data = NULL;
+    kfree(fh);
+
+    return 0;
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+
+    if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(i != fh->type))
+    {
+        return -EINVAL;
+    }
+
+    if (unlikely(!res_get(dev, fh, get_resource(fh, RESOURCE_VIDEO9))))
+    {
+        return -EBUSY;
+    }
+
+    return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev = fh->dev;
+    int err, res;
+
+    if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+        return -EINVAL;
+    if (i != fh->type)
+        return -EINVAL;
+
+    res = get_resource(fh, RESOURCE_VIDEO9);
+    err = videobuf_streamoff(get_queue(fh));
+    if (err < 0)
+        return err;
+    res_free(dev, fh, res);
+    return 0;
+}
+
+static long video_ioctl_upstream9(struct file *file, unsigned int cmd, unsigned long arg)    
+{   
+    struct cx25821_fh *fh = file->private_data;
+    struct cx25821_dev *dev = fh->dev;
+    int command = 0;
+    struct upstream_user_struct *data_from_user;
+        
+    
+    data_from_user = (struct upstream_user_struct *)arg;
+    
+    if( !data_from_user )
+    {
+        printk("cx25821 in %s(): Upstream data is INVALID. Returning.\n", __func__);
+        return 0;
+    }
+      
+    command = data_from_user->command;    
+        
+    if( command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO )
+    {
+        return 0;
+    }
+    
+    
+    dev->input_filename      = data_from_user->input_filename;
+    dev->input_audiofilename = data_from_user->input_filename;
+    dev->vid_stdname         = data_from_user->vid_stdname;
+    dev->pixel_format        = data_from_user->pixel_format;
+    dev->channel_select      = data_from_user->channel_select;
+    dev->command             = data_from_user->command;
+    
+    switch(command)
+    {   
+        case UPSTREAM_START_VIDEO:
+            cx25821_start_upstream_video_ch1(dev, data_from_user);
+            break;
+            
+        case UPSTREAM_STOP_VIDEO:   
+            cx25821_stop_upstream_video_ch1(dev);
+            break;            
+    }
+       
+    return 0;
+}
+
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *f)
+{
+    struct cx25821_fh *fh = priv;
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    int err;
+
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    dprintk(2, "%s()\n", __func__);
+    err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+    if (0 != err)
+        return err;
+    fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+    fh->width      = f->fmt.pix.width;
+    fh->height     = f->fmt.pix.height;
+    fh->vidq.field = f->fmt.pix.field;
+    dprintk(2, "%s() width=%d height=%d field=%d\n", __func__, fh->width, fh->height, fh->vidq.field);
+    cx25821_call_all(dev, video, s_fmt, f);
+    return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+    struct cx25821_fh *fh = priv;
+    return videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+}
+static int vidioc_log_status (struct file *file, void *priv)
+{
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    char name[32 + 2];
+
+    snprintf(name, sizeof(name), "%s/2", dev->name);
+    printk(KERN_INFO "%s/2: ============  START LOG STATUS  ============\n",
+              dev->name);
+    cx25821_call_all(dev, core, log_status);
+    printk(KERN_INFO "%s/2: =============  END LOG STATUS  =============\n",
+              dev->name);
+    return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+    struct cx25821_dev *dev  = ((struct cx25821_fh *)priv)->dev;
+    struct cx25821_fh *fh = priv;
+    int err;
+    if (fh) 
+    {
+        err = v4l2_prio_check(&dev->prio, &fh->prio);
+        if (0 != err)
+            return err;
+    }
+
+    return 0;
+}
+// exported stuff
+static const struct v4l2_file_operations video_fops = {
+    .owner         = THIS_MODULE,
+    .open          = video_open,
+    .release       = video_release,
+    .read          = video_read,
+    .poll          = video_poll,
+    .mmap          = video_mmap,
+    .ioctl         = video_ioctl_upstream9,  
+};
+
+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_reqbufs       = vidioc_reqbufs,
+    .vidioc_querybuf      = vidioc_querybuf,
+    .vidioc_qbuf          = vidioc_qbuf,
+    .vidioc_dqbuf         = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+    .vidioc_s_std         = vidioc_s_std,
+    .vidioc_querystd      = vidioc_querystd,
+#endif
+    .vidioc_cropcap       = vidioc_cropcap,
+    .vidioc_s_crop        = vidioc_s_crop,
+    .vidioc_g_crop        = vidioc_g_crop,
+    .vidioc_enum_input    = vidioc_enum_input,
+    .vidioc_g_input       = vidioc_g_input,
+    .vidioc_s_input       = vidioc_s_input,
+    .vidioc_g_ctrl        = vidioc_g_ctrl,
+    .vidioc_s_ctrl        = vidioc_s_ctrl,
+    .vidioc_queryctrl    = vidioc_queryctrl,
+    .vidioc_streamon      = vidioc_streamon,
+    .vidioc_streamoff     = vidioc_streamoff,
+    .vidioc_log_status    = vidioc_log_status,
+    .vidioc_g_priority   = vidioc_g_priority,
+    .vidioc_s_priority   = vidioc_s_priority,
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+    .vidiocgmbuf          = vidiocgmbuf,
+#endif
+#ifdef TUNER_FLAG
+    .vidioc_g_tuner       = vidioc_g_tuner,
+    .vidioc_s_tuner       = vidioc_s_tuner,
+    .vidioc_g_frequency   = vidioc_g_frequency,
+    .vidioc_s_frequency   = vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+    .vidioc_g_register    = vidioc_g_register,
+    .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_video_template9 = {
+    .name                 = "cx25821-upstream9",
+    .fops                 = &video_fops,
+    .minor                = -1,
+    .ioctl_ops            = &video_ioctl_ops,
+    .tvnorms              = CX25821_NORMS,
+    .current_norm         = V4L2_STD_NTSC_M,
+};
+
+
+
diff --git a/drivers/staging/cx25821/cx25821.h b/drivers/staging/cx25821/cx25821.h
new file mode 100644 (file)
index 0000000..074ea34
--- /dev/null
@@ -0,0 +1,589 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc. 
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> 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.
+ */
+
+
+#ifndef CX25821_H_
+#define CX25821_H_
+
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/kdev_t.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>  
+#include <media/tuner.h>
+#include <media/tveeprom.h>
+#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-dvb.h>
+
+#include "btcx-risc.h"
+#include "cx25821-reg.h"
+#include "cx25821-medusa-reg.h"
+#include "cx25821-sram.h"
+#include "cx25821-audio.h"
+#include "media/cx2341x.h"
+
+#include <linux/version.h>
+#include <linux/mutex.h>
+
+#define CX25821_VERSION_CODE KERNEL_VERSION(0, 0, 106)
+
+#define UNSET (-1U)
+#define NO_SYNC_LINE (-1U)
+
+#define CX25821_MAXBOARDS 2
+
+#define TRUE    1
+#define FALSE   0
+#define LINE_SIZE_D1    1440
+
+// Number of decoders and encoders 
+#define MAX_DECODERS            8
+#define MAX_ENCODERS            2
+#define QUAD_DECODERS           4
+#define MAX_CAMERAS             16
+
+/* Max number of inputs by card */
+#define MAX_CX25821_INPUT 8
+#define INPUT(nr) (&cx25821_boards[dev->board].input[nr])
+#define RESOURCE_VIDEO0       1
+#define RESOURCE_VIDEO1       2
+#define RESOURCE_VIDEO2       4
+#define RESOURCE_VIDEO3       8
+#define RESOURCE_VIDEO4       16
+#define RESOURCE_VIDEO5       32
+#define RESOURCE_VIDEO6       64
+#define RESOURCE_VIDEO7       128
+#define RESOURCE_VIDEO8       256
+#define RESOURCE_VIDEO9       512
+#define RESOURCE_VIDEO10      1024
+#define RESOURCE_VIDEO11      2048
+#define RESOURCE_VIDEO_IOCTL  4096
+
+
+#define BUFFER_TIMEOUT     (HZ)  /* 0.5 seconds */
+
+#define UNKNOWN_BOARD       0
+#define CX25821_BOARD        1
+
+/* Currently supported by the driver */ 
+#define CX25821_NORMS (\
+    V4L2_STD_NTSC_M |  V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR | \
+    V4L2_STD_PAL_BG |  V4L2_STD_PAL_DK    |  V4L2_STD_PAL_I    | \
+    V4L2_STD_PAL_M  |  V4L2_STD_PAL_N     |  V4L2_STD_PAL_H    | \
+    V4L2_STD_PAL_Nc )
+
+#define CX25821_BOARD_CONEXANT_ATHENA10 1
+#define MAX_VID_CHANNEL_NUM     12
+#define VID_CHANNEL_NUM 8
+
+struct cx25821_fmt {
+    char  *name;
+    u32   fourcc;          /* v4l2 format id */
+    int   depth;
+    int   flags;
+    u32   cxformat;
+};
+
+struct cx25821_ctrl {
+    struct v4l2_queryctrl v;
+    u32                   off;
+    u32                   reg;
+    u32                   mask;
+    u32                   shift;
+};
+
+struct cx25821_tvnorm {
+    char        *name;
+    v4l2_std_id id;
+    u32     cxiformat;
+    u32     cxoformat;
+};
+
+struct cx25821_fh {
+    struct cx25821_dev         *dev;
+    enum v4l2_buf_type         type;
+    int                        radio;
+    u32                        resources;
+
+    enum v4l2_priority        prio;
+
+    /* video overlay */
+    struct v4l2_window         win;
+    struct v4l2_clip           *clips;
+    unsigned int               nclips;
+
+    /* video capture */
+    struct cx25821_fmt         *fmt;
+    unsigned int               width, height;
+
+    /* vbi capture */
+    struct videobuf_queue      vidq;
+    struct videobuf_queue      vbiq;
+
+    /* H264 Encoder specifics ONLY */
+    struct videobuf_queue      mpegq;
+    atomic_t                   v4l_reading;
+};
+
+enum cx25821_itype {
+    CX25821_VMUX_COMPOSITE = 1,
+    CX25821_VMUX_SVIDEO,
+    CX25821_VMUX_DEBUG,
+    CX25821_RADIO,
+};
+
+enum cx25821_src_sel_type {
+    CX25821_SRC_SEL_EXT_656_VIDEO = 0,
+    CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO
+};
+
+/* buffer for one video frame */
+struct cx25821_buffer {
+    /* common v4l buffer stuff -- must be first */
+    struct videobuf_buffer vb;
+
+    /* cx25821 specific */
+    unsigned int           bpl;
+    struct btcx_riscmem    risc;
+    struct cx25821_fmt     *fmt;
+    u32                    count;
+};
+
+struct cx25821_input {
+    enum cx25821_itype type;
+    unsigned int    vmux;
+    u32             gpio0, gpio1, gpio2, gpio3;
+};
+
+typedef enum {
+    CX25821_UNDEFINED = 0,
+    CX25821_RAW,
+    CX25821_264
+} port_t;
+
+struct cx25821_board {
+    char                *name;
+    port_t              porta, portb, portc;
+    unsigned int        tuner_type;
+    unsigned int        radio_type;
+    unsigned char       tuner_addr;
+    unsigned char       radio_addr;
+
+    u32         clk_freq;
+    struct cx25821_input    input[2];
+};
+
+struct cx25821_subid {
+    u16     subvendor;
+    u16     subdevice;
+    u32     card;
+};
+
+struct cx25821_i2c {
+    struct cx25821_dev *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;
+
+    /* cx25821 registers used for raw addess */
+    u32                        i2c_period;
+    u32                        reg_ctrl;
+    u32                        reg_stat;
+    u32                        reg_addr;
+    u32                        reg_rdata;
+    u32                        reg_wdata;
+};
+
+struct cx25821_dmaqueue {
+    struct list_head       active;
+    struct list_head       queued;
+    struct timer_list      timeout;
+    struct btcx_riscmem    stopper;
+    u32                    count;
+};
+
+struct cx25821_data {
+       struct cx25821_dev *dev;
+       struct sram_channel *channel;
+};
+
+struct cx25821_dev {
+    struct list_head           devlist;
+    atomic_t                   refcount;
+    struct v4l2_device         v4l2_dev;
+
+    struct v4l2_prio_state     prio;
+
+    /* pci stuff */
+    struct pci_dev             *pci;
+    unsigned char              pci_rev, pci_lat;
+    int                        pci_bus, pci_slot;
+    u32                        base_io_addr;
+    u32                        __iomem *lmmio;
+    u8                         __iomem *bmmio;
+    int                        pci_irqmask;
+    int                        hwrevision;
+
+    u32                        clk_freq;
+
+    /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
+    struct cx25821_i2c         i2c_bus[3];
+
+    int                        nr;
+    struct mutex               lock;
+
+    /* board details */
+    unsigned int               board;
+    char                       name[32];
+
+    /* sram configuration */
+    struct sram_channel        *sram_channels;
+
+    /* Analog video */
+    u32                        resources;
+    unsigned int               input;
+    u32                        tvaudio;
+    v4l2_std_id                tvnorm;
+    unsigned int               tuner_type;
+    unsigned char              tuner_addr;
+    unsigned int               radio_type;
+    unsigned char              radio_addr;
+    unsigned int               has_radio;
+    unsigned int               videc_type;
+    unsigned char              videc_addr;
+    unsigned short             _max_num_decoders;
+
+    int                        ctl_bright;
+    int                        ctl_contrast;
+    int                        ctl_hue;
+    int                        ctl_saturation;
+
+    struct cx25821_data        timeout_data[MAX_VID_CHANNEL_NUM];
+
+    /* Analog Audio Upstream */
+    int _audio_is_running;  
+    int _audiopixel_format;
+    int _is_first_audio_frame;
+    int _audiofile_status;
+    int _audio_lines_count;
+    int _audioframe_count;
+    int _audio_upstream_channel_select;
+    int _last_index_irq;                //The last interrupt index processed.
+
+    __le32 *     _risc_audio_jmp_addr;
+    __le32 *     _risc_virt_start_addr;
+    __le32 *     _risc_virt_addr;
+    dma_addr_t   _risc_phys_addr;
+    dma_addr_t   _risc_phys_start_addr;
+
+    unsigned int _audiorisc_size;
+    unsigned int _audiodata_buf_size;
+    __le32 *     _audiodata_buf_virt_addr;
+    dma_addr_t   _audiodata_buf_phys_addr;
+    char *_audiofilename;           
+
+    /* V4l */
+    u32                        freq;
+    struct video_device        *video_dev[MAX_VID_CHANNEL_NUM];
+    struct video_device        *vbi_dev;
+    struct video_device        *radio_dev;
+    struct video_device        *ioctl_dev;
+
+    struct cx25821_dmaqueue    vidq[MAX_VID_CHANNEL_NUM];
+    spinlock_t                 slock;
+    
+    /* Video Upstream */
+    int _line_size;
+    int _prog_cnt;
+    int _pixel_format;
+    int _is_first_frame;
+    int _is_running;
+    int _file_status;
+    int _lines_count;
+    int _frame_count;
+    int _channel_upstream_select;
+    unsigned int _risc_size;
+
+    __le32 *     _dma_virt_start_addr;
+    __le32 *     _dma_virt_addr;
+    dma_addr_t   _dma_phys_addr;
+    dma_addr_t   _dma_phys_start_addr;
+
+    unsigned int _data_buf_size;
+    __le32 *     _data_buf_virt_addr;
+    dma_addr_t   _data_buf_phys_addr;
+    char * _filename;       
+    char * _defaultname;      
+
+
+    int _line_size_ch2;
+    int _prog_cnt_ch2;
+    int _pixel_format_ch2;
+    int _is_first_frame_ch2;
+    int _is_running_ch2;
+    int _file_status_ch2;
+    int _lines_count_ch2;
+    int _frame_count_ch2;
+    int _channel2_upstream_select;
+    unsigned int _risc_size_ch2;
+
+    __le32 *     _dma_virt_start_addr_ch2;
+    __le32 *     _dma_virt_addr_ch2;
+    dma_addr_t   _dma_phys_addr_ch2;
+    dma_addr_t   _dma_phys_start_addr_ch2;
+
+    unsigned int _data_buf_size_ch2;
+    __le32 *     _data_buf_virt_addr_ch2;
+    dma_addr_t   _data_buf_phys_addr_ch2;
+    char * _filename_ch2;    
+    char * _defaultname_ch2; 
+
+    /* MPEG Encoder ONLY settings */
+    u32                        cx23417_mailbox;
+    struct cx2341x_mpeg_params mpeg_params;
+    struct video_device        *v4l_device;
+    atomic_t                   v4l_reader_count;
+    struct cx25821_tvnorm      encodernorm;
+    
+    u32                        upstream_riscbuf_size;
+    u32                        upstream_databuf_size;
+    u32                        upstream_riscbuf_size_ch2;
+    u32                        upstream_databuf_size_ch2;
+    u32                        audio_upstream_riscbuf_size;
+    u32                        audio_upstream_databuf_size;
+    int                        _isNTSC;    
+    int                        _frame_index;     
+    int                        _audioframe_index;  
+    struct workqueue_struct *  _irq_queues;       
+    struct work_struct         _irq_work_entry;         
+    struct workqueue_struct *  _irq_queues_ch2;       
+    struct work_struct         _irq_work_entry_ch2;         
+    struct workqueue_struct *  _irq_audio_queues;       
+    struct work_struct         _audio_work_entry; 
+    char *input_filename;
+    char *input_filename_ch2;
+    int  _frame_index_ch2;  
+    int  _isNTSC_ch2;    
+    char *vid_stdname_ch2;
+    int pixel_format_ch2;
+    int channel_select_ch2;
+    int command_ch2;
+    char *input_audiofilename;
+    char *vid_stdname;
+    int pixel_format;
+    int channel_select;
+    int command;
+    int pixel_formats[VID_CHANNEL_NUM];
+    int use_cif_resolution[VID_CHANNEL_NUM];
+    int cif_width[VID_CHANNEL_NUM];
+    int channel_opened;
+};
+
+
+struct upstream_user_struct {
+    char *input_filename;
+    char *vid_stdname;
+    int pixel_format;
+    int channel_select;
+    int command;
+};
+
+struct downstream_user_struct {
+    char *vid_stdname;
+    int pixel_format;
+    int cif_resolution_enable;
+    int cif_width;
+    int decoder_select;
+    int command;
+    int reg_address;
+    int reg_data;
+};
+
+extern struct upstream_user_struct *up_data;
+
+static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev)
+{
+    return container_of(v4l2_dev, struct cx25821_dev, v4l2_dev);
+}
+
+#define cx25821_call_all(dev, o, f, args...) \
+    v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args)
+    
+extern struct list_head cx25821_devlist;
+extern struct cx25821_board cx25821_boards[];
+extern struct cx25821_subid cx25821_subids[];
+
+#define SRAM_CH00  0 /* Video A */
+#define SRAM_CH01  1 /* Video B */
+#define SRAM_CH02  2 /* Video C */
+#define SRAM_CH03  3 /* Video D */
+#define SRAM_CH04  4 /* Video E */
+#define SRAM_CH05  5 /* Video F */
+#define SRAM_CH06  6 /* Video G */
+#define SRAM_CH07  7 /* Video H */
+
+#define SRAM_CH08  8 /* Audio A */
+#define SRAM_CH09  9 /* Video Upstream I */
+#define SRAM_CH10  10 /* Video Upstream J */
+#define SRAM_CH11  11 /* Audio Upstream AUD_CHANNEL_B */
+
+
+
+#define VID_UPSTREAM_SRAM_CHANNEL_I     SRAM_CH09
+#define VID_UPSTREAM_SRAM_CHANNEL_J     SRAM_CH10
+#define AUDIO_UPSTREAM_SRAM_CHANNEL_B   SRAM_CH11
+#define VIDEO_IOCTL_CH  11
+
+struct sram_channel {
+    char *name;
+    u32  i;
+    u32  cmds_start;
+    u32  ctrl_start;
+    u32  cdt;
+    u32  fifo_start;
+    u32  fifo_size;
+    u32  ptr1_reg;
+    u32  ptr2_reg;
+    u32  cnt1_reg;
+    u32  cnt2_reg;
+    u32  int_msk;
+    u32  int_stat;
+    u32  int_mstat;
+    u32  dma_ctl;
+    u32  gpcnt_ctl;
+    u32  gpcnt;
+    u32  aud_length;
+    u32  aud_cfg;
+    u32  fld_aud_fifo_en;
+    u32  fld_aud_risc_en;
+    
+    //For Upstream Video
+    u32  vid_fmt_ctl;
+    u32  vid_active_ctl1;
+    u32  vid_active_ctl2;
+    u32  vid_cdt_size;
+    
+    u32  vip_ctl;
+    u32  pix_frmt;
+    u32  jumponly;    
+    u32  irq_bit;
+};
+extern struct sram_channel cx25821_sram_channels[];
+
+#define STATUS_SUCCESS         0
+#define STATUS_UNSUCCESSFUL    -1
+
+#define cx_read(reg)             readl(dev->lmmio + ((reg)>>2))
+#define cx_write(reg, value)     writel((value), dev->lmmio + ((reg)>>2))
+
+#define cx_andor(reg, mask, value) \
+  writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
+  ((value) & (mask)), dev->lmmio+((reg)>>2))
+
+#define cx_set(reg, bit)          cx_andor((reg), (bit), (bit))
+#define cx_clear(reg, bit)        cx_andor((reg), (bit), 0)
+
+#define Set_GPIO_Bit(Bit)                       (1 << Bit)
+#define Clear_GPIO_Bit(Bit)                     (~(1 << Bit))
+
+#define CX25821_ERR(fmt, args...)      printk(KERN_ERR  "cx25821(%d): " fmt, dev->board, ## args)
+#define CX25821_WARN(fmt, args...)     printk(KERN_WARNING "cx25821(%d): " fmt, dev->board , ## args)
+#define CX25821_INFO(fmt, args...)     printk(KERN_INFO "cx25821(%d): " fmt, dev->board , ## args)
+
+extern int  cx25821_i2c_register(struct cx25821_i2c *bus);
+extern void cx25821_card_setup(struct cx25821_dev *dev);
+extern int  cx25821_ir_init(struct cx25821_dev *dev);
+extern int  cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value);
+extern int  cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value);
+extern int  cx25821_i2c_unregister(struct cx25821_i2c *bus);
+extern void cx25821_gpio_init(struct cx25821_dev *dev);
+extern void cx25821_set_gpiopin_direction( struct cx25821_dev *dev,
+                                           int    pin_number,
+                                           int    pin_logic_value);
+                                 
+extern int  medusa_video_init(struct cx25821_dev *dev);
+extern int  medusa_set_videostandard(struct cx25821_dev *dev);
+extern void medusa_set_resolution(struct cx25821_dev *dev, int width, int decoder_select);
+extern int  medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder);
+extern int  medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder);
+extern int  medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder);
+extern int  medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder);
+
+extern int  cx25821_sram_channel_setup(struct cx25821_dev *dev, struct sram_channel *ch, unsigned int bpl, u32 risc);
+
+extern int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+                   struct scatterlist *sglist, 
+                   unsigned int top_offset,
+                   unsigned int bottom_offset, 
+                   unsigned int bpl,
+                   unsigned int padding, 
+                   unsigned int lines);
+extern int cx25821_risc_databuffer_audio(struct pci_dev *pci,
+                   struct btcx_riscmem *risc,
+                   struct scatterlist *sglist,
+                   unsigned int bpl,
+                   unsigned int lines,
+                   unsigned int lpi);           
+extern void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf);
+extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,u32 reg, u32 mask, u32 value);
+extern void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch);
+extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, struct sram_channel *ch);
+
+
+extern struct cx25821_dev* cx25821_dev_get(struct pci_dev *pci);
+extern void cx25821_print_irqbits(char *name, char *tag, char **strings, int len, u32 bits, u32 mask);
+extern void cx25821_dev_unregister(struct cx25821_dev *dev);
+extern int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev,
+                   struct sram_channel *ch,
+                   unsigned int bpl, u32 risc);
+                   
+extern int  cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, int pixel_format);
+extern int  cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, int pixel_format);
+extern int  cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select);
+extern void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev);            
+extern void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev);             
+extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev);   
+extern void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, struct upstream_user_struct *up_data);  
+extern void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, struct upstream_user_struct *up_data);  
+extern void cx25821_start_upstream_audio(struct cx25821_dev *dev, struct upstream_user_struct *up_data);    
+extern void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev);    
+extern void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev);  
+extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev); 
+extern int  cx25821_sram_channel_setup_upstream( struct cx25821_dev *dev, struct sram_channel *ch, unsigned int bpl, u32 risc);
+extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel, u32 format);
+extern void cx25821_videoioctl_unregister(struct cx25821_dev *dev);
+extern struct video_device *cx25821_vdev_init(struct cx25821_dev *dev,
+                    struct pci_dev *pci,
+                    struct video_device *template,
+                    char *type);
+#endif