summaryrefslogtreecommitdiffstats
path: root/drivers/media/pci/cx25821
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/pci/cx25821')
-rw-r--r--drivers/media/pci/cx25821/Kconfig29
-rw-r--r--drivers/media/pci/cx25821/Makefile7
-rw-r--r--drivers/media/pci/cx25821/cx25821-alsa.c819
-rw-r--r--drivers/media/pci/cx25821/cx25821-audio.h48
-rw-r--r--drivers/media/pci/cx25821/cx25821-biffuncs.h31
-rw-r--r--drivers/media/pci/cx25821/cx25821-cards.c33
-rw-r--r--drivers/media/pci/cx25821/cx25821-core.c1385
-rw-r--r--drivers/media/pci/cx25821/cx25821-gpio.c85
-rw-r--r--drivers/media/pci/cx25821/cx25821-i2c.c405
-rw-r--r--drivers/media/pci/cx25821/cx25821-medusa-defines.h28
-rw-r--r--drivers/media/pci/cx25821/cx25821-medusa-reg.h441
-rw-r--r--drivers/media/pci/cx25821/cx25821-medusa-video.c731
-rw-r--r--drivers/media/pci/cx25821/cx25821-medusa-video.h29
-rw-r--r--drivers/media/pci/cx25821/cx25821-reg.h1578
-rw-r--r--drivers/media/pci/cx25821/cx25821-sram.h247
-rw-r--r--drivers/media/pci/cx25821/cx25821-video.c776
-rw-r--r--drivers/media/pci/cx25821/cx25821-video.h51
-rw-r--r--drivers/media/pci/cx25821/cx25821.h426
18 files changed, 7149 insertions, 0 deletions
diff --git a/drivers/media/pci/cx25821/Kconfig b/drivers/media/pci/cx25821/Kconfig
new file mode 100644
index 000000000..b26615fdc
--- /dev/null
+++ b/drivers/media/pci/cx25821/Kconfig
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config VIDEO_CX25821
+ tristate "Conexant cx25821 support"
+ depends on VIDEO_DEV && PCI && I2C
+ select I2C_ALGOBIT
+ select VIDEOBUF2_DMA_SG
+ 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
+ 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/media/pci/cx25821/Makefile b/drivers/media/pci/cx25821/Makefile
new file mode 100644
index 000000000..94633d02a
--- /dev/null
+++ b/drivers/media/pci/cx25821/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+cx25821-y := cx25821-core.o cx25821-cards.o cx25821-i2c.o \
+ cx25821-gpio.o cx25821-medusa-video.o \
+ cx25821-video.o
+
+obj-$(CONFIG_VIDEO_CX25821) += cx25821.o
+obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o
diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c
new file mode 100644
index 000000000..a42f0c03a
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-alsa.c
@@ -0,0 +1,819 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ * Based on SAA713x ALSA driver and CX88 driver
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#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 <linux/slab.h>
+
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "cx25821.h"
+#include "cx25821-reg.h"
+
+#define AUDIO_SRAM_CHANNEL SRAM_CH08
+
+#define dprintk(level, fmt, arg...) \
+do { \
+ if (debug >= level) \
+ pr_info("%s/1: " fmt, chip->dev->name, ##arg); \
+} while (0)
+#define dprintk_core(level, fmt, arg...) \
+do { \
+ if (debug >= level) \
+ printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name, ##arg); \
+} while (0)
+
+/****************************************************************************
+ Data type declarations - Can be moded to a header file later
+ ****************************************************************************/
+
+static int devno;
+
+struct cx25821_audio_buffer {
+ unsigned int bpl;
+ struct cx25821_riscmem risc;
+ void *vaddr;
+ struct scatterlist *sglist;
+ int sglen;
+ unsigned long nr_pages;
+};
+
+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 cx25821_audio_buffer *buf;
+
+ struct snd_pcm_substream *substream;
+};
+
+
+/****************************************************************************
+ 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 bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+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");
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+/****************************************************************************
+ Module specific functions
+ ****************************************************************************/
+/* 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)
+
+static int cx25821_alsa_dma_init(struct cx25821_audio_dev *chip,
+ unsigned long nr_pages)
+{
+ struct cx25821_audio_buffer *buf = chip->buf;
+ struct page *pg;
+ int i;
+
+ buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
+ if (NULL == buf->vaddr) {
+ dprintk(1, "vmalloc_32(%lu pages) failed\n", nr_pages);
+ return -ENOMEM;
+ }
+
+ dprintk(1, "vmalloc is at addr 0x%p, size=%lu\n",
+ buf->vaddr,
+ nr_pages << PAGE_SHIFT);
+
+ memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT);
+ buf->nr_pages = nr_pages;
+
+ buf->sglist = vzalloc(array_size(sizeof(*buf->sglist), buf->nr_pages));
+ if (NULL == buf->sglist)
+ goto vzalloc_err;
+
+ sg_init_table(buf->sglist, buf->nr_pages);
+ for (i = 0; i < buf->nr_pages; i++) {
+ pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE);
+ if (NULL == pg)
+ goto vmalloc_to_page_err;
+ sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0);
+ }
+ return 0;
+
+vmalloc_to_page_err:
+ vfree(buf->sglist);
+ buf->sglist = NULL;
+vzalloc_err:
+ vfree(buf->vaddr);
+ buf->vaddr = NULL;
+ return -ENOMEM;
+}
+
+static int cx25821_alsa_dma_map(struct cx25821_audio_dev *dev)
+{
+ struct cx25821_audio_buffer *buf = dev->buf;
+
+ buf->sglen = dma_map_sg(&dev->pci->dev, buf->sglist,
+ buf->nr_pages, DMA_FROM_DEVICE);
+
+ if (0 == buf->sglen) {
+ pr_warn("%s: cx25821_alsa_map_sg failed\n", __func__);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int cx25821_alsa_dma_unmap(struct cx25821_audio_dev *dev)
+{
+ struct cx25821_audio_buffer *buf = dev->buf;
+
+ if (!buf->sglen)
+ return 0;
+
+ dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->nr_pages, DMA_FROM_DEVICE);
+ buf->sglen = 0;
+ return 0;
+}
+
+static int cx25821_alsa_dma_free(struct cx25821_audio_buffer *buf)
+{
+ vfree(buf->sglist);
+ buf->sglist = NULL;
+ vfree(buf->vaddr);
+ buf->vaddr = NULL;
+ return 0;
+}
+
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip)
+{
+ struct cx25821_audio_buffer *buf = chip->buf;
+ struct cx25821_dev *dev = chip->dev;
+ const 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 */
+ /* GP_COUNT_CONTROL_RESET = 0x3 */
+ cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+ 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);
+
+ /*
+ pr_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(struct cx25821_audio_dev *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(struct cx25821_audio_dev *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) {
+ pr_warn("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) {
+ pr_warn("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)
+{
+ struct cx25821_audio_dev *chip = dev_id;
+ struct cx25821_dev *dev = chip->dev;
+ u32 status, pci_status;
+ u32 audint_status, audint_mask;
+ int loop, handled = 0;
+
+ audint_status = cx_read(AUD_A_INT_STAT);
+ audint_mask = cx_read(AUD_A_INT_MSK);
+ 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(struct cx25821_audio_dev *chip)
+{
+ struct cx25821_riscmem *risc = &chip->buf->risc;
+
+ BUG_ON(!chip->dma_size);
+
+ dprintk(2, "Freeing buffer\n");
+ cx25821_alsa_dma_unmap(chip);
+ cx25821_alsa_dma_free(chip->buf);
+ dma_free_coherent(&chip->pci->dev, risc->size, risc->cpu, risc->dma);
+ kfree(chip->buf);
+
+ chip->buf = NULL;
+ chip->dma_size = 0;
+
+ return 0;
+}
+
+/****************************************************************************
+ ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE 384
+static const 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,
+ /* 128 * 128 = 16384 = 1024 * 16 */
+ .buffer_bytes_max = (AUDIO_LINE_SIZE * AUDIO_LINE_SIZE),
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int err;
+ unsigned int bpl = 0;
+
+ if (!chip) {
+ pr_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) {
+ /* since there are 3 audio Clusters */
+ bpl = cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 3;
+ 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)
+{
+ struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+ struct cx25821_audio_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 = kzalloc(sizeof(*buf), GFP_KERNEL);
+ if (NULL == buf)
+ return -ENOMEM;
+
+ if (chip->period_size > AUDIO_LINE_SIZE)
+ chip->period_size = AUDIO_LINE_SIZE;
+
+ buf->bpl = chip->period_size;
+ chip->buf = buf;
+
+ ret = cx25821_alsa_dma_init(chip,
+ (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
+ if (ret < 0)
+ goto error;
+
+ ret = cx25821_alsa_dma_map(chip);
+ if (ret < 0)
+ goto error;
+
+ ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, buf->sglist,
+ chip->period_size, chip->num_periods, 1);
+ if (ret < 0) {
+ pr_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 */
+
+ substream->runtime->dma_area = chip->buf->vaddr;
+ substream->runtime->dma_bytes = chip->dma_size;
+ substream->runtime->dma_addr = 0;
+
+ return 0;
+
+error:
+ chip->buf = NULL;
+ kfree(buf);
+ return ret;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx25821_hw_free(struct snd_pcm_substream *substream)
+{
+ struct cx25821_audio_dev *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)
+{
+ struct cx25821_audio_dev *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)
+{
+ struct cx25821_audio_dev *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 const struct snd_pcm_ops snd_cx25821_pcm_ops = {
+ .open = snd_cx25821_pcm_open,
+ .close = snd_cx25821_close,
+ .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(struct cx25821_audio_dev *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) {
+ pr_info("ERROR: FAILED snd_pcm_new() in %s\n", __func__);
+ return err;
+ }
+ pcm->private_data = chip;
+ pcm->info_flags = 0;
+ strscpy(pcm->name, name, sizeof(pcm->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 const struct pci_device_id __maybe_unused cx25821_audio_pci_tbl[] = {
+ {0x14f1, 0x0920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl);
+
+/*
+ * Alsa Constructor - Component probe
+ */
+static int cx25821_audio_initdev(struct cx25821_dev *dev)
+{
+ struct snd_card *card;
+ struct cx25821_audio_dev *chip;
+ int err;
+
+ if (devno >= SNDRV_CARDS) {
+ pr_info("DEBUG ERROR: devno >= SNDRV_CARDS %s\n", __func__);
+ return -ENODEV;
+ }
+
+ if (!enable[devno]) {
+ ++devno;
+ pr_info("DEBUG ERROR: !enable[devno] %s\n", __func__);
+ return -ENOENT;
+ }
+
+ err = snd_card_new(&dev->pci->dev, index[devno], id[devno],
+ THIS_MODULE,
+ sizeof(struct cx25821_audio_dev), &card);
+ if (err < 0) {
+ pr_info("DEBUG ERROR: cannot create snd_card_new in %s\n",
+ __func__);
+ return err;
+ }
+
+ strscpy(card->driver, "cx25821", sizeof(card->driver));
+
+ /* Card "creation" */
+ chip = 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 = devm_request_irq(&dev->pci->dev, dev->pci->irq, cx25821_irq,
+ IRQF_SHARED, chip->dev->name, chip);
+
+ if (err < 0) {
+ pr_err("ERROR %s: can't get IRQ %d for ALSA\n", chip->dev->name,
+ dev->pci->irq);
+ goto error;
+ }
+
+ err = snd_cx25821_pcm(chip, 0, "cx25821 Digital");
+ if (err < 0) {
+ pr_info("DEBUG ERROR: cannot create snd_cx25821_pcm %s\n",
+ __func__);
+ goto error;
+ }
+
+ strscpy(card->shortname, "cx25821", sizeof(card->shortname));
+ sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name,
+ chip->iobase, chip->irq);
+ strscpy(card->mixername, "CX25821", sizeof(card->mixername));
+
+ pr_info("%s/%i: ALSA support for cx25821 boards\n", card->driver,
+ devno);
+
+ err = snd_card_register(card);
+ if (err < 0) {
+ pr_info("DEBUG ERROR: cannot register sound card %s\n",
+ __func__);
+ goto error;
+ }
+
+ dev->card = card;
+ devno++;
+ return 0;
+
+error:
+ snd_card_free(card);
+ return err;
+}
+
+/****************************************************************************
+ LINUX MODULE INIT
+ ****************************************************************************/
+
+static int cx25821_alsa_exit_callback(struct device *dev, void *data)
+{
+ struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
+ struct cx25821_dev *cxdev = get_cx25821(v4l2_dev);
+
+ snd_card_free(cxdev->card);
+ return 0;
+}
+
+static void cx25821_audio_fini(void)
+{
+ struct device_driver *drv = driver_find("cx25821", &pci_bus_type);
+ int ret;
+
+ ret = driver_for_each_device(drv, NULL, NULL, cx25821_alsa_exit_callback);
+ if (ret)
+ pr_err("%s failed to find a cx25821 driver.\n", __func__);
+}
+
+static int cx25821_alsa_init_callback(struct device *dev, void *data)
+{
+ struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
+ struct cx25821_dev *cxdev = get_cx25821(v4l2_dev);
+
+ cx25821_audio_initdev(cxdev);
+ return 0;
+}
+
+/*
+ * Module initializer
+ *
+ * Loops through present saa7134 cards, and assigns an ALSA device
+ * to each one
+ *
+ */
+static int cx25821_alsa_init(void)
+{
+ struct device_driver *drv = driver_find("cx25821", &pci_bus_type);
+
+ return driver_for_each_device(drv, NULL, NULL, cx25821_alsa_init_callback);
+
+}
+
+late_initcall(cx25821_alsa_init);
+module_exit(cx25821_audio_fini);
diff --git a/drivers/media/pci/cx25821/cx25821-audio.h b/drivers/media/pci/cx25821/cx25821-audio.h
new file mode 100644
index 000000000..96f26e4b2
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-audio.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ */
+
+#ifndef __CX25821_AUDIO_H__
+#define __CX25821_AUDIO_H__
+
+#define USE_RISC_NOOP 1
+#define LINES_PER_BUFFER 15
+#define AUDIO_LINE_SIZE 128
+
+/* Number of buffer programs to use at once. */
+#define NUMBER_OF_PROGRAMS 8
+
+/*
+ * Max size of the RISC program for a buffer. - worst case is 2 writes per line
+ * Space is also added for the 4 no-op instructions added on the end.
+ */
+#ifndef USE_RISC_NOOP
+#define MAX_BUFFER_PROGRAM_SIZE \
+ (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \
+ RISC_WRITECR_INSTRUCTION_SIZE * 4)
+#endif
+
+/* MAE 12 July 2005 Try to use NOOP RISC instruction instead */
+#ifdef USE_RISC_NOOP
+#define MAX_BUFFER_PROGRAM_SIZE \
+ (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \
+ RISC_NOOP_INSTRUCTION_SIZE * 4)
+#endif
+
+/* Sizes of various instructions in bytes. Used when adding instructions. */
+#define RISC_WRITE_INSTRUCTION_SIZE 12
+#define RISC_JUMP_INSTRUCTION_SIZE 12
+#define RISC_SKIP_INSTRUCTION_SIZE 4
+#define RISC_SYNC_INSTRUCTION_SIZE 4
+#define RISC_WRITECR_INSTRUCTION_SIZE 16
+#define RISC_NOOP_INSTRUCTION_SIZE 4
+
+#define MAX_AUDIO_DMA_BUFFER_SIZE \
+ (MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + \
+ RISC_SYNC_INSTRUCTION_SIZE)
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-biffuncs.h b/drivers/media/pci/cx25821/cx25821-biffuncs.h
new file mode 100644
index 000000000..6c1aa132e
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-biffuncs.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ */
+
+#ifndef _BITFUNCS_H
+#define _BITFUNCS_H
+
+#define SetBit(Bit) (1 << Bit)
+
+static inline u8 getBit(u32 sample, u8 index)
+{
+ return (u8) ((sample >> index) & 1);
+}
+
+static inline u32 clearBitAtPos(u32 value, u8 bit)
+{
+ return value & ~(1 << bit);
+}
+
+static inline u32 setBitAtPos(u32 sample, u8 bit)
+{
+ sample |= (1 << bit);
+ return sample;
+
+}
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-cards.c b/drivers/media/pci/cx25821/cx25821-cards.c
new file mode 100644
index 000000000..5aa67fa51
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-cards.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * 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
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "cx25821.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,
+ },
+
+};
diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c
new file mode 100644
index 000000000..6627fa916
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-core.c
@@ -0,0 +1,1385 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * 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
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/i2c.h>
+#include <linux/slab.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");
+
+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");
+
+const 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,
+ },
+};
+EXPORT_SYMBOL(cx25821_sram_channels);
+
+static int cx25821_risc_decode(u32 risc)
+{
+ static const char * const 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 const 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 const char * const bits[] = {
+ "12", "13", "14", "resync",
+ "cnt0", "cnt1", "18", "19",
+ "20", "21", "22", "23",
+ "irq1", "irq2", "eol", "sol",
+ };
+ int i;
+
+ pr_cont("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)))
+ pr_cont(" %s", bits[i]);
+ }
+ pr_cont(" count=%d ]\n", risc & 0xfff);
+ return incr[risc >> 28] ? incr[risc >> 28] : 1;
+}
+
+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);
+ /* use external ALT_PLL_REF pin as its reference clock instead */
+ tmp |= FLD_USE_ALT_PLL_REF;
+ cx_write(CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE));
+
+ msleep(100);
+}
+
+int cx25821_sram_channel_setup(struct cx25821_dev *dev,
+ const 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,
+ const 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;
+}
+EXPORT_SYMBOL(cx25821_sram_channel_setup_audio);
+
+void cx25821_sram_channel_dump(struct cx25821_dev *dev, const 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;
+
+ pr_warn("%s: %s - dma channel status dump\n", dev->name, ch->name);
+ for (i = 0; i < ARRAY_SIZE(name); i++)
+ pr_warn("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));
+ pr_warn("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 */
+
+ pr_warn("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));
+ pr_warn("ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n",
+ 4 * (i + j), i + j, risc, j);
+ }
+ }
+
+ pr_warn(" : fifo: 0x%08x -> 0x%x\n",
+ ch->fifo_start, ch->fifo_start + ch->fifo_size);
+ pr_warn(" : ctrl: 0x%08x -> 0x%x\n",
+ ch->ctrl_start, ch->ctrl_start + 6 * 16);
+ pr_warn(" : ptr1_reg: 0x%08x\n",
+ cx_read(ch->ptr1_reg));
+ pr_warn(" : ptr2_reg: 0x%08x\n",
+ cx_read(ch->ptr2_reg));
+ pr_warn(" : cnt1_reg: 0x%08x\n",
+ cx_read(ch->cnt1_reg));
+ pr_warn(" : cnt2_reg: 0x%08x\n",
+ cx_read(ch->cnt2_reg));
+}
+
+void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
+ const struct sram_channel *ch)
+{
+ static const char * const 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;
+
+ pr_info("\n%s: %s - dma Audio channel status dump\n",
+ dev->name, ch->name);
+
+ for (i = 0; i < ARRAY_SIZE(name); i++)
+ pr_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));
+ pr_warn("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 */
+
+ pr_warn("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));
+ pr_warn("ctrl + 0x%2x : iq %x: 0x%08x [ arg #%d ]\n",
+ 4 * (i + j), i + j, risc, j);
+ }
+ }
+
+ pr_warn(" : fifo: 0x%08x -> 0x%x\n",
+ ch->fifo_start, ch->fifo_start + ch->fifo_size);
+ pr_warn(" : ctrl: 0x%08x -> 0x%x\n",
+ ch->ctrl_start, ch->ctrl_start + 6 * 16);
+ pr_warn(" : ptr1_reg: 0x%08x\n",
+ cx_read(ch->ptr1_reg));
+ pr_warn(" : ptr2_reg: 0x%08x\n",
+ cx_read(ch->ptr2_reg));
+ pr_warn(" : cnt1_reg: 0x%08x\n",
+ cx_read(ch->cnt1_reg));
+ pr_warn(" : 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));
+ pr_warn("instruction %d = 0x%x\n", i, risc);
+ }
+
+ /* read data from the first cdt buffer */
+ risc = cx_read(AUD_A_CDT);
+ pr_warn("\nread cdt loc=0x%x\n", risc);
+ for (i = 0; i < 8; i++) {
+ n = cx_read(risc + i * 4);
+ pr_cont("0x%x ", n);
+ }
+ pr_cont("\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);
+}
+EXPORT_SYMBOL(cx25821_sram_channel_dump_audio);
+
+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->channels[i].sram_channels->dma_ctl, 0);
+ cx_write(dev->channels[i].sram_channels->int_msk, 0);
+ }
+
+ for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+ i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) {
+ cx_write(dev->channels[i].sram_channels->dma_ctl, 0);
+ cx_write(dev->channels[i].sram_channels->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)
+{
+ if (channel_select <= 7 && channel_select >= 0) {
+ cx_write(dev->channels[channel_select].sram_channels->pix_frmt,
+ format);
+ }
+ dev->channels[channel_select].pixel_formats = format;
+}
+
+static void cx25821_set_vip_mode(struct cx25821_dev *dev,
+ const 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->channels[i].sram_channels->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 */
+ msleep(100);
+
+ for (i = 0; i < VID_CHANNEL_NUM; i++) {
+ cx25821_set_vip_mode(dev, dev->channels[i].sram_channels);
+ cx25821_sram_channel_setup(dev, dev->channels[i].sram_channels,
+ 1440, 0);
+ dev->channels[i].pixel_formats = PIXEL_FRMT_422;
+ dev->channels[i].use_cif_resolution = 0;
+ }
+
+ /* Probably only affect Downstream */
+ for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+ i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) {
+ dev->channels[i].pixel_formats = PIXEL_FRMT_422;
+ cx25821_set_vip_mode(dev, dev->channels[i].sram_channels);
+ }
+
+ cx25821_sram_channel_setup_audio(dev,
+ dev->channels[SRAM_CH08].sram_channels, 128, 0);
+
+ cx25821_gpio_init(dev);
+}
+
+static int cx25821_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;
+
+ pr_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;
+
+ pr_info("Hardware revision = 0x%02x\n", dev->hwrevision);
+}
+
+static void cx25821_iounmap(struct cx25821_dev *dev)
+{
+ if (dev == NULL)
+ return;
+
+ /* Releasing IO memory */
+ if (dev->lmmio != NULL) {
+ iounmap(dev->lmmio);
+ dev->lmmio = NULL;
+ }
+}
+
+static int cx25821_dev_setup(struct cx25821_dev *dev)
+{
+ static unsigned int cx25821_devcount;
+ int i;
+
+ mutex_init(&dev->lock);
+
+ dev->nr = ++cx25821_devcount;
+ sprintf(dev->name, "cx25821[%d]", dev->nr);
+
+ if (dev->nr >= ARRAY_SIZE(card)) {
+ CX25821_INFO("dev->nr >= %zd", ARRAY_SIZE(card));
+ return -ENODEV;
+ }
+ if (dev->pci->device != 0x8210) {
+ pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n",
+ __func__, dev->pci->device);
+ return -ENODEV;
+ }
+ pr_info("Athena Hardware device = 0x%02x\n", dev->pci->device);
+
+ /* Apply a sensible clock frequency for the PCIe bridge */
+ dev->clk_freq = 28000000;
+ for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) {
+ dev->channels[i].dev = dev;
+ dev->channels[i].id = i;
+ dev->channels[i].sram_channels = &cx25821_sram_channels[i];
+ }
+
+ /* 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 (cx25821_get_resources(dev) < 0) {
+ pr_err("%s: No more PCIe resources for subsystem: %04x:%04x\n",
+ dev->name, dev->pci->subsystem_vendor,
+ dev->pci->subsystem_device);
+
+ cx25821_devcount--;
+ return -EBUSY;
+ }
+
+ /* PCIe stuff */
+ dev->base_io_addr = pci_resource_start(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;
+
+ pr_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]); */
+
+ if (medusa_video_init(dev) < 0)
+ CX25821_ERR("%s(): Failed to initialize medusa!\n", __func__);
+
+ cx25821_video_register(dev);
+
+ cx25821_dev_checkrevision(dev);
+ return 0;
+}
+
+void cx25821_dev_unregister(struct cx25821_dev *dev)
+{
+ int i;
+
+ if (!dev->base_io_addr)
+ return;
+
+ release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0));
+
+ for (i = 0; i < MAX_VID_CAP_CHANNEL_NUM - 1; i++) {
+ if (i == SRAM_CH08) /* audio channel */
+ continue;
+ /*
+ * TODO: enable when video output is properly
+ * supported.
+ if (i == SRAM_CH09 || i == SRAM_CH10)
+ cx25821_free_mem_upstream(&dev->channels[i]);
+ */
+ cx25821_video_unregister(dev, i);
+ }
+
+ cx25821_i2c_unregister(&dev->i2c_bus[0]);
+ cx25821_iounmap(dev);
+}
+EXPORT_SYMBOL(cx25821_dev_unregister);
+
+int cx25821_riscmem_alloc(struct pci_dev *pci,
+ struct cx25821_riscmem *risc,
+ unsigned int size)
+{
+ __le32 *cpu;
+ dma_addr_t dma = 0;
+
+ if (risc->cpu && risc->size < size) {
+ dma_free_coherent(&pci->dev, risc->size, risc->cpu, risc->dma);
+ risc->cpu = NULL;
+ }
+ if (NULL == risc->cpu) {
+ cpu = dma_alloc_coherent(&pci->dev, size, &dma, GFP_KERNEL);
+ if (NULL == cpu)
+ return -ENOMEM;
+ risc->cpu = cpu;
+ risc->dma = dma;
+ risc->size = size;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(cx25821_riscmem_alloc);
+
+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, bool jump)
+{
+ struct scatterlist *sg;
+ unsigned int line, todo;
+
+ if (jump) {
+ *(rp++) = cpu_to_le32(RISC_JUMP);
+ *(rp++) = cpu_to_le32(0);
+ *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+ }
+
+ /* 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 = sg_next(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 = sg_next(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 = sg_next(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 cx25821_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 3 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 += 5;
+ rc = cx25821_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, true);
+ }
+
+ if (UNSET != bottom_offset) {
+ rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl,
+ padding, lines, UNSET == top_offset);
+ }
+
+ /* save pointer to jmp instruction address */
+ risc->jmp = rp;
+ BUG_ON((risc->jmp - risc->cpu + 3) * 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 = sg_next(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 = sg_next(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 = sg_next(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 cx25821_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;
+
+ rc = cx25821_riscmem_alloc(pci, risc, instructions * 12);
+ if (rc < 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;
+}
+EXPORT_SYMBOL(cx25821_risc_databuffer_audio);
+
+void cx25821_free_buffer(struct cx25821_dev *dev, struct cx25821_buffer *buf)
+{
+ if (WARN_ON(buf->risc.size == 0))
+ return;
+ dma_free_coherent(&dev->pci->dev, buf->risc.size, buf->risc.cpu,
+ buf->risc.dma);
+ memset(&buf->risc, 0, sizeof(buf->risc));
+}
+
+static irqreturn_t cx25821_irq(int irq, void *dev_id)
+{
+ struct cx25821_dev *dev = dev_id;
+ u32 pci_status;
+ 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);
+
+ if (pci_status == 0)
+ goto out;
+
+ for (i = 0; i < VID_CHANNEL_NUM; i++) {
+ if (pci_status & mask[i]) {
+ vid_status = cx_read(dev->channels[i].
+ sram_channels->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 pr_fmt("%s: %s [0x%x]"), name, tag, bits);
+
+ for (i = 0; i < len; i++) {
+ if (!(bits & (1 << i)))
+ continue;
+ if (strings[i])
+ pr_cont(" %s", strings[i]);
+ else
+ pr_cont(" %d", i);
+ if (!(mask & (1 << i)))
+ continue;
+ pr_cont("*");
+ }
+ pr_cont("\n");
+}
+EXPORT_SYMBOL(cx25821_print_irqbits);
+
+struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci)
+{
+ struct cx25821_dev *dev = pci_get_drvdata(pci);
+ return dev;
+}
+EXPORT_SYMBOL(cx25821_dev_get);
+
+static int 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;
+
+ pr_info("pci enable failed!\n");
+
+ goto fail_unregister_device;
+ }
+
+ err = cx25821_dev_setup(dev);
+ if (err)
+ goto fail_unregister_pci;
+
+ /* 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);
+ pr_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);
+ err = dma_set_mask(&pci_dev->dev, 0xffffffff);
+ if (err) {
+ pr_err("%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, dev->name, dev);
+
+ if (err < 0) {
+ pr_err("%s: can't get IRQ %d\n", dev->name, pci_dev->irq);
+ goto fail_irq;
+ }
+
+ return 0;
+
+fail_irq:
+ pr_info("cx25821_initdev() can't get IRQ !\n");
+ cx25821_dev_unregister(dev);
+
+fail_unregister_pci:
+ pci_disable_device(pci_dev);
+fail_unregister_device:
+ v4l2_device_unregister(&dev->v4l2_dev);
+
+fail_free:
+ kfree(dev);
+ return err;
+}
+
+static void 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);
+
+ /* unregister stuff */
+ if (pci_dev->irq)
+ free_irq(pci_dev->irq, dev);
+ pci_disable_device(pci_dev);
+
+ cx25821_dev_unregister(dev);
+ v4l2_device_unregister(v4l2_dev);
+ kfree(dev);
+}
+
+static const struct pci_device_id cx25821_pci_tbl[] = {
+ {
+ /* CX25821 Athena */
+ .vendor = 0x14f1,
+ .device = 0x8210,
+ .subvendor = 0x14f1,
+ .subdevice = 0x0920,
+ }, {
+ /* CX25821 No Brand */
+ .vendor = 0x14f1,
+ .device = 0x8210,
+ .subvendor = 0x0000,
+ .subdevice = 0x0000,
+ }, {
+ /* --- 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 = cx25821_finidev,
+};
+
+static int __init cx25821_init(void)
+{
+ pr_info("driver loaded\n");
+ return pci_register_driver(&cx25821_pci_driver);
+}
+
+static void __exit cx25821_fini(void)
+{
+ pci_unregister_driver(&cx25821_pci_driver);
+}
+
+module_init(cx25821_init);
+module_exit(cx25821_fini);
diff --git a/drivers/media/pci/cx25821/cx25821-gpio.c b/drivers/media/pci/cx25821/cx25821-gpio.c
new file mode 100644
index 000000000..dbe3ca61c
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-gpio.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ */
+
+#include <linux/module.h>
+#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);
+}
+EXPORT_SYMBOL(cx25821_set_gpiopin_direction);
+
+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;
+
+ /* change to output direction */
+ cx25821_set_gpiopin_direction(dev, pin_number, 0);
+
+ 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);
+ msleep(20);
+ break;
+ }
+
+}
diff --git a/drivers/media/pci/cx25821/cx25821-i2c.c b/drivers/media/pci/cx25821/cx25821-i2c.c
new file mode 100644
index 000000000..0ef4cd652
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-i2c.c
@@ -0,0 +1,405 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * 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
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include "cx25821.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;
+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)
+ pr_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)
+ pr_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;
+}
+
+
+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 const struct i2c_algorithm cx25821_i2c_algo_template = {
+ .master_xfer = i2c_xfer,
+ .functionality = cx25821_functionality,
+#ifdef NEED_ALGO_CONTROL
+ .algo_control = dummy_algo_control,
+#endif
+};
+
+static const struct i2c_adapter cx25821_i2c_adap_template = {
+ .name = "cx25821",
+ .owner = THIS_MODULE,
+ .algo = &cx25821_i2c_algo_template,
+};
+
+static const struct i2c_client cx25821_i2c_client_template = {
+ .name = "cx25821 internal",
+};
+
+/* init + register i2c adapter */
+int cx25821_i2c_register(struct cx25821_i2c *bus)
+{
+ struct cx25821_dev *dev = bus->dev;
+
+ dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
+
+ bus->i2c_adap = cx25821_i2c_adap_template;
+ bus->i2c_client = cx25821_i2c_client_template;
+ bus->i2c_adap.dev.parent = &dev->pci->dev;
+
+ strscpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name));
+
+ bus->i2c_adap.algo_data = bus;
+ i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
+ i2c_add_adapter(&bus->i2c_adap);
+
+ bus->i2c_client.adapter = &bus->i2c_adap;
+
+ /* 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;
+}
+
+#if 0 /* Currently unused */
+static 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);
+}
+#endif
+
+int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value)
+{
+ struct i2c_client *client = &bus->i2c_client;
+ 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;
+
+ 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/media/pci/cx25821/cx25821-medusa-defines.h b/drivers/media/pci/cx25821/cx25821-medusa-defines.h
new file mode 100644
index 000000000..20c93855f
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-medusa-defines.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ */
+
+#ifndef _MEDUSA_DEF_H_
+#define _MEDUSA_DEF_H_
+
+/* Video decoder that we supported */
+#define VDEC_A 0
+#define VDEC_B 1
+#define VDEC_C 2
+#define VDEC_D 3
+#define VDEC_E 4
+#define VDEC_F 5
+#define VDEC_G 6
+#define VDEC_H 7
+
+/* end of display sequence */
+#define END_OF_SEQ 0xF;
+
+/* registry string size */
+#define MAX_REGISTRY_SZ 40;
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-medusa-reg.h b/drivers/media/pci/cx25821/cx25821-medusa-reg.h
new file mode 100644
index 000000000..117507e13
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-medusa-reg.h
@@ -0,0 +1,441 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ */
+
+#ifndef __MEDUSA_REGISTERS__
+#define __MEDUSA_REGISTERS__
+
+/* Serial Slave Registers */
+#define HOST_REGISTER1 0x0000
+#define HOST_REGISTER2 0x0001
+
+/* Chip Configuration Registers */
+#define CHIP_CTRL 0x0100
+#define AFE_AB_CTRL 0x0104
+#define AFE_CD_CTRL 0x0108
+#define AFE_EF_CTRL 0x010C
+#define AFE_GH_CTRL 0x0110
+#define DENC_AB_CTRL 0x0114
+#define BYP_AB_CTRL 0x0118
+#define MON_A_CTRL 0x011C
+#define DISP_SEQ_A 0x0120
+#define DISP_SEQ_B 0x0124
+#define DISP_AB_CNT 0x0128
+#define DISP_CD_CNT 0x012C
+#define DISP_EF_CNT 0x0130
+#define DISP_GH_CNT 0x0134
+#define DISP_IJ_CNT 0x0138
+#define PIN_OE_CTRL 0x013C
+#define PIN_SPD_CTRL 0x0140
+#define PIN_SPD_CTRL2 0x0144
+#define IRQ_STAT_CTRL 0x0148
+#define POWER_CTRL_AB 0x014C
+#define POWER_CTRL_CD 0x0150
+#define POWER_CTRL_EF 0x0154
+#define POWER_CTRL_GH 0x0158
+#define TUNE_CTRL 0x015C
+#define BIAS_CTRL 0x0160
+#define AFE_AB_DIAG_CTRL 0x0164
+#define AFE_CD_DIAG_CTRL 0x0168
+#define AFE_EF_DIAG_CTRL 0x016C
+#define AFE_GH_DIAG_CTRL 0x0170
+#define PLL_AB_DIAG_CTRL 0x0174
+#define PLL_CD_DIAG_CTRL 0x0178
+#define PLL_EF_DIAG_CTRL 0x017C
+#define PLL_GH_DIAG_CTRL 0x0180
+#define TEST_CTRL 0x0184
+#define BIST_STAT 0x0188
+#define BIST_STAT2 0x018C
+#define BIST_VID_PLL_AB_STAT 0x0190
+#define BIST_VID_PLL_CD_STAT 0x0194
+#define BIST_VID_PLL_EF_STAT 0x0198
+#define BIST_VID_PLL_GH_STAT 0x019C
+#define DLL_DIAG_CTRL 0x01A0
+#define DEV_CH_ID_CTRL 0x01A4
+#define ABIST_CTRL_STATUS 0x01A8
+#define ABIST_FREQ 0x01AC
+#define ABIST_GOERT_SHIFT 0x01B0
+#define ABIST_COEF12 0x01B4
+#define ABIST_COEF34 0x01B8
+#define ABIST_COEF56 0x01BC
+#define ABIST_COEF7_SNR 0x01C0
+#define ABIST_ADC_CAL 0x01C4
+#define ABIST_BIN1_VGA0 0x01C8
+#define ABIST_BIN2_VGA1 0x01CC
+#define ABIST_BIN3_VGA2 0x01D0
+#define ABIST_BIN4_VGA3 0x01D4
+#define ABIST_BIN5_VGA4 0x01D8
+#define ABIST_BIN6_VGA5 0x01DC
+#define ABIST_BIN7_VGA6 0x01E0
+#define ABIST_CLAMP_A 0x01E4
+#define ABIST_CLAMP_B 0x01E8
+#define ABIST_CLAMP_C 0x01EC
+#define ABIST_CLAMP_D 0x01F0
+#define ABIST_CLAMP_E 0x01F4
+#define ABIST_CLAMP_F 0x01F8
+
+/* Digital Video Encoder A Registers */
+#define DENC_A_REG_1 0x0200
+#define DENC_A_REG_2 0x0204
+#define DENC_A_REG_3 0x0208
+#define DENC_A_REG_4 0x020C
+#define DENC_A_REG_5 0x0210
+#define DENC_A_REG_6 0x0214
+#define DENC_A_REG_7 0x0218
+#define DENC_A_REG_8 0x021C
+
+/* Digital Video Encoder B Registers */
+#define DENC_B_REG_1 0x0300
+#define DENC_B_REG_2 0x0304
+#define DENC_B_REG_3 0x0308
+#define DENC_B_REG_4 0x030C
+#define DENC_B_REG_5 0x0310
+#define DENC_B_REG_6 0x0314
+#define DENC_B_REG_7 0x0318
+#define DENC_B_REG_8 0x031C
+
+/* Video Decoder A Registers */
+#define MODE_CTRL 0x1000
+#define OUT_CTRL1 0x1004
+#define OUT_CTRL_NS 0x1008
+#define GEN_STAT 0x100C
+#define INT_STAT_MASK 0x1010
+#define LUMA_CTRL 0x1014
+#define CHROMA_CTRL 0x1018
+#define CRUSH_CTRL 0x101C
+#define HORIZ_TIM_CTRL 0x1020
+#define VERT_TIM_CTRL 0x1024
+#define MISC_TIM_CTRL 0x1028
+#define FIELD_COUNT 0x102C
+#define HSCALE_CTRL 0x1030
+#define VSCALE_CTRL 0x1034
+#define MAN_VGA_CTRL 0x1038
+#define MAN_AGC_CTRL 0x103C
+#define DFE_CTRL1 0x1040
+#define DFE_CTRL2 0x1044
+#define DFE_CTRL3 0x1048
+#define PLL_CTRL 0x104C
+#define PLL_CTRL_FAST 0x1050
+#define HTL_CTRL 0x1054
+#define SRC_CFG 0x1058
+#define SC_STEP_SIZE 0x105C
+#define SC_CONVERGE_CTRL 0x1060
+#define SC_LOOP_CTRL 0x1064
+#define COMB_2D_HFS_CFG 0x1068
+#define COMB_2D_HFD_CFG 0x106C
+#define COMB_2D_LF_CFG 0x1070
+#define COMB_2D_BLEND 0x1074
+#define COMB_MISC_CTRL 0x1078
+#define COMB_FLAT_THRESH_CTRL 0x107C
+#define COMB_TEST 0x1080
+#define BP_MISC_CTRL 0x1084
+#define VCR_DET_CTRL 0x1088
+#define NOISE_DET_CTRL 0x108C
+#define COMB_FLAT_NOISE_CTRL 0x1090
+#define VERSION 0x11F8
+#define SOFT_RST_CTRL 0x11FC
+
+/* Video Decoder B Registers */
+#define VDEC_B_MODE_CTRL 0x1200
+#define VDEC_B_OUT_CTRL1 0x1204
+#define VDEC_B_OUT_CTRL_NS 0x1208
+#define VDEC_B_GEN_STAT 0x120C
+#define VDEC_B_INT_STAT_MASK 0x1210
+#define VDEC_B_LUMA_CTRL 0x1214
+#define VDEC_B_CHROMA_CTRL 0x1218
+#define VDEC_B_CRUSH_CTRL 0x121C
+#define VDEC_B_HORIZ_TIM_CTRL 0x1220
+#define VDEC_B_VERT_TIM_CTRL 0x1224
+#define VDEC_B_MISC_TIM_CTRL 0x1228
+#define VDEC_B_FIELD_COUNT 0x122C
+#define VDEC_B_HSCALE_CTRL 0x1230
+#define VDEC_B_VSCALE_CTRL 0x1234
+#define VDEC_B_MAN_VGA_CTRL 0x1238
+#define VDEC_B_MAN_AGC_CTRL 0x123C
+#define VDEC_B_DFE_CTRL1 0x1240
+#define VDEC_B_DFE_CTRL2 0x1244
+#define VDEC_B_DFE_CTRL3 0x1248
+#define VDEC_B_PLL_CTRL 0x124C
+#define VDEC_B_PLL_CTRL_FAST 0x1250
+#define VDEC_B_HTL_CTRL 0x1254
+#define VDEC_B_SRC_CFG 0x1258
+#define VDEC_B_SC_STEP_SIZE 0x125C
+#define VDEC_B_SC_CONVERGE_CTRL 0x1260
+#define VDEC_B_SC_LOOP_CTRL 0x1264
+#define VDEC_B_COMB_2D_HFS_CFG 0x1268
+#define VDEC_B_COMB_2D_HFD_CFG 0x126C
+#define VDEC_B_COMB_2D_LF_CFG 0x1270
+#define VDEC_B_COMB_2D_BLEND 0x1274
+#define VDEC_B_COMB_MISC_CTRL 0x1278
+#define VDEC_B_COMB_FLAT_THRESH_CTRL 0x127C
+#define VDEC_B_COMB_TEST 0x1280
+#define VDEC_B_BP_MISC_CTRL 0x1284
+#define VDEC_B_VCR_DET_CTRL 0x1288
+#define VDEC_B_NOISE_DET_CTRL 0x128C
+#define VDEC_B_COMB_FLAT_NOISE_CTRL 0x1290
+#define VDEC_B_VERSION 0x13F8
+#define VDEC_B_SOFT_RST_CTRL 0x13FC
+
+/* Video Decoder C Registers */
+#define VDEC_C_MODE_CTRL 0x1400
+#define VDEC_C_OUT_CTRL1 0x1404
+#define VDEC_C_OUT_CTRL_NS 0x1408
+#define VDEC_C_GEN_STAT 0x140C
+#define VDEC_C_INT_STAT_MASK 0x1410
+#define VDEC_C_LUMA_CTRL 0x1414
+#define VDEC_C_CHROMA_CTRL 0x1418
+#define VDEC_C_CRUSH_CTRL 0x141C
+#define VDEC_C_HORIZ_TIM_CTRL 0x1420
+#define VDEC_C_VERT_TIM_CTRL 0x1424
+#define VDEC_C_MISC_TIM_CTRL 0x1428
+#define VDEC_C_FIELD_COUNT 0x142C
+#define VDEC_C_HSCALE_CTRL 0x1430
+#define VDEC_C_VSCALE_CTRL 0x1434
+#define VDEC_C_MAN_VGA_CTRL 0x1438
+#define VDEC_C_MAN_AGC_CTRL 0x143C
+#define VDEC_C_DFE_CTRL1 0x1440
+#define VDEC_C_DFE_CTRL2 0x1444
+#define VDEC_C_DFE_CTRL3 0x1448
+#define VDEC_C_PLL_CTRL 0x144C
+#define VDEC_C_PLL_CTRL_FAST 0x1450
+#define VDEC_C_HTL_CTRL 0x1454
+#define VDEC_C_SRC_CFG 0x1458
+#define VDEC_C_SC_STEP_SIZE 0x145C
+#define VDEC_C_SC_CONVERGE_CTRL 0x1460
+#define VDEC_C_SC_LOOP_CTRL 0x1464
+#define VDEC_C_COMB_2D_HFS_CFG 0x1468
+#define VDEC_C_COMB_2D_HFD_CFG 0x146C
+#define VDEC_C_COMB_2D_LF_CFG 0x1470
+#define VDEC_C_COMB_2D_BLEND 0x1474
+#define VDEC_C_COMB_MISC_CTRL 0x1478
+#define VDEC_C_COMB_FLAT_THRESH_CTRL 0x147C
+#define VDEC_C_COMB_TEST 0x1480
+#define VDEC_C_BP_MISC_CTRL 0x1484
+#define VDEC_C_VCR_DET_CTRL 0x1488
+#define VDEC_C_NOISE_DET_CTRL 0x148C
+#define VDEC_C_COMB_FLAT_NOISE_CTRL 0x1490
+#define VDEC_C_VERSION 0x15F8
+#define VDEC_C_SOFT_RST_CTRL 0x15FC
+
+/* Video Decoder D Registers */
+#define VDEC_D_MODE_CTRL 0x1600
+#define VDEC_D_OUT_CTRL1 0x1604
+#define VDEC_D_OUT_CTRL_NS 0x1608
+#define VDEC_D_GEN_STAT 0x160C
+#define VDEC_D_INT_STAT_MASK 0x1610
+#define VDEC_D_LUMA_CTRL 0x1614
+#define VDEC_D_CHROMA_CTRL 0x1618
+#define VDEC_D_CRUSH_CTRL 0x161C
+#define VDEC_D_HORIZ_TIM_CTRL 0x1620
+#define VDEC_D_VERT_TIM_CTRL 0x1624
+#define VDEC_D_MISC_TIM_CTRL 0x1628
+#define VDEC_D_FIELD_COUNT 0x162C
+#define VDEC_D_HSCALE_CTRL 0x1630
+#define VDEC_D_VSCALE_CTRL 0x1634
+#define VDEC_D_MAN_VGA_CTRL 0x1638
+#define VDEC_D_MAN_AGC_CTRL 0x163C
+#define VDEC_D_DFE_CTRL1 0x1640
+#define VDEC_D_DFE_CTRL2 0x1644
+#define VDEC_D_DFE_CTRL3 0x1648
+#define VDEC_D_PLL_CTRL 0x164C
+#define VDEC_D_PLL_CTRL_FAST 0x1650
+#define VDEC_D_HTL_CTRL 0x1654
+#define VDEC_D_SRC_CFG 0x1658
+#define VDEC_D_SC_STEP_SIZE 0x165C
+#define VDEC_D_SC_CONVERGE_CTRL 0x1660
+#define VDEC_D_SC_LOOP_CTRL 0x1664
+#define VDEC_D_COMB_2D_HFS_CFG 0x1668
+#define VDEC_D_COMB_2D_HFD_CFG 0x166C
+#define VDEC_D_COMB_2D_LF_CFG 0x1670
+#define VDEC_D_COMB_2D_BLEND 0x1674
+#define VDEC_D_COMB_MISC_CTRL 0x1678
+#define VDEC_D_COMB_FLAT_THRESH_CTRL 0x167C
+#define VDEC_D_COMB_TEST 0x1680
+#define VDEC_D_BP_MISC_CTRL 0x1684
+#define VDEC_D_VCR_DET_CTRL 0x1688
+#define VDEC_D_NOISE_DET_CTRL 0x168C
+#define VDEC_D_COMB_FLAT_NOISE_CTRL 0x1690
+#define VDEC_D_VERSION 0x17F8
+#define VDEC_D_SOFT_RST_CTRL 0x17FC
+
+/* Video Decoder E Registers */
+#define VDEC_E_MODE_CTRL 0x1800
+#define VDEC_E_OUT_CTRL1 0x1804
+#define VDEC_E_OUT_CTRL_NS 0x1808
+#define VDEC_E_GEN_STAT 0x180C
+#define VDEC_E_INT_STAT_MASK 0x1810
+#define VDEC_E_LUMA_CTRL 0x1814
+#define VDEC_E_CHROMA_CTRL 0x1818
+#define VDEC_E_CRUSH_CTRL 0x181C
+#define VDEC_E_HORIZ_TIM_CTRL 0x1820
+#define VDEC_E_VERT_TIM_CTRL 0x1824
+#define VDEC_E_MISC_TIM_CTRL 0x1828
+#define VDEC_E_FIELD_COUNT 0x182C
+#define VDEC_E_HSCALE_CTRL 0x1830
+#define VDEC_E_VSCALE_CTRL 0x1834
+#define VDEC_E_MAN_VGA_CTRL 0x1838
+#define VDEC_E_MAN_AGC_CTRL 0x183C
+#define VDEC_E_DFE_CTRL1 0x1840
+#define VDEC_E_DFE_CTRL2 0x1844
+#define VDEC_E_DFE_CTRL3 0x1848
+#define VDEC_E_PLL_CTRL 0x184C
+#define VDEC_E_PLL_CTRL_FAST 0x1850
+#define VDEC_E_HTL_CTRL 0x1854
+#define VDEC_E_SRC_CFG 0x1858
+#define VDEC_E_SC_STEP_SIZE 0x185C
+#define VDEC_E_SC_CONVERGE_CTRL 0x1860
+#define VDEC_E_SC_LOOP_CTRL 0x1864
+#define VDEC_E_COMB_2D_HFS_CFG 0x1868
+#define VDEC_E_COMB_2D_HFD_CFG 0x186C
+#define VDEC_E_COMB_2D_LF_CFG 0x1870
+#define VDEC_E_COMB_2D_BLEND 0x1874
+#define VDEC_E_COMB_MISC_CTRL 0x1878
+#define VDEC_E_COMB_FLAT_THRESH_CTRL 0x187C
+#define VDEC_E_COMB_TEST 0x1880
+#define VDEC_E_BP_MISC_CTRL 0x1884
+#define VDEC_E_VCR_DET_CTRL 0x1888
+#define VDEC_E_NOISE_DET_CTRL 0x188C
+#define VDEC_E_COMB_FLAT_NOISE_CTRL 0x1890
+#define VDEC_E_VERSION 0x19F8
+#define VDEC_E_SOFT_RST_CTRL 0x19FC
+
+/* Video Decoder F Registers */
+#define VDEC_F_MODE_CTRL 0x1A00
+#define VDEC_F_OUT_CTRL1 0x1A04
+#define VDEC_F_OUT_CTRL_NS 0x1A08
+#define VDEC_F_GEN_STAT 0x1A0C
+#define VDEC_F_INT_STAT_MASK 0x1A10
+#define VDEC_F_LUMA_CTRL 0x1A14
+#define VDEC_F_CHROMA_CTRL 0x1A18
+#define VDEC_F_CRUSH_CTRL 0x1A1C
+#define VDEC_F_HORIZ_TIM_CTRL 0x1A20
+#define VDEC_F_VERT_TIM_CTRL 0x1A24
+#define VDEC_F_MISC_TIM_CTRL 0x1A28
+#define VDEC_F_FIELD_COUNT 0x1A2C
+#define VDEC_F_HSCALE_CTRL 0x1A30
+#define VDEC_F_VSCALE_CTRL 0x1A34
+#define VDEC_F_MAN_VGA_CTRL 0x1A38
+#define VDEC_F_MAN_AGC_CTRL 0x1A3C
+#define VDEC_F_DFE_CTRL1 0x1A40
+#define VDEC_F_DFE_CTRL2 0x1A44
+#define VDEC_F_DFE_CTRL3 0x1A48
+#define VDEC_F_PLL_CTRL 0x1A4C
+#define VDEC_F_PLL_CTRL_FAST 0x1A50
+#define VDEC_F_HTL_CTRL 0x1A54
+#define VDEC_F_SRC_CFG 0x1A58
+#define VDEC_F_SC_STEP_SIZE 0x1A5C
+#define VDEC_F_SC_CONVERGE_CTRL 0x1A60
+#define VDEC_F_SC_LOOP_CTRL 0x1A64
+#define VDEC_F_COMB_2D_HFS_CFG 0x1A68
+#define VDEC_F_COMB_2D_HFD_CFG 0x1A6C
+#define VDEC_F_COMB_2D_LF_CFG 0x1A70
+#define VDEC_F_COMB_2D_BLEND 0x1A74
+#define VDEC_F_COMB_MISC_CTRL 0x1A78
+#define VDEC_F_COMB_FLAT_THRESH_CTRL 0x1A7C
+#define VDEC_F_COMB_TEST 0x1A80
+#define VDEC_F_BP_MISC_CTRL 0x1A84
+#define VDEC_F_VCR_DET_CTRL 0x1A88
+#define VDEC_F_NOISE_DET_CTRL 0x1A8C
+#define VDEC_F_COMB_FLAT_NOISE_CTRL 0x1A90
+#define VDEC_F_VERSION 0x1BF8
+#define VDEC_F_SOFT_RST_CTRL 0x1BFC
+
+/* Video Decoder G Registers */
+#define VDEC_G_MODE_CTRL 0x1C00
+#define VDEC_G_OUT_CTRL1 0x1C04
+#define VDEC_G_OUT_CTRL_NS 0x1C08
+#define VDEC_G_GEN_STAT 0x1C0C
+#define VDEC_G_INT_STAT_MASK 0x1C10
+#define VDEC_G_LUMA_CTRL 0x1C14
+#define VDEC_G_CHROMA_CTRL 0x1C18
+#define VDEC_G_CRUSH_CTRL 0x1C1C
+#define VDEC_G_HORIZ_TIM_CTRL 0x1C20
+#define VDEC_G_VERT_TIM_CTRL 0x1C24
+#define VDEC_G_MISC_TIM_CTRL 0x1C28
+#define VDEC_G_FIELD_COUNT 0x1C2C
+#define VDEC_G_HSCALE_CTRL 0x1C30
+#define VDEC_G_VSCALE_CTRL 0x1C34
+#define VDEC_G_MAN_VGA_CTRL 0x1C38
+#define VDEC_G_MAN_AGC_CTRL 0x1C3C
+#define VDEC_G_DFE_CTRL1 0x1C40
+#define VDEC_G_DFE_CTRL2 0x1C44
+#define VDEC_G_DFE_CTRL3 0x1C48
+#define VDEC_G_PLL_CTRL 0x1C4C
+#define VDEC_G_PLL_CTRL_FAST 0x1C50
+#define VDEC_G_HTL_CTRL 0x1C54
+#define VDEC_G_SRC_CFG 0x1C58
+#define VDEC_G_SC_STEP_SIZE 0x1C5C
+#define VDEC_G_SC_CONVERGE_CTRL 0x1C60
+#define VDEC_G_SC_LOOP_CTRL 0x1C64
+#define VDEC_G_COMB_2D_HFS_CFG 0x1C68
+#define VDEC_G_COMB_2D_HFD_CFG 0x1C6C
+#define VDEC_G_COMB_2D_LF_CFG 0x1C70
+#define VDEC_G_COMB_2D_BLEND 0x1C74
+#define VDEC_G_COMB_MISC_CTRL 0x1C78
+#define VDEC_G_COMB_FLAT_THRESH_CTRL 0x1C7C
+#define VDEC_G_COMB_TEST 0x1C80
+#define VDEC_G_BP_MISC_CTRL 0x1C84
+#define VDEC_G_VCR_DET_CTRL 0x1C88
+#define VDEC_G_NOISE_DET_CTRL 0x1C8C
+#define VDEC_G_COMB_FLAT_NOISE_CTRL 0x1C90
+#define VDEC_G_VERSION 0x1DF8
+#define VDEC_G_SOFT_RST_CTRL 0x1DFC
+
+/* Video Decoder H Registers */
+#define VDEC_H_MODE_CTRL 0x1E00
+#define VDEC_H_OUT_CTRL1 0x1E04
+#define VDEC_H_OUT_CTRL_NS 0x1E08
+#define VDEC_H_GEN_STAT 0x1E0C
+#define VDEC_H_INT_STAT_MASK 0x1E1E
+#define VDEC_H_LUMA_CTRL 0x1E14
+#define VDEC_H_CHROMA_CTRL 0x1E18
+#define VDEC_H_CRUSH_CTRL 0x1E1C
+#define VDEC_H_HORIZ_TIM_CTRL 0x1E20
+#define VDEC_H_VERT_TIM_CTRL 0x1E24
+#define VDEC_H_MISC_TIM_CTRL 0x1E28
+#define VDEC_H_FIELD_COUNT 0x1E2C
+#define VDEC_H_HSCALE_CTRL 0x1E30
+#define VDEC_H_VSCALE_CTRL 0x1E34
+#define VDEC_H_MAN_VGA_CTRL 0x1E38
+#define VDEC_H_MAN_AGC_CTRL 0x1E3C
+#define VDEC_H_DFE_CTRL1 0x1E40
+#define VDEC_H_DFE_CTRL2 0x1E44
+#define VDEC_H_DFE_CTRL3 0x1E48
+#define VDEC_H_PLL_CTRL 0x1E4C
+#define VDEC_H_PLL_CTRL_FAST 0x1E50
+#define VDEC_H_HTL_CTRL 0x1E54
+#define VDEC_H_SRC_CFG 0x1E58
+#define VDEC_H_SC_STEP_SIZE 0x1E5C
+#define VDEC_H_SC_CONVERGE_CTRL 0x1E60
+#define VDEC_H_SC_LOOP_CTRL 0x1E64
+#define VDEC_H_COMB_2D_HFS_CFG 0x1E68
+#define VDEC_H_COMB_2D_HFD_CFG 0x1E6C
+#define VDEC_H_COMB_2D_LF_CFG 0x1E70
+#define VDEC_H_COMB_2D_BLEND 0x1E74
+#define VDEC_H_COMB_MISC_CTRL 0x1E78
+#define VDEC_H_COMB_FLAT_THRESH_CTRL 0x1E7C
+#define VDEC_H_COMB_TEST 0x1E80
+#define VDEC_H_BP_MISC_CTRL 0x1E84
+#define VDEC_H_VCR_DET_CTRL 0x1E88
+#define VDEC_H_NOISE_DET_CTRL 0x1E8C
+#define VDEC_H_COMB_FLAT_NOISE_CTRL 0x1E90
+#define VDEC_H_VERSION 0x1FF8
+#define VDEC_H_SOFT_RST_CTRL 0x1FFC
+
+/*****************************************************************************/
+/* LUMA_CTRL register fields */
+#define VDEC_A_BRITE_CTRL 0x1014
+#define VDEC_A_CNTRST_CTRL 0x1015
+#define VDEC_A_PEAK_SEL 0x1016
+
+/*****************************************************************************/
+/* CHROMA_CTRL register fields */
+#define VDEC_A_USAT_CTRL 0x1018
+#define VDEC_A_VSAT_CTRL 0x1019
+#define VDEC_A_HUE_CTRL 0x101A
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-medusa-video.c b/drivers/media/pci/cx25821/cx25821-medusa-video.c
new file mode 100644
index 000000000..f0a1ac77f
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-medusa-video.c
@@ -0,0 +1,731 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#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)
+{
+ 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 */
+ 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 */
+ 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;
+
+ 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;
+ /* enable the fast locking mode bit[16] */
+ value |= 0x10001;
+ 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);
+ /* disable special play detection */
+ value = setBitAtPos(value, 14);
+ 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 */
+ /* 0 - 720 */
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);
+ /* 0 - 480 */
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);
+
+ /* 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);
+
+ 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;
+
+ 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;
+ /* enable the fast locking mode bit[16] */
+ value |= 0x10004;
+ 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);
+ /* disable special play detection */
+ value = setBitAtPos(value, 14);
+ 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 */
+ /* 0 - 720 */
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);
+ /* 0 - 576 */
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);
+
+ /* 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);
+
+ return ret_val;
+}
+
+int medusa_set_videostandard(struct cx25821_dev *dev)
+{
+ int status = 0;
+ 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;
+ u32 hscale = 0x0;
+ u32 vscale = 0x0;
+ const int MAX_WIDTH = 720;
+
+ /* validate the width */
+ if (width > MAX_WIDTH) {
+ pr_info("%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 = dev->_max_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 */
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ HSCALE_CTRL + (0x200 * decoder), hscale);
+ cx25821_i2c_write(&dev->i2c_bus[0],
+ VSCALE_CTRL + (0x200 * decoder), vscale);
+ }
+}
+
+static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder,
+ int duration)
+{
+ u32 fld_cnt = 0;
+ u32 tmp = 0;
+ u32 disp_cnt_reg = DISP_AB_CNT;
+
+ /* no support */
+ if (decoder < VDEC_A || decoder > VDEC_H) {
+ 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;
+ }
+
+ /* 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;
+ }
+
+ cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt);
+}
+
+/* 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;
+
+ if ((brightness > VIDEO_PROCAMP_MAX) ||
+ (brightness < VIDEO_PROCAMP_MIN)) {
+ 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);
+ 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;
+
+ if ((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) {
+ 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);
+
+ 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;
+
+ if ((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) {
+ 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);
+
+ 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;
+
+ if ((saturation > VIDEO_PROCAMP_MAX) ||
+ (saturation < VIDEO_PROCAMP_MIN)) {
+ 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);
+
+ 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;
+
+ /* 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)
+ goto error;
+
+ /* 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)
+ goto error;
+
+ /*
+ * FIXME: due to a coding bug the duration was always 0. It's
+ * likely that it really should be something else, but due to the
+ * lack of documentation I have no idea what it should be. For
+ * now just fill in 0 as the duration.
+ */
+ for (i = 0; i < dev->_max_num_decoders; i++)
+ medusa_set_decoderduration(dev, i, 0);
+
+ /* 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)
+ goto error;
+
+ /* 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)
+ goto error;
+
+ /* 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)
+ goto error;
+
+ /* 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 (dev->_max_num_decoders == MAX_DECODERS) {
+ /*
+ * Note: The octal board does not support control pins(bit16-19)
+ * These bits are ignored in the octal board.
+ *
+ * disable VDEC A-C port, default to Mobilygen Interface
+ */
+ value |= 0x010001F8;
+ } else {
+ /* disable VDEC A-C port, default to Mobilygen Interface */
+ value |= 0x010F0108;
+ }
+
+ value |= 7;
+ ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value);
+
+ if (ret_val < 0)
+ goto error;
+
+ ret_val = medusa_set_videostandard(dev);
+
+error:
+ return ret_val;
+}
diff --git a/drivers/media/pci/cx25821/cx25821-medusa-video.h b/drivers/media/pci/cx25821/cx25821-medusa-video.h
new file mode 100644
index 000000000..37f6f49cd
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-medusa-video.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ */
+
+#ifndef _MEDUSA_VIDEO_H
+#define _MEDUSA_VIDEO_H
+
+#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
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-reg.h b/drivers/media/pci/cx25821/cx25821-reg.h
new file mode 100644
index 000000000..83ee798ab
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-reg.h
@@ -0,0 +1,1578 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ */
+
+#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
+
+/*****************************************************************************
+* 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 */
+
+/* ***************************************************************************** */
+#define VID_C_INT_MSK 0x040040 /* Video C interrupt mask */
+#define VID_C_INT_STAT 0x040044 /* Video C interrupt status */
+#define VID_C_INT_MSTAT 0x040048 /* Video C interrupt masked status */
+#define VID_C_INT_SSTAT 0x04004C /* Video C interrupt set status */
+
+/* ***************************************************************************** */
+#define VID_D_INT_MSK 0x040050 /* Video D interrupt mask */
+#define VID_D_INT_STAT 0x040054 /* Video D interrupt status */
+#define VID_D_INT_MSTAT 0x040058 /* Video D interrupt masked status */
+#define VID_D_INT_SSTAT 0x04005C /* Video D interrupt set status */
+
+/* ***************************************************************************** */
+#define VID_E_INT_MSK 0x040060 /* Video E interrupt mask */
+#define VID_E_INT_STAT 0x040064 /* Video E interrupt status */
+#define VID_E_INT_MSTAT 0x040068 /* Video E interrupt masked status */
+#define VID_E_INT_SSTAT 0x04006C /* Video E interrupt set status */
+
+/* ***************************************************************************** */
+#define VID_F_INT_MSK 0x040070 /* Video F interrupt mask */
+#define VID_F_INT_STAT 0x040074 /* Video F interrupt status */
+#define VID_F_INT_MSTAT 0x040078 /* Video F interrupt masked status */
+#define VID_F_INT_SSTAT 0x04007C /* Video F interrupt set status */
+
+/* ***************************************************************************** */
+#define VID_G_INT_MSK 0x040080 /* Video G interrupt mask */
+#define VID_G_INT_STAT 0x040084 /* Video G interrupt status */
+#define VID_G_INT_MSTAT 0x040088 /* Video G interrupt masked status */
+#define VID_G_INT_SSTAT 0x04008C /* Video G interrupt set status */
+
+/* ***************************************************************************** */
+#define VID_H_INT_MSK 0x040090 /* Video H interrupt mask */
+#define VID_H_INT_STAT 0x040094 /* Video H interrupt status */
+#define VID_H_INT_MSTAT 0x040098 /* Video H interrupt masked status */
+#define VID_H_INT_SSTAT 0x04009C /* Video H interrupt set status */
+
+/* ***************************************************************************** */
+#define VID_I_INT_MSK 0x0400A0 /* Video I interrupt mask */
+#define VID_I_INT_STAT 0x0400A4 /* Video I interrupt status */
+#define VID_I_INT_MSTAT 0x0400A8 /* Video I interrupt masked status */
+#define VID_I_INT_SSTAT 0x0400AC /* Video I interrupt set status */
+
+/* ***************************************************************************** */
+#define VID_J_INT_MSK 0x0400B0 /* Video J interrupt mask */
+#define VID_J_INT_STAT 0x0400B4 /* Video J interrupt status */
+#define VID_J_INT_MSTAT 0x0400B8 /* Video J interrupt masked status */
+#define VID_J_INT_SSTAT 0x0400BC /* Video J interrupt set status */
+
+#define FLD_VID_SRC_OPC_ERR 0x00020000
+#define FLD_VID_DST_OPC_ERR 0x00010000
+#define FLD_VID_SRC_SYNC 0x00002000
+#define FLD_VID_DST_SYNC 0x00001000
+#define FLD_VID_SRC_UF 0x00000200
+#define FLD_VID_DST_OF 0x00000100
+#define FLD_VID_SRC_RISC2 0x00000020
+#define FLD_VID_DST_RISC2 0x00000010
+#define FLD_VID_SRC_RISC1 0x00000002
+#define FLD_VID_DST_RISC1 0x00000001
+#define FLD_VID_SRC_ERRORS (FLD_VID_SRC_OPC_ERR | FLD_VID_SRC_SYNC | FLD_VID_SRC_UF)
+#define FLD_VID_DST_ERRORS (FLD_VID_DST_OPC_ERR | FLD_VID_DST_SYNC | FLD_VID_DST_OF)
+
+/* ***************************************************************************** */
+#define AUD_A_INT_MSK 0x0400C0 /* Audio Int interrupt mask */
+#define AUD_A_INT_STAT 0x0400C4 /* Audio Int interrupt status */
+#define AUD_A_INT_MSTAT 0x0400C8 /* Audio Int interrupt masked status */
+#define AUD_A_INT_SSTAT 0x0400CC /* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define AUD_B_INT_MSK 0x0400D0 /* Audio Int interrupt mask */
+#define AUD_B_INT_STAT 0x0400D4 /* Audio Int interrupt status */
+#define AUD_B_INT_MSTAT 0x0400D8 /* Audio Int interrupt masked status */
+#define AUD_B_INT_SSTAT 0x0400DC /* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define AUD_C_INT_MSK 0x0400E0 /* Audio Int interrupt mask */
+#define AUD_C_INT_STAT 0x0400E4 /* Audio Int interrupt status */
+#define AUD_C_INT_MSTAT 0x0400E8 /* Audio Int interrupt masked status */
+#define AUD_C_INT_SSTAT 0x0400EC /* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define AUD_D_INT_MSK 0x0400F0 /* Audio Int interrupt mask */
+#define AUD_D_INT_STAT 0x0400F4 /* Audio Int interrupt status */
+#define AUD_D_INT_MSTAT 0x0400F8 /* Audio Int interrupt masked status */
+#define AUD_D_INT_SSTAT 0x0400FC /* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define AUD_E_INT_MSK 0x040100 /* Audio Int interrupt mask */
+#define AUD_E_INT_STAT 0x040104 /* Audio Int interrupt status */
+#define AUD_E_INT_MSTAT 0x040108 /* Audio Int interrupt masked status */
+#define AUD_E_INT_SSTAT 0x04010C /* Audio Int interrupt set status */
+
+#define FLD_AUD_SRC_OPC_ERR 0x00020000
+#define FLD_AUD_DST_OPC_ERR 0x00010000
+#define FLD_AUD_SRC_SYNC 0x00002000
+#define FLD_AUD_DST_SYNC 0x00001000
+#define FLD_AUD_SRC_OF 0x00000200
+#define FLD_AUD_DST_OF 0x00000100
+#define FLD_AUD_SRC_RISCI2 0x00000020
+#define FLD_AUD_DST_RISCI2 0x00000010
+#define FLD_AUD_SRC_RISCI1 0x00000002
+#define FLD_AUD_DST_RISCI1 0x00000001
+
+/* ***************************************************************************** */
+#define MBIF_A_INT_MSK 0x040110 /* MBIF Int interrupt mask */
+#define MBIF_A_INT_STAT 0x040114 /* MBIF Int interrupt status */
+#define MBIF_A_INT_MSTAT 0x040118 /* MBIF Int interrupt masked status */
+#define MBIF_A_INT_SSTAT 0x04011C /* MBIF Int interrupt set status */
+
+/* ***************************************************************************** */
+#define MBIF_B_INT_MSK 0x040120 /* MBIF Int interrupt mask */
+#define MBIF_B_INT_STAT 0x040124 /* MBIF Int interrupt status */
+#define MBIF_B_INT_MSTAT 0x040128 /* MBIF Int interrupt masked status */
+#define MBIF_B_INT_SSTAT 0x04012C /* MBIF Int interrupt set status */
+
+#define FLD_MBIF_DST_OPC_ERR 0x00010000
+#define FLD_MBIF_DST_SYNC 0x00001000
+#define FLD_MBIF_DST_OF 0x00000100
+#define FLD_MBIF_DST_RISCI2 0x00000010
+#define FLD_MBIF_DST_RISCI1 0x00000001
+
+/* ***************************************************************************** */
+#define AUD_EXT_INT_MSK 0x040060 /* Audio Ext interrupt mask */
+#define AUD_EXT_INT_STAT 0x040064 /* Audio Ext interrupt status */
+#define AUD_EXT_INT_MSTAT 0x040068 /* Audio Ext interrupt masked status */
+#define AUD_EXT_INT_SSTAT 0x04006C /* Audio Ext interrupt set status */
+#define FLD_AUD_EXT_OPC_ERR 0x00010000
+#define FLD_AUD_EXT_SYNC 0x00001000
+#define FLD_AUD_EXT_OF 0x00000100
+#define FLD_AUD_EXT_RISCI2 0x00000010
+#define FLD_AUD_EXT_RISCI1 0x00000001
+
+/* ***************************************************************************** */
+#define GPIO_LO 0x110010 /* Lower of GPIO pins [31:0] */
+#define GPIO_HI 0x110014 /* Upper WORD of GPIO pins [47:31] */
+
+#define GPIO_LO_OE 0x110018 /* Lower of GPIO output enable [31:0] */
+#define GPIO_HI_OE 0x11001C /* Upper word of GPIO output enable [47:32] */
+
+#define GPIO_LO_INT_MSK 0x11003C /* GPIO interrupt mask */
+#define GPIO_LO_INT_STAT 0x110044 /* GPIO interrupt status */
+#define GPIO_LO_INT_MSTAT 0x11004C /* GPIO interrupt masked status */
+#define GPIO_LO_ISM_SNS 0x110054 /* GPIO interrupt sensitivity */
+#define GPIO_LO_ISM_POL 0x11005C /* GPIO interrupt polarity */
+
+#define GPIO_HI_INT_MSK 0x110040 /* GPIO interrupt mask */
+#define GPIO_HI_INT_STAT 0x110048 /* GPIO interrupt status */
+#define GPIO_HI_INT_MSTAT 0x110050 /* GPIO interrupt masked status */
+#define GPIO_HI_ISM_SNS 0x110058 /* GPIO interrupt sensitivity */
+#define GPIO_HI_ISM_POL 0x110060 /* GPIO interrupt polarity */
+
+#define FLD_GPIO43_INT (1 << 11)
+#define FLD_GPIO42_INT (1 << 10)
+#define FLD_GPIO41_INT (1 << 9)
+#define FLD_GPIO40_INT (1 << 8)
+
+#define FLD_GPIO9_INT (1 << 9)
+#define FLD_GPIO8_INT (1 << 8)
+#define FLD_GPIO7_INT (1 << 7)
+#define FLD_GPIO6_INT (1 << 6)
+#define FLD_GPIO5_INT (1 << 5)
+#define FLD_GPIO4_INT (1 << 4)
+#define FLD_GPIO3_INT (1 << 3)
+#define FLD_GPIO2_INT (1 << 2)
+#define FLD_GPIO1_INT (1 << 1)
+#define FLD_GPIO0_INT (1 << 0)
+
+/* ***************************************************************************** */
+#define TC_REQ 0x040090 /* Rider PCI Express traFFic class request */
+
+/* ***************************************************************************** */
+#define TC_REQ_SET 0x040094 /* Rider PCI Express traFFic class request set */
+
+/* ***************************************************************************** */
+/* Rider */
+/* ***************************************************************************** */
+
+/* PCI Compatible Header */
+/* ***************************************************************************** */
+#define RDR_CFG0 0x050000
+#define RDR_VENDOR_DEVICE_ID_CFG 0x050000
+
+/* ***************************************************************************** */
+#define RDR_CFG1 0x050004
+
+/* ***************************************************************************** */
+#define RDR_CFG2 0x050008
+
+/* ***************************************************************************** */
+#define RDR_CFG3 0x05000C
+
+/* ***************************************************************************** */
+#define RDR_CFG4 0x050010
+
+/* ***************************************************************************** */
+#define RDR_CFG5 0x050014
+
+/* ***************************************************************************** */
+#define RDR_CFG6 0x050018
+
+/* ***************************************************************************** */
+#define RDR_CFG7 0x05001C
+
+/* ***************************************************************************** */
+#define RDR_CFG8 0x050020
+
+/* ***************************************************************************** */
+#define RDR_CFG9 0x050024
+
+/* ***************************************************************************** */
+#define RDR_CFGA 0x050028
+
+/* ***************************************************************************** */
+#define RDR_CFGB 0x05002C
+#define RDR_SUSSYSTEM_ID_CFG 0x05002C
+
+/* ***************************************************************************** */
+#define RDR_CFGC 0x050030
+
+/* ***************************************************************************** */
+#define RDR_CFGD 0x050034
+
+/* ***************************************************************************** */
+#define RDR_CFGE 0x050038
+
+/* ***************************************************************************** */
+#define RDR_CFGF 0x05003C
+
+/* ***************************************************************************** */
+/* PCI-Express Capabilities */
+/* ***************************************************************************** */
+#define RDR_PECAP 0x050040
+
+/* ***************************************************************************** */
+#define RDR_PEDEVCAP 0x050044
+
+/* ***************************************************************************** */
+#define RDR_PEDEVSC 0x050048
+
+/* ***************************************************************************** */
+#define RDR_PELINKCAP 0x05004C
+
+/* ***************************************************************************** */
+#define RDR_PELINKSC 0x050050
+
+/* ***************************************************************************** */
+#define RDR_PMICAP 0x050080
+
+/* ***************************************************************************** */
+#define RDR_PMCSR 0x050084
+
+/* ***************************************************************************** */
+#define RDR_VPDCAP 0x050090
+
+/* ***************************************************************************** */
+#define RDR_VPDDATA 0x050094
+
+/* ***************************************************************************** */
+#define RDR_MSICAP 0x0500A0
+
+/* ***************************************************************************** */
+#define RDR_MSIARL 0x0500A4
+
+/* ***************************************************************************** */
+#define RDR_MSIARU 0x0500A8
+
+/* ***************************************************************************** */
+#define RDR_MSIDATA 0x0500AC
+
+/* ***************************************************************************** */
+/* PCI Express Extended Capabilities */
+/* ***************************************************************************** */
+#define RDR_AERXCAP 0x050100
+
+/* ***************************************************************************** */
+#define RDR_AERUESTA 0x050104
+
+/* ***************************************************************************** */
+#define RDR_AERUEMSK 0x050108
+
+/* ***************************************************************************** */
+#define RDR_AERUESEV 0x05010C
+
+/* ***************************************************************************** */
+#define RDR_AERCESTA 0x050110
+
+/* ***************************************************************************** */
+#define RDR_AERCEMSK 0x050114
+
+/* ***************************************************************************** */
+#define RDR_AERCC 0x050118
+
+/* ***************************************************************************** */
+#define RDR_AERHL0 0x05011C
+
+/* ***************************************************************************** */
+#define RDR_AERHL1 0x050120
+
+/* ***************************************************************************** */
+#define RDR_AERHL2 0x050124
+
+/* ***************************************************************************** */
+#define RDR_AERHL3 0x050128
+
+/* ***************************************************************************** */
+#define RDR_VCXCAP 0x050200
+
+/* ***************************************************************************** */
+#define RDR_VCCAP1 0x050204
+
+/* ***************************************************************************** */
+#define RDR_VCCAP2 0x050208
+
+/* ***************************************************************************** */
+#define RDR_VCSC 0x05020C
+
+/* ***************************************************************************** */
+#define RDR_VCR0_CAP 0x050210
+
+/* ***************************************************************************** */
+#define RDR_VCR0_CTRL 0x050214
+
+/* ***************************************************************************** */
+#define RDR_VCR0_STAT 0x050218
+
+/* ***************************************************************************** */
+#define RDR_VCR1_CAP 0x05021C
+
+/* ***************************************************************************** */
+#define RDR_VCR1_CTRL 0x050220
+
+/* ***************************************************************************** */
+#define RDR_VCR1_STAT 0x050224
+
+/* ***************************************************************************** */
+#define RDR_VCR2_CAP 0x050228
+
+/* ***************************************************************************** */
+#define RDR_VCR2_CTRL 0x05022C
+
+/* ***************************************************************************** */
+#define RDR_VCR2_STAT 0x050230
+
+/* ***************************************************************************** */
+#define RDR_VCR3_CAP 0x050234
+
+/* ***************************************************************************** */
+#define RDR_VCR3_CTRL 0x050238
+
+/* ***************************************************************************** */
+#define RDR_VCR3_STAT 0x05023C
+
+/* ***************************************************************************** */
+#define RDR_VCARB0 0x050240
+
+/* ***************************************************************************** */
+#define RDR_VCARB1 0x050244
+
+/* ***************************************************************************** */
+#define RDR_VCARB2 0x050248
+
+/* ***************************************************************************** */
+#define RDR_VCARB3 0x05024C
+
+/* ***************************************************************************** */
+#define RDR_VCARB4 0x050250
+
+/* ***************************************************************************** */
+#define RDR_VCARB5 0x050254
+
+/* ***************************************************************************** */
+#define RDR_VCARB6 0x050258
+
+/* ***************************************************************************** */
+#define RDR_VCARB7 0x05025C
+
+/* ***************************************************************************** */
+#define RDR_RDRSTAT0 0x050300
+
+/* ***************************************************************************** */
+#define RDR_RDRSTAT1 0x050304
+
+/* ***************************************************************************** */
+#define RDR_RDRCTL0 0x050308
+
+/* ***************************************************************************** */
+#define RDR_RDRCTL1 0x05030C
+
+/* ***************************************************************************** */
+/* Transaction Layer Registers */
+/* ***************************************************************************** */
+#define RDR_TLSTAT0 0x050310
+
+/* ***************************************************************************** */
+#define RDR_TLSTAT1 0x050314
+
+/* ***************************************************************************** */
+#define RDR_TLCTL0 0x050318
+#define FLD_CFG_UR_CPL_MODE 0x00000040
+#define FLD_CFG_CORR_ERR_QUITE 0x00000020
+#define FLD_CFG_RCB_CK_EN 0x00000010
+#define FLD_CFG_BNDRY_CK_EN 0x00000008
+#define FLD_CFG_BYTE_EN_CK_EN 0x00000004
+#define FLD_CFG_RELAX_ORDER_MSK 0x00000002
+#define FLD_CFG_TAG_ORDER_EN 0x00000001
+
+/* ***************************************************************************** */
+#define RDR_TLCTL1 0x05031C
+
+/* ***************************************************************************** */
+#define RDR_REQRCAL 0x050320
+
+/* ***************************************************************************** */
+#define RDR_REQRCAU 0x050324
+
+/* ***************************************************************************** */
+#define RDR_REQEPA 0x050328
+
+/* ***************************************************************************** */
+#define RDR_REQCTRL 0x05032C
+
+/* ***************************************************************************** */
+#define RDR_REQSTAT 0x050330
+
+/* ***************************************************************************** */
+#define RDR_TL_TEST 0x050334
+
+/* ***************************************************************************** */
+#define RDR_VCR01_CTL 0x050348
+
+/* ***************************************************************************** */
+#define RDR_VCR23_CTL 0x05034C
+
+/* ***************************************************************************** */
+#define RDR_RX_VCR0_FC 0x050350
+
+/* ***************************************************************************** */
+#define RDR_RX_VCR1_FC 0x050354
+
+/* ***************************************************************************** */
+#define RDR_RX_VCR2_FC 0x050358
+
+/* ***************************************************************************** */
+#define RDR_RX_VCR3_FC 0x05035C
+
+/* ***************************************************************************** */
+/* Data Link Layer Registers */
+/* ***************************************************************************** */
+#define RDR_DLLSTAT 0x050360
+
+/* ***************************************************************************** */
+#define RDR_DLLCTRL 0x050364
+
+/* ***************************************************************************** */
+#define RDR_REPLAYTO 0x050368
+
+/* ***************************************************************************** */
+#define RDR_ACKLATTO 0x05036C
+
+/* ***************************************************************************** */
+/* MAC Layer Registers */
+/* ***************************************************************************** */
+#define RDR_MACSTAT0 0x050380
+
+/* ***************************************************************************** */
+#define RDR_MACSTAT1 0x050384
+
+/* ***************************************************************************** */
+#define RDR_MACCTRL0 0x050388
+
+/* ***************************************************************************** */
+#define RDR_MACCTRL1 0x05038C
+
+/* ***************************************************************************** */
+#define RDR_MACCTRL2 0x050390
+
+/* ***************************************************************************** */
+#define RDR_MAC_LB_DATA 0x050394
+
+/* ***************************************************************************** */
+#define RDR_L0S_EXIT_LAT 0x050398
+
+/* ***************************************************************************** */
+/* DMAC */
+/* ***************************************************************************** */
+#define DMA1_PTR1 0x100000 /* DMA Current Ptr : Ch#1 */
+
+/* ***************************************************************************** */
+#define DMA2_PTR1 0x100004 /* DMA Current Ptr : Ch#2 */
+
+/* ***************************************************************************** */
+#define DMA3_PTR1 0x100008 /* DMA Current Ptr : Ch#3 */
+
+/* ***************************************************************************** */
+#define DMA4_PTR1 0x10000C /* DMA Current Ptr : Ch#4 */
+
+/* ***************************************************************************** */
+#define DMA5_PTR1 0x100010 /* DMA Current Ptr : Ch#5 */
+
+/* ***************************************************************************** */
+#define DMA6_PTR1 0x100014 /* DMA Current Ptr : Ch#6 */
+
+/* ***************************************************************************** */
+#define DMA7_PTR1 0x100018 /* DMA Current Ptr : Ch#7 */
+
+/* ***************************************************************************** */
+#define DMA8_PTR1 0x10001C /* DMA Current Ptr : Ch#8 */
+
+/* ***************************************************************************** */
+#define DMA9_PTR1 0x100020 /* DMA Current Ptr : Ch#9 */
+
+/* ***************************************************************************** */
+#define DMA10_PTR1 0x100024 /* DMA Current Ptr : Ch#10 */
+
+/* ***************************************************************************** */
+#define DMA11_PTR1 0x100028 /* DMA Current Ptr : Ch#11 */
+
+/* ***************************************************************************** */
+#define DMA12_PTR1 0x10002C /* DMA Current Ptr : Ch#12 */
+
+/* ***************************************************************************** */
+#define DMA13_PTR1 0x100030 /* DMA Current Ptr : Ch#13 */
+
+/* ***************************************************************************** */
+#define DMA14_PTR1 0x100034 /* DMA Current Ptr : Ch#14 */
+
+/* ***************************************************************************** */
+#define DMA15_PTR1 0x100038 /* DMA Current Ptr : Ch#15 */
+
+/* ***************************************************************************** */
+#define DMA16_PTR1 0x10003C /* DMA Current Ptr : Ch#16 */
+
+/* ***************************************************************************** */
+#define DMA17_PTR1 0x100040 /* DMA Current Ptr : Ch#17 */
+
+/* ***************************************************************************** */
+#define DMA18_PTR1 0x100044 /* DMA Current Ptr : Ch#18 */
+
+/* ***************************************************************************** */
+#define DMA19_PTR1 0x100048 /* DMA Current Ptr : Ch#19 */
+
+/* ***************************************************************************** */
+#define DMA20_PTR1 0x10004C /* DMA Current Ptr : Ch#20 */
+
+/* ***************************************************************************** */
+#define DMA21_PTR1 0x100050 /* DMA Current Ptr : Ch#21 */
+
+/* ***************************************************************************** */
+#define DMA22_PTR1 0x100054 /* DMA Current Ptr : Ch#22 */
+
+/* ***************************************************************************** */
+#define DMA23_PTR1 0x100058 /* DMA Current Ptr : Ch#23 */
+
+/* ***************************************************************************** */
+#define DMA24_PTR1 0x10005C /* DMA Current Ptr : Ch#24 */
+
+/* ***************************************************************************** */
+#define DMA25_PTR1 0x100060 /* DMA Current Ptr : Ch#25 */
+
+/* ***************************************************************************** */
+#define DMA26_PTR1 0x100064 /* DMA Current Ptr : Ch#26 */
+
+/* ***************************************************************************** */
+#define DMA1_PTR2 0x100080 /* DMA Tab Ptr : Ch#1 */
+
+/* ***************************************************************************** */
+#define DMA2_PTR2 0x100084 /* DMA Tab Ptr : Ch#2 */
+
+/* ***************************************************************************** */
+#define DMA3_PTR2 0x100088 /* DMA Tab Ptr : Ch#3 */
+
+/* ***************************************************************************** */
+#define DMA4_PTR2 0x10008C /* DMA Tab Ptr : Ch#4 */
+
+/* ***************************************************************************** */
+#define DMA5_PTR2 0x100090 /* DMA Tab Ptr : Ch#5 */
+
+/* ***************************************************************************** */
+#define DMA6_PTR2 0x100094 /* DMA Tab Ptr : Ch#6 */
+
+/* ***************************************************************************** */
+#define DMA7_PTR2 0x100098 /* DMA Tab Ptr : Ch#7 */
+
+/* ***************************************************************************** */
+#define DMA8_PTR2 0x10009C /* DMA Tab Ptr : Ch#8 */
+
+/* ***************************************************************************** */
+#define DMA9_PTR2 0x1000A0 /* DMA Tab Ptr : Ch#9 */
+
+/* ***************************************************************************** */
+#define DMA10_PTR2 0x1000A4 /* DMA Tab Ptr : Ch#10 */
+
+/* ***************************************************************************** */
+#define DMA11_PTR2 0x1000A8 /* DMA Tab Ptr : Ch#11 */
+
+/* ***************************************************************************** */
+#define DMA12_PTR2 0x1000AC /* DMA Tab Ptr : Ch#12 */
+
+/* ***************************************************************************** */
+#define DMA13_PTR2 0x1000B0 /* DMA Tab Ptr : Ch#13 */
+
+/* ***************************************************************************** */
+#define DMA14_PTR2 0x1000B4 /* DMA Tab Ptr : Ch#14 */
+
+/* ***************************************************************************** */
+#define DMA15_PTR2 0x1000B8 /* DMA Tab Ptr : Ch#15 */
+
+/* ***************************************************************************** */
+#define DMA16_PTR2 0x1000BC /* DMA Tab Ptr : Ch#16 */
+
+/* ***************************************************************************** */
+#define DMA17_PTR2 0x1000C0 /* DMA Tab Ptr : Ch#17 */
+
+/* ***************************************************************************** */
+#define DMA18_PTR2 0x1000C4 /* DMA Tab Ptr : Ch#18 */
+
+/* ***************************************************************************** */
+#define DMA19_PTR2 0x1000C8 /* DMA Tab Ptr : Ch#19 */
+
+/* ***************************************************************************** */
+#define DMA20_PTR2 0x1000CC /* DMA Tab Ptr : Ch#20 */
+
+/* ***************************************************************************** */
+#define DMA21_PTR2 0x1000D0 /* DMA Tab Ptr : Ch#21 */
+
+/* ***************************************************************************** */
+#define DMA22_PTR2 0x1000D4 /* DMA Tab Ptr : Ch#22 */
+
+/* ***************************************************************************** */
+#define DMA23_PTR2 0x1000D8 /* DMA Tab Ptr : Ch#23 */
+
+/* ***************************************************************************** */
+#define DMA24_PTR2 0x1000DC /* DMA Tab Ptr : Ch#24 */
+
+/* ***************************************************************************** */
+#define DMA25_PTR2 0x1000E0 /* DMA Tab Ptr : Ch#25 */
+
+/* ***************************************************************************** */
+#define DMA26_PTR2 0x1000E4 /* DMA Tab Ptr : Ch#26 */
+
+/* ***************************************************************************** */
+#define DMA1_CNT1 0x100100 /* DMA BuFFer Size : Ch#1 */
+
+/* ***************************************************************************** */
+#define DMA2_CNT1 0x100104 /* DMA BuFFer Size : Ch#2 */
+
+/* ***************************************************************************** */
+#define DMA3_CNT1 0x100108 /* DMA BuFFer Size : Ch#3 */
+
+/* ***************************************************************************** */
+#define DMA4_CNT1 0x10010C /* DMA BuFFer Size : Ch#4 */
+
+/* ***************************************************************************** */
+#define DMA5_CNT1 0x100110 /* DMA BuFFer Size : Ch#5 */
+
+/* ***************************************************************************** */
+#define DMA6_CNT1 0x100114 /* DMA BuFFer Size : Ch#6 */
+
+/* ***************************************************************************** */
+#define DMA7_CNT1 0x100118 /* DMA BuFFer Size : Ch#7 */
+
+/* ***************************************************************************** */
+#define DMA8_CNT1 0x10011C /* DMA BuFFer Size : Ch#8 */
+
+/* ***************************************************************************** */
+#define DMA9_CNT1 0x100120 /* DMA BuFFer Size : Ch#9 */
+
+/* ***************************************************************************** */
+#define DMA10_CNT1 0x100124 /* DMA BuFFer Size : Ch#10 */
+
+/* ***************************************************************************** */
+#define DMA11_CNT1 0x100128 /* DMA BuFFer Size : Ch#11 */
+
+/* ***************************************************************************** */
+#define DMA12_CNT1 0x10012C /* DMA BuFFer Size : Ch#12 */
+
+/* ***************************************************************************** */
+#define DMA13_CNT1 0x100130 /* DMA BuFFer Size : Ch#13 */
+
+/* ***************************************************************************** */
+#define DMA14_CNT1 0x100134 /* DMA BuFFer Size : Ch#14 */
+
+/* ***************************************************************************** */
+#define DMA15_CNT1 0x100138 /* DMA BuFFer Size : Ch#15 */
+
+/* ***************************************************************************** */
+#define DMA16_CNT1 0x10013C /* DMA BuFFer Size : Ch#16 */
+
+/* ***************************************************************************** */
+#define DMA17_CNT1 0x100140 /* DMA BuFFer Size : Ch#17 */
+
+/* ***************************************************************************** */
+#define DMA18_CNT1 0x100144 /* DMA BuFFer Size : Ch#18 */
+
+/* ***************************************************************************** */
+#define DMA19_CNT1 0x100148 /* DMA BuFFer Size : Ch#19 */
+
+/* ***************************************************************************** */
+#define DMA20_CNT1 0x10014C /* DMA BuFFer Size : Ch#20 */
+
+/* ***************************************************************************** */
+#define DMA21_CNT1 0x100150 /* DMA BuFFer Size : Ch#21 */
+
+/* ***************************************************************************** */
+#define DMA22_CNT1 0x100154 /* DMA BuFFer Size : Ch#22 */
+
+/* ***************************************************************************** */
+#define DMA23_CNT1 0x100158 /* DMA BuFFer Size : Ch#23 */
+
+/* ***************************************************************************** */
+#define DMA24_CNT1 0x10015C /* DMA BuFFer Size : Ch#24 */
+
+/* ***************************************************************************** */
+#define DMA25_CNT1 0x100160 /* DMA BuFFer Size : Ch#25 */
+
+/* ***************************************************************************** */
+#define DMA26_CNT1 0x100164 /* DMA BuFFer Size : Ch#26 */
+
+/* ***************************************************************************** */
+#define DMA1_CNT2 0x100180 /* DMA Table Size : Ch#1 */
+
+/* ***************************************************************************** */
+#define DMA2_CNT2 0x100184 /* DMA Table Size : Ch#2 */
+
+/* ***************************************************************************** */
+#define DMA3_CNT2 0x100188 /* DMA Table Size : Ch#3 */
+
+/* ***************************************************************************** */
+#define DMA4_CNT2 0x10018C /* DMA Table Size : Ch#4 */
+
+/* ***************************************************************************** */
+#define DMA5_CNT2 0x100190 /* DMA Table Size : Ch#5 */
+
+/* ***************************************************************************** */
+#define DMA6_CNT2 0x100194 /* DMA Table Size : Ch#6 */
+
+/* ***************************************************************************** */
+#define DMA7_CNT2 0x100198 /* DMA Table Size : Ch#7 */
+
+/* ***************************************************************************** */
+#define DMA8_CNT2 0x10019C /* DMA Table Size : Ch#8 */
+
+/* ***************************************************************************** */
+#define DMA9_CNT2 0x1001A0 /* DMA Table Size : Ch#9 */
+
+/* ***************************************************************************** */
+#define DMA10_CNT2 0x1001A4 /* DMA Table Size : Ch#10 */
+
+/* ***************************************************************************** */
+#define DMA11_CNT2 0x1001A8 /* DMA Table Size : Ch#11 */
+
+/* ***************************************************************************** */
+#define DMA12_CNT2 0x1001AC /* DMA Table Size : Ch#12 */
+
+/* ***************************************************************************** */
+#define DMA13_CNT2 0x1001B0 /* DMA Table Size : Ch#13 */
+
+/* ***************************************************************************** */
+#define DMA14_CNT2 0x1001B4 /* DMA Table Size : Ch#14 */
+
+/* ***************************************************************************** */
+#define DMA15_CNT2 0x1001B8 /* DMA Table Size : Ch#15 */
+
+/* ***************************************************************************** */
+#define DMA16_CNT2 0x1001BC /* DMA Table Size : Ch#16 */
+
+/* ***************************************************************************** */
+#define DMA17_CNT2 0x1001C0 /* DMA Table Size : Ch#17 */
+
+/* ***************************************************************************** */
+#define DMA18_CNT2 0x1001C4 /* DMA Table Size : Ch#18 */
+
+/* ***************************************************************************** */
+#define DMA19_CNT2 0x1001C8 /* DMA Table Size : Ch#19 */
+
+/* ***************************************************************************** */
+#define DMA20_CNT2 0x1001CC /* DMA Table Size : Ch#20 */
+
+/* ***************************************************************************** */
+#define DMA21_CNT2 0x1001D0 /* DMA Table Size : Ch#21 */
+
+/* ***************************************************************************** */
+#define DMA22_CNT2 0x1001D4 /* DMA Table Size : Ch#22 */
+
+/* ***************************************************************************** */
+#define DMA23_CNT2 0x1001D8 /* DMA Table Size : Ch#23 */
+
+/* ***************************************************************************** */
+#define DMA24_CNT2 0x1001DC /* DMA Table Size : Ch#24 */
+
+/* ***************************************************************************** */
+#define DMA25_CNT2 0x1001E0 /* DMA Table Size : Ch#25 */
+
+/* ***************************************************************************** */
+#define DMA26_CNT2 0x1001E4 /* DMA Table Size : Ch#26 */
+
+/* ***************************************************************************** */
+ /* ITG */
+/* ***************************************************************************** */
+#define TM_CNT_LDW 0x110000 /* Timer : Counter low */
+
+/* ***************************************************************************** */
+#define TM_CNT_UW 0x110004 /* Timer : Counter high word */
+
+/* ***************************************************************************** */
+#define TM_LMT_LDW 0x110008 /* Timer : Limit low */
+
+/* ***************************************************************************** */
+#define TM_LMT_UW 0x11000C /* Timer : Limit high word */
+
+/* ***************************************************************************** */
+#define GP0_IO 0x110010 /* GPIO output enables data I/O */
+#define FLD_GP_OE 0x00FF0000 /* GPIO: GP_OE output enable */
+#define FLD_GP_IN 0x0000FF00 /* GPIO: GP_IN status */
+#define FLD_GP_OUT 0x000000FF /* GPIO: GP_OUT control */
+
+/* ***************************************************************************** */
+#define GPIO_ISM 0x110014 /* GPIO interrupt sensitivity mode */
+#define FLD_GP_ISM_SNS 0x00000070
+#define FLD_GP_ISM_POL 0x00000007
+
+/* ***************************************************************************** */
+#define SOFT_RESET 0x11001C /* Output system reset reg */
+#define FLD_PECOS_SOFT_RESET 0x00000001
+
+/* ***************************************************************************** */
+#define MC416_RWD 0x110020 /* MC416 GPIO[18:3] pin */
+#define MC416_OEN 0x110024 /* Output enable of GPIO[18:3] */
+#define MC416_CTL 0x110028
+
+/* ***************************************************************************** */
+#define ALT_PIN_OUT_SEL 0x11002C /* Alternate GPIO output select */
+
+#define FLD_ALT_GPIO_OUT_SEL 0xF0000000
+/* 0 Disabled <-- default */
+/* 1 GPIO[0] */
+/* 2 GPIO[10] */
+/* 3 VIP_656_DATA_VAL */
+/* 4 VIP_656_DATA[0] */
+/* 5 VIP_656_CLK */
+/* 6 VIP_656_DATA_EXT[1] */
+/* 7 VIP_656_DATA_EXT[0] */
+/* 8 ATT_IF */
+
+#define FLD_AUX_PLL_CLK_ALT_SEL 0x0F000000
+/* 0 AUX_PLL_CLK<-- default */
+/* 1 GPIO[2] */
+/* 2 GPIO[10] */
+/* 3 VIP_656_DATA_VAL */
+/* 4 VIP_656_DATA[0] */
+/* 5 VIP_656_CLK */
+/* 6 VIP_656_DATA_EXT[1] */
+/* 7 VIP_656_DATA_EXT[0] */
+
+#define FLD_IR_TX_ALT_SEL 0x00F00000
+/* 0 IR_TX <-- default */
+/* 1 GPIO[1] */
+/* 2 GPIO[10] */
+/* 3 VIP_656_DATA_VAL */
+/* 4 VIP_656_DATA[0] */
+/* 5 VIP_656_CLK */
+/* 6 VIP_656_DATA_EXT[1] */
+/* 7 VIP_656_DATA_EXT[0] */
+
+#define FLD_IR_RX_ALT_SEL 0x000F0000
+/* 0 IR_RX <-- default */
+/* 1 GPIO[0] */
+/* 2 GPIO[10] */
+/* 3 VIP_656_DATA_VAL */
+/* 4 VIP_656_DATA[0] */
+/* 5 VIP_656_CLK */
+/* 6 VIP_656_DATA_EXT[1] */
+/* 7 VIP_656_DATA_EXT[0] */
+
+#define FLD_GPIO10_ALT_SEL 0x0000F000
+/* 0 GPIO[10] <-- default */
+/* 1 GPIO[0] */
+/* 2 GPIO[10] */
+/* 3 VIP_656_DATA_VAL */
+/* 4 VIP_656_DATA[0] */
+/* 5 VIP_656_CLK */
+/* 6 VIP_656_DATA_EXT[1] */
+/* 7 VIP_656_DATA_EXT[0] */
+
+#define FLD_GPIO2_ALT_SEL 0x00000F00
+/* 0 GPIO[2] <-- default */
+/* 1 GPIO[1] */
+/* 2 GPIO[10] */
+/* 3 VIP_656_DATA_VAL */
+/* 4 VIP_656_DATA[0] */
+/* 5 VIP_656_CLK */
+/* 6 VIP_656_DATA_EXT[1] */
+/* 7 VIP_656_DATA_EXT[0] */
+
+#define FLD_GPIO1_ALT_SEL 0x000000F0
+/* 0 GPIO[1] <-- default */
+/* 1 GPIO[0] */
+/* 2 GPIO[10] */
+/* 3 VIP_656_DATA_VAL */
+/* 4 VIP_656_DATA[0] */
+/* 5 VIP_656_CLK */
+/* 6 VIP_656_DATA_EXT[1] */
+/* 7 VIP_656_DATA_EXT[0] */
+
+#define FLD_GPIO0_ALT_SEL 0x0000000F
+/* 0 GPIO[0] <-- default */
+/* 1 GPIO[1] */
+/* 2 GPIO[10] */
+/* 3 VIP_656_DATA_VAL */
+/* 4 VIP_656_DATA[0] */
+/* 5 VIP_656_CLK */
+/* 6 VIP_656_DATA_EXT[1] */
+/* 7 VIP_656_DATA_EXT[0] */
+
+#define ALT_PIN_IN_SEL 0x110030 /* Alternate GPIO input select */
+
+#define FLD_GPIO10_ALT_IN_SEL 0x0000F000
+/* 0 GPIO[10] <-- default */
+/* 1 IR_RX */
+/* 2 IR_TX */
+/* 3 AUX_PLL_CLK */
+/* 4 IF_ATT_SEL */
+/* 5 GPIO[0] */
+/* 6 GPIO[1] */
+/* 7 GPIO[2] */
+
+#define FLD_GPIO2_ALT_IN_SEL 0x00000F00
+/* 0 GPIO[2] <-- default */
+/* 1 IR_RX */
+/* 2 IR_TX */
+/* 3 AUX_PLL_CLK */
+/* 4 IF_ATT_SEL */
+
+#define FLD_GPIO1_ALT_IN_SEL 0x000000F0
+/* 0 GPIO[1] <-- default */
+/* 1 IR_RX */
+/* 2 IR_TX */
+/* 3 AUX_PLL_CLK */
+/* 4 IF_ATT_SEL */
+
+#define FLD_GPIO0_ALT_IN_SEL 0x0000000F
+/* 0 GPIO[0] <-- default */
+/* 1 IR_RX */
+/* 2 IR_TX */
+/* 3 AUX_PLL_CLK */
+/* 4 IF_ATT_SEL */
+
+/* ***************************************************************************** */
+#define TEST_BUS_CTL1 0x110040 /* Test bus control register #1 */
+
+/* ***************************************************************************** */
+#define TEST_BUS_CTL2 0x110044 /* Test bus control register #2 */
+
+/* ***************************************************************************** */
+#define CLK_DELAY 0x110048 /* Clock delay */
+#define FLD_MOE_CLK_DIS 0x80000000 /* Disable MoE clock */
+
+/* ***************************************************************************** */
+#define PAD_CTRL 0x110068 /* Pad drive strength control */
+
+/* ***************************************************************************** */
+#define MBIST_CTRL 0x110050 /* SRAM memory built-in self test control */
+
+/* ***************************************************************************** */
+#define MBIST_STAT 0x110054 /* SRAM memory built-in self test status */
+
+/* ***************************************************************************** */
+/* PLL registers */
+/* ***************************************************************************** */
+#define PLL_A_INT_FRAC 0x110088
+#define PLL_A_POST_STAT_BIST 0x11008C
+#define PLL_B_INT_FRAC 0x110090
+#define PLL_B_POST_STAT_BIST 0x110094
+#define PLL_C_INT_FRAC 0x110098
+#define PLL_C_POST_STAT_BIST 0x11009C
+#define PLL_D_INT_FRAC 0x1100A0
+#define PLL_D_POST_STAT_BIST 0x1100A4
+
+#define CLK_RST 0x11002C
+#define FLD_VID_I_CLK_NOE 0x00001000
+#define FLD_VID_J_CLK_NOE 0x00002000
+#define FLD_USE_ALT_PLL_REF 0x00004000
+
+#define VID_CH_MODE_SEL 0x110078
+#define VID_CH_CLK_SEL 0x11007C
+
+/* ***************************************************************************** */
+#define VBI_A_DMA 0x130008 /* VBI A DMA data port */
+
+/* ***************************************************************************** */
+#define VID_A_VIP_CTL 0x130080 /* Video A VIP format control */
+#define FLD_VIP_MODE 0x00000001
+
+/* ***************************************************************************** */
+#define VID_A_PIXEL_FRMT 0x130084 /* Video A pixel format */
+#define FLD_VID_A_GAMMA_DIS 0x00000008
+#define FLD_VID_A_FORMAT 0x00000007
+#define FLD_VID_A_GAMMA_FACTOR 0x00000010
+
+/* ***************************************************************************** */
+#define VID_A_VBI_CTL 0x130088 /* Video A VBI miscellaneous control */
+#define FLD_VID_A_VIP_EXT 0x00000003
+
+/* ***************************************************************************** */
+#define VID_B_DMA 0x130100 /* Video B DMA data port */
+
+/* ***************************************************************************** */
+#define VBI_B_DMA 0x130108 /* VBI B DMA data port */
+
+/* ***************************************************************************** */
+#define VID_B_SRC_SEL 0x130144 /* Video B source select */
+#define FLD_VID_B_SRC_SEL 0x00000000
+
+/* ***************************************************************************** */
+#define VID_B_LNGTH 0x130150 /* Video B line length */
+#define FLD_VID_B_LN_LNGTH 0x00000FFF
+
+/* ***************************************************************************** */
+#define VID_B_VIP_CTL 0x130180 /* Video B VIP format control */
+
+/* ***************************************************************************** */
+#define VID_B_PIXEL_FRMT 0x130184 /* Video B pixel format */
+#define FLD_VID_B_GAMMA_DIS 0x00000008
+#define FLD_VID_B_FORMAT 0x00000007
+#define FLD_VID_B_GAMMA_FACTOR 0x00000010
+
+/* ***************************************************************************** */
+#define VID_C_DMA 0x130200 /* Video C DMA data port */
+
+/* ***************************************************************************** */
+#define VID_C_LNGTH 0x130250 /* Video C line length */
+#define FLD_VID_C_LN_LNGTH 0x00000FFF
+
+/* ***************************************************************************** */
+/* Video Destination Channels */
+/* ***************************************************************************** */
+
+#define VID_DST_A_GPCNT 0x130020 /* Video A general purpose counter */
+#define VID_DST_B_GPCNT 0x130120 /* Video B general purpose counter */
+#define VID_DST_C_GPCNT 0x130220 /* Video C general purpose counter */
+#define VID_DST_D_GPCNT 0x130320 /* Video D general purpose counter */
+#define VID_DST_E_GPCNT 0x130420 /* Video E general purpose counter */
+#define VID_DST_F_GPCNT 0x130520 /* Video F general purpose counter */
+#define VID_DST_G_GPCNT 0x130620 /* Video G general purpose counter */
+#define VID_DST_H_GPCNT 0x130720 /* Video H general purpose counter */
+
+/* ***************************************************************************** */
+
+#define VID_DST_A_GPCNT_CTL 0x130030 /* Video A general purpose control */
+#define VID_DST_B_GPCNT_CTL 0x130130 /* Video B general purpose control */
+#define VID_DST_C_GPCNT_CTL 0x130230 /* Video C general purpose control */
+#define VID_DST_D_GPCNT_CTL 0x130330 /* Video D general purpose control */
+#define VID_DST_E_GPCNT_CTL 0x130430 /* Video E general purpose control */
+#define VID_DST_F_GPCNT_CTL 0x130530 /* Video F general purpose control */
+#define VID_DST_G_GPCNT_CTL 0x130630 /* Video G general purpose control */
+#define VID_DST_H_GPCNT_CTL 0x130730 /* Video H general purpose control */
+
+/* ***************************************************************************** */
+
+#define VID_DST_A_DMA_CTL 0x130040 /* Video A DMA control */
+#define VID_DST_B_DMA_CTL 0x130140 /* Video B DMA control */
+#define VID_DST_C_DMA_CTL 0x130240 /* Video C DMA control */
+#define VID_DST_D_DMA_CTL 0x130340 /* Video D DMA control */
+#define VID_DST_E_DMA_CTL 0x130440 /* Video E DMA control */
+#define VID_DST_F_DMA_CTL 0x130540 /* Video F DMA control */
+#define VID_DST_G_DMA_CTL 0x130640 /* Video G DMA control */
+#define VID_DST_H_DMA_CTL 0x130740 /* Video H DMA control */
+
+#define FLD_VID_RISC_EN 0x00000010
+#define FLD_VID_FIFO_EN 0x00000001
+
+/* ***************************************************************************** */
+
+#define VID_DST_A_VIP_CTL 0x130080 /* Video A VIP control */
+#define VID_DST_B_VIP_CTL 0x130180 /* Video B VIP control */
+#define VID_DST_C_VIP_CTL 0x130280 /* Video C VIP control */
+#define VID_DST_D_VIP_CTL 0x130380 /* Video D VIP control */
+#define VID_DST_E_VIP_CTL 0x130480 /* Video E VIP control */
+#define VID_DST_F_VIP_CTL 0x130580 /* Video F VIP control */
+#define VID_DST_G_VIP_CTL 0x130680 /* Video G VIP control */
+#define VID_DST_H_VIP_CTL 0x130780 /* Video H VIP control */
+
+/* ***************************************************************************** */
+
+#define VID_DST_A_PIX_FRMT 0x130084 /* Video A Pixel format */
+#define VID_DST_B_PIX_FRMT 0x130184 /* Video B Pixel format */
+#define VID_DST_C_PIX_FRMT 0x130284 /* Video C Pixel format */
+#define VID_DST_D_PIX_FRMT 0x130384 /* Video D Pixel format */
+#define VID_DST_E_PIX_FRMT 0x130484 /* Video E Pixel format */
+#define VID_DST_F_PIX_FRMT 0x130584 /* Video F Pixel format */
+#define VID_DST_G_PIX_FRMT 0x130684 /* Video G Pixel format */
+#define VID_DST_H_PIX_FRMT 0x130784 /* Video H Pixel format */
+
+/* ***************************************************************************** */
+/* Video Source Channels */
+/* ***************************************************************************** */
+
+#define VID_SRC_A_GPCNT_CTL 0x130804 /* Video A general purpose control */
+#define VID_SRC_B_GPCNT_CTL 0x130904 /* Video B general purpose control */
+#define VID_SRC_C_GPCNT_CTL 0x130A04 /* Video C general purpose control */
+#define VID_SRC_D_GPCNT_CTL 0x130B04 /* Video D general purpose control */
+#define VID_SRC_E_GPCNT_CTL 0x130C04 /* Video E general purpose control */
+#define VID_SRC_F_GPCNT_CTL 0x130D04 /* Video F general purpose control */
+#define VID_SRC_I_GPCNT_CTL 0x130E04 /* Video I general purpose control */
+#define VID_SRC_J_GPCNT_CTL 0x130F04 /* Video J general purpose control */
+
+/* ***************************************************************************** */
+
+#define VID_SRC_A_GPCNT 0x130808 /* Video A general purpose counter */
+#define VID_SRC_B_GPCNT 0x130908 /* Video B general purpose counter */
+#define VID_SRC_C_GPCNT 0x130A08 /* Video C general purpose counter */
+#define VID_SRC_D_GPCNT 0x130B08 /* Video D general purpose counter */
+#define VID_SRC_E_GPCNT 0x130C08 /* Video E general purpose counter */
+#define VID_SRC_F_GPCNT 0x130D08 /* Video F general purpose counter */
+#define VID_SRC_I_GPCNT 0x130E08 /* Video I general purpose counter */
+#define VID_SRC_J_GPCNT 0x130F08 /* Video J general purpose counter */
+
+/* ***************************************************************************** */
+
+#define VID_SRC_A_DMA_CTL 0x13080C /* Video A DMA control */
+#define VID_SRC_B_DMA_CTL 0x13090C /* Video B DMA control */
+#define VID_SRC_C_DMA_CTL 0x130A0C /* Video C DMA control */
+#define VID_SRC_D_DMA_CTL 0x130B0C /* Video D DMA control */
+#define VID_SRC_E_DMA_CTL 0x130C0C /* Video E DMA control */
+#define VID_SRC_F_DMA_CTL 0x130D0C /* Video F DMA control */
+#define VID_SRC_I_DMA_CTL 0x130E0C /* Video I DMA control */
+#define VID_SRC_J_DMA_CTL 0x130F0C /* Video J DMA control */
+
+#define FLD_APB_RISC_EN 0x00000010
+#define FLD_APB_FIFO_EN 0x00000001
+
+/* ***************************************************************************** */
+
+#define VID_SRC_A_FMT_CTL 0x130810 /* Video A format control */
+#define VID_SRC_B_FMT_CTL 0x130910 /* Video B format control */
+#define VID_SRC_C_FMT_CTL 0x130A10 /* Video C format control */
+#define VID_SRC_D_FMT_CTL 0x130B10 /* Video D format control */
+#define VID_SRC_E_FMT_CTL 0x130C10 /* Video E format control */
+#define VID_SRC_F_FMT_CTL 0x130D10 /* Video F format control */
+#define VID_SRC_I_FMT_CTL 0x130E10 /* Video I format control */
+#define VID_SRC_J_FMT_CTL 0x130F10 /* Video J format control */
+
+/* ***************************************************************************** */
+
+#define VID_SRC_A_ACTIVE_CTL1 0x130814 /* Video A active control 1 */
+#define VID_SRC_B_ACTIVE_CTL1 0x130914 /* Video B active control 1 */
+#define VID_SRC_C_ACTIVE_CTL1 0x130A14 /* Video C active control 1 */
+#define VID_SRC_D_ACTIVE_CTL1 0x130B14 /* Video D active control 1 */
+#define VID_SRC_E_ACTIVE_CTL1 0x130C14 /* Video E active control 1 */
+#define VID_SRC_F_ACTIVE_CTL1 0x130D14 /* Video F active control 1 */
+#define VID_SRC_I_ACTIVE_CTL1 0x130E14 /* Video I active control 1 */
+#define VID_SRC_J_ACTIVE_CTL1 0x130F14 /* Video J active control 1 */
+
+/* ***************************************************************************** */
+
+#define VID_SRC_A_ACTIVE_CTL2 0x130818 /* Video A active control 2 */
+#define VID_SRC_B_ACTIVE_CTL2 0x130918 /* Video B active control 2 */
+#define VID_SRC_C_ACTIVE_CTL2 0x130A18 /* Video C active control 2 */
+#define VID_SRC_D_ACTIVE_CTL2 0x130B18 /* Video D active control 2 */
+#define VID_SRC_E_ACTIVE_CTL2 0x130C18 /* Video E active control 2 */
+#define VID_SRC_F_ACTIVE_CTL2 0x130D18 /* Video F active control 2 */
+#define VID_SRC_I_ACTIVE_CTL2 0x130E18 /* Video I active control 2 */
+#define VID_SRC_J_ACTIVE_CTL2 0x130F18 /* Video J active control 2 */
+
+/* ***************************************************************************** */
+
+#define VID_SRC_A_CDT_SZ 0x13081C /* Video A CDT size */
+#define VID_SRC_B_CDT_SZ 0x13091C /* Video B CDT size */
+#define VID_SRC_C_CDT_SZ 0x130A1C /* Video C CDT size */
+#define VID_SRC_D_CDT_SZ 0x130B1C /* Video D CDT size */
+#define VID_SRC_E_CDT_SZ 0x130C1C /* Video E CDT size */
+#define VID_SRC_F_CDT_SZ 0x130D1C /* Video F CDT size */
+#define VID_SRC_I_CDT_SZ 0x130E1C /* Video I CDT size */
+#define VID_SRC_J_CDT_SZ 0x130F1C /* Video J CDT size */
+
+/* ***************************************************************************** */
+/* Audio I/F */
+/* ***************************************************************************** */
+#define AUD_DST_A_DMA 0x140000 /* Audio Int A DMA data port */
+#define AUD_SRC_A_DMA 0x140008 /* Audio Int A DMA data port */
+
+#define AUD_A_GPCNT 0x140010 /* Audio Int A gp counter */
+#define FLD_AUD_A_GP_CNT 0x0000FFFF
+
+#define AUD_A_GPCNT_CTL 0x140014 /* Audio Int A gp control */
+
+#define AUD_A_LNGTH 0x140018 /* Audio Int A line length */
+
+#define AUD_A_CFG 0x14001C /* Audio Int A configuration */
+
+/* ***************************************************************************** */
+#define AUD_DST_B_DMA 0x140100 /* Audio Int B DMA data port */
+#define AUD_SRC_B_DMA 0x140108 /* Audio Int B DMA data port */
+
+#define AUD_B_GPCNT 0x140110 /* Audio Int B gp counter */
+#define FLD_AUD_B_GP_CNT 0x0000FFFF
+
+#define AUD_B_GPCNT_CTL 0x140114 /* Audio Int B gp control */
+
+#define AUD_B_LNGTH 0x140118 /* Audio Int B line length */
+
+#define AUD_B_CFG 0x14011C /* Audio Int B configuration */
+
+/* ***************************************************************************** */
+#define AUD_DST_C_DMA 0x140200 /* Audio Int C DMA data port */
+#define AUD_SRC_C_DMA 0x140208 /* Audio Int C DMA data port */
+
+#define AUD_C_GPCNT 0x140210 /* Audio Int C gp counter */
+#define FLD_AUD_C_GP_CNT 0x0000FFFF
+
+#define AUD_C_GPCNT_CTL 0x140214 /* Audio Int C gp control */
+
+#define AUD_C_LNGTH 0x140218 /* Audio Int C line length */
+
+#define AUD_C_CFG 0x14021C /* Audio Int C configuration */
+
+/* ***************************************************************************** */
+#define AUD_DST_D_DMA 0x140300 /* Audio Int D DMA data port */
+#define AUD_SRC_D_DMA 0x140308 /* Audio Int D DMA data port */
+
+#define AUD_D_GPCNT 0x140310 /* Audio Int D gp counter */
+#define FLD_AUD_D_GP_CNT 0x0000FFFF
+
+#define AUD_D_GPCNT_CTL 0x140314 /* Audio Int D gp control */
+
+#define AUD_D_LNGTH 0x140318 /* Audio Int D line length */
+
+#define AUD_D_CFG 0x14031C /* Audio Int D configuration */
+
+/* ***************************************************************************** */
+#define AUD_SRC_E_DMA 0x140400 /* Audio Int E DMA data port */
+
+#define AUD_E_GPCNT 0x140410 /* Audio Int E gp counter */
+#define FLD_AUD_E_GP_CNT 0x0000FFFF
+
+#define AUD_E_GPCNT_CTL 0x140414 /* Audio Int E gp control */
+
+#define AUD_E_CFG 0x14041C /* Audio Int E configuration */
+
+/* ***************************************************************************** */
+
+#define FLD_AUD_DST_LN_LNGTH 0x00000FFF
+
+#define FLD_AUD_DST_PK_MODE 0x00004000
+
+#define FLD_AUD_CLK_ENABLE 0x00000200
+
+#define FLD_AUD_MASTER_MODE 0x00000002
+
+#define FLD_AUD_SONY_MODE 0x00000001
+
+#define FLD_AUD_CLK_SELECT_PLL_D 0x00001800
+
+#define FLD_AUD_DST_ENABLE 0x00020000
+
+#define FLD_AUD_SRC_ENABLE 0x00010000
+
+/* ***************************************************************************** */
+#define AUD_INT_DMA_CTL 0x140500 /* Audio Int DMA control */
+
+#define FLD_AUD_SRC_E_RISC_EN 0x00008000
+#define FLD_AUD_SRC_C_RISC_EN 0x00004000
+#define FLD_AUD_SRC_B_RISC_EN 0x00002000
+#define FLD_AUD_SRC_A_RISC_EN 0x00001000
+
+#define FLD_AUD_DST_D_RISC_EN 0x00000800
+#define FLD_AUD_DST_C_RISC_EN 0x00000400
+#define FLD_AUD_DST_B_RISC_EN 0x00000200
+#define FLD_AUD_DST_A_RISC_EN 0x00000100
+
+#define FLD_AUD_SRC_E_FIFO_EN 0x00000080
+#define FLD_AUD_SRC_C_FIFO_EN 0x00000040
+#define FLD_AUD_SRC_B_FIFO_EN 0x00000020
+#define FLD_AUD_SRC_A_FIFO_EN 0x00000010
+
+#define FLD_AUD_DST_D_FIFO_EN 0x00000008
+#define FLD_AUD_DST_C_FIFO_EN 0x00000004
+#define FLD_AUD_DST_B_FIFO_EN 0x00000002
+#define FLD_AUD_DST_A_FIFO_EN 0x00000001
+
+/* ***************************************************************************** */
+/* */
+/* Mobilygen Interface Registers */
+/* */
+/* ***************************************************************************** */
+/* Mobilygen Interface A */
+/* ***************************************************************************** */
+#define MB_IF_A_DMA 0x150000 /* MBIF A DMA data port */
+#define MB_IF_A_GPCN 0x150008 /* MBIF A GP counter */
+#define MB_IF_A_GPCN_CTRL 0x15000C
+#define MB_IF_A_DMA_CTRL 0x150010
+#define MB_IF_A_LENGTH 0x150014
+#define MB_IF_A_HDMA_XFER_SZ 0x150018
+#define MB_IF_A_HCMD 0x15001C
+#define MB_IF_A_HCONFIG 0x150020
+#define MB_IF_A_DATA_STRUCT_0 0x150024
+#define MB_IF_A_DATA_STRUCT_1 0x150028
+#define MB_IF_A_DATA_STRUCT_2 0x15002C
+#define MB_IF_A_DATA_STRUCT_3 0x150030
+#define MB_IF_A_DATA_STRUCT_4 0x150034
+#define MB_IF_A_DATA_STRUCT_5 0x150038
+#define MB_IF_A_DATA_STRUCT_6 0x15003C
+#define MB_IF_A_DATA_STRUCT_7 0x150040
+#define MB_IF_A_DATA_STRUCT_8 0x150044
+#define MB_IF_A_DATA_STRUCT_9 0x150048
+#define MB_IF_A_DATA_STRUCT_A 0x15004C
+#define MB_IF_A_DATA_STRUCT_B 0x150050
+#define MB_IF_A_DATA_STRUCT_C 0x150054
+#define MB_IF_A_DATA_STRUCT_D 0x150058
+#define MB_IF_A_DATA_STRUCT_E 0x15005C
+#define MB_IF_A_DATA_STRUCT_F 0x150060
+/* ***************************************************************************** */
+/* Mobilygen Interface B */
+/* ***************************************************************************** */
+#define MB_IF_B_DMA 0x160000 /* MBIF A DMA data port */
+#define MB_IF_B_GPCN 0x160008 /* MBIF A GP counter */
+#define MB_IF_B_GPCN_CTRL 0x16000C
+#define MB_IF_B_DMA_CTRL 0x160010
+#define MB_IF_B_LENGTH 0x160014
+#define MB_IF_B_HDMA_XFER_SZ 0x160018
+#define MB_IF_B_HCMD 0x16001C
+#define MB_IF_B_HCONFIG 0x160020
+#define MB_IF_B_DATA_STRUCT_0 0x160024
+#define MB_IF_B_DATA_STRUCT_1 0x160028
+#define MB_IF_B_DATA_STRUCT_2 0x16002C
+#define MB_IF_B_DATA_STRUCT_3 0x160030
+#define MB_IF_B_DATA_STRUCT_4 0x160034
+#define MB_IF_B_DATA_STRUCT_5 0x160038
+#define MB_IF_B_DATA_STRUCT_6 0x16003C
+#define MB_IF_B_DATA_STRUCT_7 0x160040
+#define MB_IF_B_DATA_STRUCT_8 0x160044
+#define MB_IF_B_DATA_STRUCT_9 0x160048
+#define MB_IF_B_DATA_STRUCT_A 0x16004C
+#define MB_IF_B_DATA_STRUCT_B 0x160050
+#define MB_IF_B_DATA_STRUCT_C 0x160054
+#define MB_IF_B_DATA_STRUCT_D 0x160058
+#define MB_IF_B_DATA_STRUCT_E 0x16005C
+#define MB_IF_B_DATA_STRUCT_F 0x160060
+
+/* MB_DMA_CTRL */
+#define FLD_MB_IF_RISC_EN 0x00000010
+#define FLD_MB_IF_FIFO_EN 0x00000001
+
+/* MB_LENGTH */
+#define FLD_MB_IF_LN_LNGTH 0x00000FFF
+
+/* MB_HCMD register */
+#define FLD_MB_HCMD_H_GO 0x80000000
+#define FLD_MB_HCMD_H_BUSY 0x40000000
+#define FLD_MB_HCMD_H_DMA_HOLD 0x10000000
+#define FLD_MB_HCMD_H_DMA_BUSY 0x08000000
+#define FLD_MB_HCMD_H_DMA_TYPE 0x04000000
+#define FLD_MB_HCMD_H_DMA_XACT 0x02000000
+#define FLD_MB_HCMD_H_RW_N 0x01000000
+#define FLD_MB_HCMD_H_ADDR 0x00FF0000
+#define FLD_MB_HCMD_H_DATA 0x0000FFFF
+
+/* ***************************************************************************** */
+/* I2C #1 */
+/* ***************************************************************************** */
+#define I2C1_ADDR 0x180000 /* I2C #1 address */
+#define FLD_I2C_DADDR 0xfe000000 /* RW [31:25] I2C Device Address */
+ /* RO [24] reserved */
+/* ***************************************************************************** */
+#define FLD_I2C_SADDR 0x00FFFFFF /* RW [23:0] I2C Sub-address */
+
+/* ***************************************************************************** */
+#define I2C1_WDATA 0x180004 /* I2C #1 write data */
+#define FLD_I2C_WDATA 0xFFFFFFFF /* RW [31:0] */
+
+/* ***************************************************************************** */
+#define I2C1_CTRL 0x180008 /* I2C #1 control */
+#define FLD_I2C_PERIOD 0xFF000000 /* RW [31:24] */
+#define FLD_I2C_SCL_IN 0x00200000 /* RW [21] */
+#define FLD_I2C_SDA_IN 0x00100000 /* RW [20] */
+ /* RO [19:18] reserved */
+#define FLD_I2C_SCL_OUT 0x00020000 /* RW [17] */
+#define FLD_I2C_SDA_OUT 0x00010000 /* RW [16] */
+ /* RO [15] reserved */
+#define FLD_I2C_DATA_LEN 0x00007000 /* RW [14:12] */
+#define FLD_I2C_SADDR_INC 0x00000800 /* RW [11] */
+ /* RO [10:9] reserved */
+#define FLD_I2C_SADDR_LEN 0x00000300 /* RW [9:8] */
+ /* RO [7:6] reserved */
+#define FLD_I2C_SOFT 0x00000020 /* RW [5] */
+#define FLD_I2C_NOSTOP 0x00000010 /* RW [4] */
+#define FLD_I2C_EXTEND 0x00000008 /* RW [3] */
+#define FLD_I2C_SYNC 0x00000004 /* RW [2] */
+#define FLD_I2C_READ_SA 0x00000002 /* RW [1] */
+#define FLD_I2C_READ_WRN 0x00000001 /* RW [0] */
+
+/* ***************************************************************************** */
+#define I2C1_RDATA 0x18000C /* I2C #1 read data */
+#define FLD_I2C_RDATA 0xFFFFFFFF /* RO [31:0] */
+
+/* ***************************************************************************** */
+#define I2C1_STAT 0x180010 /* I2C #1 status */
+#define FLD_I2C_XFER_IN_PROG 0x00000002 /* RO [1] */
+#define FLD_I2C_RACK 0x00000001 /* RO [0] */
+
+/* ***************************************************************************** */
+/* I2C #2 */
+/* ***************************************************************************** */
+#define I2C2_ADDR 0x190000 /* I2C #2 address */
+
+/* ***************************************************************************** */
+#define I2C2_WDATA 0x190004 /* I2C #2 write data */
+
+/* ***************************************************************************** */
+#define I2C2_CTRL 0x190008 /* I2C #2 control */
+
+/* ***************************************************************************** */
+#define I2C2_RDATA 0x19000C /* I2C #2 read data */
+
+/* ***************************************************************************** */
+#define I2C2_STAT 0x190010 /* I2C #2 status */
+
+/* ***************************************************************************** */
+/* I2C #3 */
+/* ***************************************************************************** */
+#define I2C3_ADDR 0x1A0000 /* I2C #3 address */
+
+/* ***************************************************************************** */
+#define I2C3_WDATA 0x1A0004 /* I2C #3 write data */
+
+/* ***************************************************************************** */
+#define I2C3_CTRL 0x1A0008 /* I2C #3 control */
+
+/* ***************************************************************************** */
+#define I2C3_RDATA 0x1A000C /* I2C #3 read data */
+
+/* ***************************************************************************** */
+#define I2C3_STAT 0x1A0010 /* I2C #3 status */
+
+/* ***************************************************************************** */
+/* UART */
+/* ***************************************************************************** */
+#define UART_CTL 0x1B0000 /* UART Control Register */
+#define FLD_LOOP_BACK_EN (1 << 7) /* RW field - default 0 */
+#define FLD_RX_TRG_SZ (3 << 2) /* RW field - default 0 */
+#define FLD_RX_EN (1 << 1) /* RW field - default 0 */
+#define FLD_TX_EN (1 << 0) /* RW field - default 0 */
+
+/* ***************************************************************************** */
+#define UART_BRD 0x1B0004 /* UART Baud Rate Divisor */
+#define FLD_BRD 0x0000FFFF /* RW field - default 0x197 */
+
+/* ***************************************************************************** */
+#define UART_DBUF 0x1B0008 /* UART Tx/Rx Data BuFFer */
+#define FLD_DB 0xFFFFFFFF /* RW field - default 0 */
+
+/* ***************************************************************************** */
+#define UART_ISR 0x1B000C /* UART Interrupt Status */
+#define FLD_RXD_TIMEOUT_EN (1 << 7) /* RW field - default 0 */
+#define FLD_FRM_ERR_EN (1 << 6) /* RW field - default 0 */
+#define FLD_RXD_RDY_EN (1 << 5) /* RW field - default 0 */
+#define FLD_TXD_EMPTY_EN (1 << 4) /* RW field - default 0 */
+#define FLD_RXD_OVERFLOW (1 << 3) /* RW field - default 0 */
+#define FLD_FRM_ERR (1 << 2) /* RW field - default 0 */
+#define FLD_RXD_RDY (1 << 1) /* RW field - default 0 */
+#define FLD_TXD_EMPTY (1 << 0) /* RW field - default 0 */
+
+/* ***************************************************************************** */
+#define UART_CNT 0x1B0010 /* UART Tx/Rx FIFO Byte Count */
+#define FLD_TXD_CNT (0x1F << 8) /* RW field - default 0 */
+#define FLD_RXD_CNT (0x1F << 0) /* RW field - default 0 */
+
+/* ***************************************************************************** */
+/* 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 */
diff --git a/drivers/media/pci/cx25821/cx25821-sram.h b/drivers/media/pci/cx25821/cx25821-sram.h
new file mode 100644
index 000000000..99bbb7252
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-sram.h
@@ -0,0 +1,247 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Driver for the Conexant CX25821 PCIe bridge
+ *
+ * Copyright (C) 2009 Conexant Systems Inc.
+ * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ */
+
+#ifndef __ATHENA_SRAM_H__
+#define __ATHENA_SRAM_H__
+
+/* #define RX_SRAM_START_SIZE = 0; // Start of reserved SRAM */
+#define VID_CMDS_SIZE 80 /* Video CMDS size in bytes */
+#define AUDIO_CMDS_SIZE 80 /* AUDIO CMDS size in bytes */
+#define MBIF_CMDS_SIZE 80 /* MBIF CMDS size in bytes */
+
+/* #define RX_SRAM_POOL_START_SIZE = 0; // Start of usable RX SRAM for buffers */
+#define VID_IQ_SIZE 64 /* VID instruction queue size in bytes */
+#define MBIF_IQ_SIZE 64
+#define AUDIO_IQ_SIZE 64 /* AUD instruction queue size in bytes */
+
+#define VID_CDT_SIZE 64 /* VID cluster descriptor table size in bytes */
+#define MBIF_CDT_SIZE 64 /* MBIF/HBI cluster descriptor table size in bytes */
+#define AUDIO_CDT_SIZE 48 /* AUD cluster descriptor table size in bytes */
+
+/* #define RX_SRAM_POOL_FREE_SIZE = 16; // Start of available RX SRAM */
+/* #define RX_SRAM_END_SIZE = 0; // End of RX SRAM */
+
+/* #define TX_SRAM_POOL_START_SIZE = 0; // Start of transmit pool SRAM */
+/* #define MSI_DATA_SIZE = 64; // Reserved (MSI Data, RISC working stora */
+
+#define VID_CLUSTER_SIZE 1440 /* VID cluster data line */
+#define AUDIO_CLUSTER_SIZE 128 /* AUDIO cluster data line */
+#define MBIF_CLUSTER_SIZE 1440 /* MBIF/HBI cluster data line */
+
+/* #define TX_SRAM_POOL_FREE_SIZE = 704; // Start of available TX SRAM */
+/* #define TX_SRAM_END_SIZE = 0; // End of TX SRAM */
+
+/* Receive SRAM */
+#define RX_SRAM_START 0x10000
+#define VID_A_DOWN_CMDS 0x10000
+#define VID_B_DOWN_CMDS 0x10050
+#define VID_C_DOWN_CMDS 0x100A0
+#define VID_D_DOWN_CMDS 0x100F0
+#define VID_E_DOWN_CMDS 0x10140
+#define VID_F_DOWN_CMDS 0x10190
+#define VID_G_DOWN_CMDS 0x101E0
+#define VID_H_DOWN_CMDS 0x10230
+#define VID_A_UP_CMDS 0x10280
+#define VID_B_UP_CMDS 0x102D0
+#define VID_C_UP_CMDS 0x10320
+#define VID_D_UP_CMDS 0x10370
+#define VID_E_UP_CMDS 0x103C0
+#define VID_F_UP_CMDS 0x10410
+#define VID_I_UP_CMDS 0x10460
+#define VID_J_UP_CMDS 0x104B0
+#define AUD_A_DOWN_CMDS 0x10500
+#define AUD_B_DOWN_CMDS 0x10550
+#define AUD_C_DOWN_CMDS 0x105A0
+#define AUD_D_DOWN_CMDS 0x105F0
+#define AUD_A_UP_CMDS 0x10640
+#define AUD_B_UP_CMDS 0x10690
+#define AUD_C_UP_CMDS 0x106E0
+#define AUD_E_UP_CMDS 0x10730
+#define MBIF_A_DOWN_CMDS 0x10780
+#define MBIF_B_DOWN_CMDS 0x107D0
+#define DMA_SCRATCH_PAD 0x10820 /* Scratch pad area from 0x10820 to 0x10B40 */
+
+/* #define RX_SRAM_POOL_START = 0x105B0; */
+
+#define VID_A_IQ 0x11000
+#define VID_B_IQ 0x11040
+#define VID_C_IQ 0x11080
+#define VID_D_IQ 0x110C0
+#define VID_E_IQ 0x11100
+#define VID_F_IQ 0x11140
+#define VID_G_IQ 0x11180
+#define VID_H_IQ 0x111C0
+#define VID_I_IQ 0x11200
+#define VID_J_IQ 0x11240
+#define AUD_A_IQ 0x11280
+#define AUD_B_IQ 0x112C0
+#define AUD_C_IQ 0x11300
+#define AUD_D_IQ 0x11340
+#define AUD_E_IQ 0x11380
+#define MBIF_A_IQ 0x11000
+#define MBIF_B_IQ 0x110C0
+
+#define VID_A_CDT 0x10C00
+#define VID_B_CDT 0x10C40
+#define VID_C_CDT 0x10C80
+#define VID_D_CDT 0x10CC0
+#define VID_E_CDT 0x10D00
+#define VID_F_CDT 0x10D40
+#define VID_G_CDT 0x10D80
+#define VID_H_CDT 0x10DC0
+#define VID_I_CDT 0x10E00
+#define VID_J_CDT 0x10E40
+#define AUD_A_CDT 0x10E80
+#define AUD_B_CDT 0x10EB0
+#define AUD_C_CDT 0x10EE0
+#define AUD_D_CDT 0x10F10
+#define AUD_E_CDT 0x10F40
+#define MBIF_A_CDT 0x10C00
+#define MBIF_B_CDT 0x10CC0
+
+/* Cluster Buffer for RX */
+#define VID_A_UP_CLUSTER_1 0x11400
+#define VID_A_UP_CLUSTER_2 0x119A0
+#define VID_A_UP_CLUSTER_3 0x11F40
+#define VID_A_UP_CLUSTER_4 0x124E0
+
+#define VID_B_UP_CLUSTER_1 0x12A80
+#define VID_B_UP_CLUSTER_2 0x13020
+#define VID_B_UP_CLUSTER_3 0x135C0
+#define VID_B_UP_CLUSTER_4 0x13B60
+
+#define VID_C_UP_CLUSTER_1 0x14100
+#define VID_C_UP_CLUSTER_2 0x146A0
+#define VID_C_UP_CLUSTER_3 0x14C40
+#define VID_C_UP_CLUSTER_4 0x151E0
+
+#define VID_D_UP_CLUSTER_1 0x15780
+#define VID_D_UP_CLUSTER_2 0x15D20
+#define VID_D_UP_CLUSTER_3 0x162C0
+#define VID_D_UP_CLUSTER_4 0x16860
+
+#define VID_E_UP_CLUSTER_1 0x16E00
+#define VID_E_UP_CLUSTER_2 0x173A0
+#define VID_E_UP_CLUSTER_3 0x17940
+#define VID_E_UP_CLUSTER_4 0x17EE0
+
+#define VID_F_UP_CLUSTER_1 0x18480
+#define VID_F_UP_CLUSTER_2 0x18A20
+#define VID_F_UP_CLUSTER_3 0x18FC0
+#define VID_F_UP_CLUSTER_4 0x19560
+
+#define VID_I_UP_CLUSTER_1 0x19B00
+#define VID_I_UP_CLUSTER_2 0x1A0A0
+#define VID_I_UP_CLUSTER_3 0x1A640
+#define VID_I_UP_CLUSTER_4 0x1ABE0
+
+#define VID_J_UP_CLUSTER_1 0x1B180
+#define VID_J_UP_CLUSTER_2 0x1B720
+#define VID_J_UP_CLUSTER_3 0x1BCC0
+#define VID_J_UP_CLUSTER_4 0x1C260
+
+#define AUD_A_UP_CLUSTER_1 0x1C800
+#define AUD_A_UP_CLUSTER_2 0x1C880
+#define AUD_A_UP_CLUSTER_3 0x1C900
+
+#define AUD_B_UP_CLUSTER_1 0x1C980
+#define AUD_B_UP_CLUSTER_2 0x1CA00
+#define AUD_B_UP_CLUSTER_3 0x1CA80
+
+#define AUD_C_UP_CLUSTER_1 0x1CB00
+#define AUD_C_UP_CLUSTER_2 0x1CB80
+#define AUD_C_UP_CLUSTER_3 0x1CC00
+
+#define AUD_E_UP_CLUSTER_1 0x1CC80
+#define AUD_E_UP_CLUSTER_2 0x1CD00
+#define AUD_E_UP_CLUSTER_3 0x1CD80
+
+#define RX_SRAM_POOL_FREE 0x1CE00
+#define RX_SRAM_END 0x1D000
+
+/* Free Receive SRAM 144 Bytes */
+
+/* Transmit SRAM */
+#define TX_SRAM_POOL_START 0x00000
+
+#define VID_A_DOWN_CLUSTER_1 0x00040
+#define VID_A_DOWN_CLUSTER_2 0x005E0
+#define VID_A_DOWN_CLUSTER_3 0x00B80
+#define VID_A_DOWN_CLUSTER_4 0x01120
+
+#define VID_B_DOWN_CLUSTER_1 0x016C0
+#define VID_B_DOWN_CLUSTER_2 0x01C60
+#define VID_B_DOWN_CLUSTER_3 0x02200
+#define VID_B_DOWN_CLUSTER_4 0x027A0
+
+#define VID_C_DOWN_CLUSTER_1 0x02D40
+#define VID_C_DOWN_CLUSTER_2 0x032E0
+#define VID_C_DOWN_CLUSTER_3 0x03880
+#define VID_C_DOWN_CLUSTER_4 0x03E20
+
+#define VID_D_DOWN_CLUSTER_1 0x043C0
+#define VID_D_DOWN_CLUSTER_2 0x04960
+#define VID_D_DOWN_CLUSTER_3 0x04F00
+#define VID_D_DOWN_CLUSTER_4 0x054A0
+
+#define VID_E_DOWN_CLUSTER_1 0x05a40
+#define VID_E_DOWN_CLUSTER_2 0x05FE0
+#define VID_E_DOWN_CLUSTER_3 0x06580
+#define VID_E_DOWN_CLUSTER_4 0x06B20
+
+#define VID_F_DOWN_CLUSTER_1 0x070C0
+#define VID_F_DOWN_CLUSTER_2 0x07660
+#define VID_F_DOWN_CLUSTER_3 0x07C00
+#define VID_F_DOWN_CLUSTER_4 0x081A0
+
+#define VID_G_DOWN_CLUSTER_1 0x08740
+#define VID_G_DOWN_CLUSTER_2 0x08CE0
+#define VID_G_DOWN_CLUSTER_3 0x09280
+#define VID_G_DOWN_CLUSTER_4 0x09820
+
+#define VID_H_DOWN_CLUSTER_1 0x09DC0
+#define VID_H_DOWN_CLUSTER_2 0x0A360
+#define VID_H_DOWN_CLUSTER_3 0x0A900
+#define VID_H_DOWN_CLUSTER_4 0x0AEA0
+
+#define AUD_A_DOWN_CLUSTER_1 0x0B500
+#define AUD_A_DOWN_CLUSTER_2 0x0B580
+#define AUD_A_DOWN_CLUSTER_3 0x0B600
+
+#define AUD_B_DOWN_CLUSTER_1 0x0B680
+#define AUD_B_DOWN_CLUSTER_2 0x0B700
+#define AUD_B_DOWN_CLUSTER_3 0x0B780
+
+#define AUD_C_DOWN_CLUSTER_1 0x0B800
+#define AUD_C_DOWN_CLUSTER_2 0x0B880
+#define AUD_C_DOWN_CLUSTER_3 0x0B900
+
+#define AUD_D_DOWN_CLUSTER_1 0x0B980
+#define AUD_D_DOWN_CLUSTER_2 0x0BA00
+#define AUD_D_DOWN_CLUSTER_3 0x0BA80
+
+#define TX_SRAM_POOL_FREE 0x0BB00
+#define TX_SRAM_END 0x0C000
+
+#define BYTES_TO_DWORDS(bcount) ((bcount) >> 2)
+#define BYTES_TO_QWORDS(bcount) ((bcount) >> 3)
+#define BYTES_TO_OWORDS(bcount) ((bcount) >> 4)
+
+#define VID_IQ_SIZE_DW BYTES_TO_DWORDS(VID_IQ_SIZE)
+#define VID_CDT_SIZE_QW BYTES_TO_QWORDS(VID_CDT_SIZE)
+#define VID_CLUSTER_SIZE_OW BYTES_TO_OWORDS(VID_CLUSTER_SIZE)
+
+#define AUDIO_IQ_SIZE_DW BYTES_TO_DWORDS(AUDIO_IQ_SIZE)
+#define AUDIO_CDT_SIZE_QW BYTES_TO_QWORDS(AUDIO_CDT_SIZE)
+#define AUDIO_CLUSTER_SIZE_QW BYTES_TO_QWORDS(AUDIO_CLUSTER_SIZE)
+
+#define MBIF_IQ_SIZE_DW BYTES_TO_DWORDS(MBIF_IQ_SIZE)
+#define MBIF_CDT_SIZE_QW BYTES_TO_QWORDS(MBIF_CDT_SIZE)
+#define MBIF_CLUSTER_SIZE_OW BYTES_TO_OWORDS(MBIF_CLUSTER_SIZE)
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
new file mode 100644
index 000000000..1b80c990c
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -0,0 +1,776 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * 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> cx25821 driver
+ * Parts adapted/taken from Eduardo Moscoso Rubino
+ * Copyright (C) 2009 Eduardo Moscoso Rubino <moscoso@TopoLogica.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821-video.h"
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(video_nr, int, NULL, 0444);
+
+MODULE_PARM_DESC(video_nr, "video 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]");
+
+#define FORMAT_FLAGS_PACKED 0x01
+
+static const struct cx25821_fmt formats[] = {
+ {
+ .fourcc = V4L2_PIX_FMT_Y41P,
+ .depth = 12,
+ .flags = FORMAT_FLAGS_PACKED,
+ }, {
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .depth = 16,
+ .flags = FORMAT_FLAGS_PACKED,
+ },
+};
+
+static const struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(formats); i++)
+ if (formats[i].fourcc == fourcc)
+ return formats + i;
+ return NULL;
+}
+
+int cx25821_start_video_dma(struct cx25821_dev *dev,
+ struct cx25821_dmaqueue *q,
+ struct cx25821_buffer *buf,
+ const 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);
+
+ /* 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_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
+{
+ int handled = 0;
+ u32 mask;
+ const struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+
+ 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)) {
+ pr_warn("%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) {
+ struct cx25821_dmaqueue *dmaq =
+ &dev->channels[channel->i].dma_vidq;
+ struct cx25821_buffer *buf;
+
+ spin_lock(&dev->slock);
+ if (!list_empty(&dmaq->active)) {
+ buf = list_entry(dmaq->active.next,
+ struct cx25821_buffer, queue);
+
+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
+ buf->vb.sequence = dmaq->count++;
+ list_del(&buf->queue);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+ }
+ spin_unlock(&dev->slock);
+ handled++;
+ }
+ return handled;
+}
+
+static int cx25821_queue_setup(struct vb2_queue *q,
+ unsigned int *num_buffers, unsigned int *num_planes,
+ unsigned int sizes[], struct device *alloc_devs[])
+{
+ struct cx25821_channel *chan = q->drv_priv;
+ unsigned size = (chan->fmt->depth * chan->width * chan->height) >> 3;
+
+ if (*num_planes)
+ return sizes[0] < size ? -EINVAL : 0;
+
+ *num_planes = 1;
+ sizes[0] = size;
+ return 0;
+}
+
+static int cx25821_buffer_prepare(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
+ struct cx25821_dev *dev = chan->dev;
+ struct cx25821_buffer *buf =
+ container_of(vbuf, struct cx25821_buffer, vb);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
+ u32 line0_offset;
+ int bpl_local = LINE_SIZE_D1;
+ int ret;
+
+ if (chan->pixel_formats == PIXEL_FRMT_411)
+ buf->bpl = (chan->fmt->depth * chan->width) >> 3;
+ else
+ buf->bpl = (chan->fmt->depth >> 3) * chan->width;
+
+ if (vb2_plane_size(vb, 0) < chan->height * buf->bpl)
+ return -EINVAL;
+ vb2_set_plane_payload(vb, 0, chan->height * buf->bpl);
+ buf->vb.field = chan->field;
+
+ if (chan->pixel_formats == PIXEL_FRMT_411) {
+ bpl_local = buf->bpl;
+ } else {
+ bpl_local = buf->bpl; /* Default */
+
+ if (chan->use_cif_resolution) {
+ if (dev->tvnorm & V4L2_STD_625_50)
+ bpl_local = 352 << 1;
+ else
+ bpl_local = chan->cif_width << 1;
+ }
+ }
+
+ switch (chan->field) {
+ case V4L2_FIELD_TOP:
+ ret = cx25821_risc_buffer(dev->pci, &buf->risc,
+ sgt->sgl, 0, UNSET,
+ buf->bpl, 0, chan->height);
+ break;
+ case V4L2_FIELD_BOTTOM:
+ ret = cx25821_risc_buffer(dev->pci, &buf->risc,
+ sgt->sgl, UNSET, 0,
+ buf->bpl, 0, chan->height);
+ break;
+ case V4L2_FIELD_INTERLACED:
+ /* All other formats are top field first */
+ line0_offset = 0;
+ dprintk(1, "top field first\n");
+
+ ret = cx25821_risc_buffer(dev->pci, &buf->risc,
+ sgt->sgl, line0_offset,
+ bpl_local, bpl_local, bpl_local,
+ chan->height >> 1);
+ break;
+ case V4L2_FIELD_SEQ_TB:
+ ret = cx25821_risc_buffer(dev->pci, &buf->risc,
+ sgt->sgl,
+ 0, buf->bpl * (chan->height >> 1),
+ buf->bpl, 0, chan->height >> 1);
+ break;
+ case V4L2_FIELD_SEQ_BT:
+ ret = cx25821_risc_buffer(dev->pci, &buf->risc,
+ sgt->sgl,
+ buf->bpl * (chan->height >> 1), 0,
+ buf->bpl, 0, chan->height >> 1);
+ break;
+ default:
+ WARN_ON(1);
+ ret = -EINVAL;
+ break;
+ }
+
+ dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp 0x%08x - dma=0x%08lx\n",
+ buf, buf->vb.vb2_buf.index, chan->width, chan->height,
+ chan->fmt->depth, chan->fmt->fourcc,
+ (unsigned long)buf->risc.dma);
+
+ return ret;
+}
+
+static void cx25821_buffer_finish(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct cx25821_buffer *buf =
+ container_of(vbuf, struct cx25821_buffer, vb);
+ struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
+ struct cx25821_dev *dev = chan->dev;
+
+ cx25821_free_buffer(dev, buf);
+}
+
+static void cx25821_buffer_queue(struct vb2_buffer *vb)
+{
+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ struct cx25821_buffer *buf =
+ container_of(vbuf, struct cx25821_buffer, vb);
+ struct cx25821_channel *chan = vb->vb2_queue->drv_priv;
+ struct cx25821_dev *dev = chan->dev;
+ struct cx25821_buffer *prev;
+ struct cx25821_dmaqueue *q = &dev->channels[chan->id].dma_vidq;
+
+ buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 12);
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 12);
+ buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+ if (list_empty(&q->active)) {
+ list_add_tail(&buf->queue, &q->active);
+ } else {
+ buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
+ prev = list_entry(q->active.prev, struct cx25821_buffer,
+ queue);
+ list_add_tail(&buf->queue, &q->active);
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+ }
+}
+
+static int cx25821_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+ struct cx25821_channel *chan = q->drv_priv;
+ struct cx25821_dev *dev = chan->dev;
+ struct cx25821_dmaqueue *dmaq = &dev->channels[chan->id].dma_vidq;
+ struct cx25821_buffer *buf = list_entry(dmaq->active.next,
+ struct cx25821_buffer, queue);
+
+ dmaq->count = 0;
+ cx25821_start_video_dma(dev, dmaq, buf, chan->sram_channels);
+ return 0;
+}
+
+static void cx25821_stop_streaming(struct vb2_queue *q)
+{
+ struct cx25821_channel *chan = q->drv_priv;
+ struct cx25821_dev *dev = chan->dev;
+ struct cx25821_dmaqueue *dmaq = &dev->channels[chan->id].dma_vidq;
+ unsigned long flags;
+
+ cx_write(chan->sram_channels->dma_ctl, 0); /* FIFO and RISC disable */
+ spin_lock_irqsave(&dev->slock, flags);
+ while (!list_empty(&dmaq->active)) {
+ struct cx25821_buffer *buf = list_entry(dmaq->active.next,
+ struct cx25821_buffer, queue);
+
+ list_del(&buf->queue);
+ vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+ }
+ spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+static const struct vb2_ops cx25821_video_qops = {
+ .queue_setup = cx25821_queue_setup,
+ .buf_prepare = cx25821_buffer_prepare,
+ .buf_finish = cx25821_buffer_finish,
+ .buf_queue = cx25821_buffer_queue,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+ .start_streaming = cx25821_start_streaming,
+ .stop_streaming = cx25821_stop_streaming,
+};
+
+/* VIDEO IOCTLS */
+
+static int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ if (unlikely(f->index >= ARRAY_SIZE(formats)))
+ return -EINVAL;
+
+ f->pixelformat = formats[f->index].fourcc;
+
+ return 0;
+}
+
+static int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_channel *chan = video_drvdata(file);
+
+ f->fmt.pix.width = chan->width;
+ f->fmt.pix.height = chan->height;
+ f->fmt.pix.field = chan->field;
+ f->fmt.pix.pixelformat = chan->fmt->fourcc;
+ f->fmt.pix.bytesperline = (chan->width * chan->fmt->depth) >> 3;
+ f->fmt.pix.sizeimage = chan->height * f->fmt.pix.bytesperline;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+ return 0;
+}
+
+static int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_channel *chan = video_drvdata(file);
+ struct cx25821_dev *dev = chan->dev;
+ const struct cx25821_fmt *fmt;
+ enum v4l2_field field = f->fmt.pix.field;
+ unsigned int maxh;
+ unsigned w;
+
+ fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
+ if (NULL == fmt)
+ return -EINVAL;
+ maxh = (dev->tvnorm & V4L2_STD_625_50) ? 576 : 480;
+
+ w = f->fmt.pix.width;
+ if (field != V4L2_FIELD_BOTTOM)
+ field = V4L2_FIELD_TOP;
+ if (w < 352) {
+ w = 176;
+ f->fmt.pix.height = maxh / 4;
+ } else if (w < 720) {
+ w = 352;
+ f->fmt.pix.height = maxh / 2;
+ } else {
+ w = 720;
+ f->fmt.pix.height = maxh;
+ field = V4L2_FIELD_INTERLACED;
+ }
+ f->fmt.pix.field = field;
+ f->fmt.pix.width = w;
+ f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
+ f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_channel *chan = video_drvdata(file);
+ struct cx25821_dev *dev = chan->dev;
+ int pix_format = PIXEL_FRMT_422;
+ int err;
+
+ err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f);
+
+ if (0 != err)
+ return err;
+
+ chan->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
+ chan->field = f->fmt.pix.field;
+ chan->width = f->fmt.pix.width;
+ chan->height = f->fmt.pix.height;
+
+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+ pix_format = PIXEL_FRMT_411;
+ else
+ pix_format = PIXEL_FRMT_422;
+
+ cx25821_set_pixel_format(dev, SRAM_CH00, pix_format);
+
+ /* check if cif resolution */
+ if (chan->width == 320 || chan->width == 352)
+ chan->use_cif_resolution = 1;
+ else
+ chan->use_cif_resolution = 0;
+
+ chan->cif_width = chan->width;
+ medusa_set_resolution(dev, chan->width, SRAM_CH00);
+ return 0;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+ struct cx25821_channel *chan = video_drvdata(file);
+ struct cx25821_dev *dev = chan->dev;
+ const struct sram_channel *sram_ch = chan->sram_channels;
+ u32 tmp = 0;
+
+ tmp = cx_read(sram_ch->dma_ctl);
+ pr_info("Video input 0 is %s\n",
+ (tmp & 0x11) ? "streaming" : "stopped");
+ return 0;
+}
+
+
+static int cx25821_vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ struct cx25821_channel *chan = video_drvdata(file);
+ struct cx25821_dev *dev = chan->dev;
+
+ strscpy(cap->driver, "cx25821", sizeof(cap->driver));
+ strscpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card));
+ sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
+ V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
+ V4L2_CAP_DEVICE_CAPS;
+ return 0;
+}
+
+static int cx25821_vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
+{
+ struct cx25821_channel *chan = video_drvdata(file);
+
+ *tvnorms = chan->dev->tvnorm;
+ return 0;
+}
+
+static int cx25821_vidioc_s_std(struct file *file, void *priv,
+ v4l2_std_id tvnorms)
+{
+ struct cx25821_channel *chan = video_drvdata(file);
+ struct cx25821_dev *dev = chan->dev;
+
+ if (dev->tvnorm == tvnorms)
+ return 0;
+
+ dev->tvnorm = tvnorms;
+ chan->width = 720;
+ chan->height = (dev->tvnorm & V4L2_STD_625_50) ? 576 : 480;
+
+ medusa_set_videostandard(dev);
+
+ return 0;
+}
+
+static int cx25821_vidioc_enum_input(struct file *file, void *priv,
+ struct v4l2_input *i)
+{
+ if (i->index)
+ return -EINVAL;
+
+ i->type = V4L2_INPUT_TYPE_CAMERA;
+ i->std = CX25821_NORMS;
+ strscpy(i->name, "Composite", sizeof(i->name));
+ return 0;
+}
+
+static int cx25821_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+ *i = 0;
+ return 0;
+}
+
+static int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+ return i ? -EINVAL : 0;
+}
+
+static int cx25821_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct cx25821_channel *chan =
+ container_of(ctrl->handler, struct cx25821_channel, hdl);
+ struct cx25821_dev *dev = chan->dev;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ medusa_set_brightness(dev, ctrl->val, chan->id);
+ break;
+ case V4L2_CID_HUE:
+ medusa_set_hue(dev, ctrl->val, chan->id);
+ break;
+ case V4L2_CID_CONTRAST:
+ medusa_set_contrast(dev, ctrl->val, chan->id);
+ break;
+ case V4L2_CID_SATURATION:
+ medusa_set_saturation(dev, ctrl->val, chan->id);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int cx25821_vidioc_enum_output(struct file *file, void *priv,
+ struct v4l2_output *o)
+{
+ if (o->index)
+ return -EINVAL;
+
+ o->type = V4L2_INPUT_TYPE_CAMERA;
+ o->std = CX25821_NORMS;
+ strscpy(o->name, "Composite", sizeof(o->name));
+ return 0;
+}
+
+static int cx25821_vidioc_g_output(struct file *file, void *priv, unsigned int *o)
+{
+ *o = 0;
+ return 0;
+}
+
+static int cx25821_vidioc_s_output(struct file *file, void *priv, unsigned int o)
+{
+ return o ? -EINVAL : 0;
+}
+
+static int cx25821_vidioc_try_fmt_vid_out(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_channel *chan = video_drvdata(file);
+ struct cx25821_dev *dev = chan->dev;
+ const struct cx25821_fmt *fmt;
+
+ fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
+ if (NULL == fmt)
+ return -EINVAL;
+ f->fmt.pix.width = 720;
+ f->fmt.pix.height = (dev->tvnorm & V4L2_STD_625_50) ? 576 : 480;
+ f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+ f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
+ f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ return 0;
+}
+
+static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct cx25821_channel *chan = video_drvdata(file);
+ int err;
+
+ err = cx25821_vidioc_try_fmt_vid_out(file, priv, f);
+
+ if (0 != err)
+ return err;
+
+ chan->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
+ chan->field = f->fmt.pix.field;
+ chan->width = f->fmt.pix.width;
+ chan->height = f->fmt.pix.height;
+ if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+ chan->pixel_formats = PIXEL_FRMT_411;
+ else
+ chan->pixel_formats = PIXEL_FRMT_422;
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops cx25821_ctrl_ops = {
+ .s_ctrl = cx25821_s_ctrl,
+};
+
+static const struct v4l2_file_operations video_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .read = vb2_fop_read,
+ .poll = vb2_fop_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .mmap = vb2_fop_mmap,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+ .vidioc_querycap = cx25821_vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+ .vidioc_g_std = cx25821_vidioc_g_std,
+ .vidioc_s_std = cx25821_vidioc_s_std,
+ .vidioc_enum_input = cx25821_vidioc_enum_input,
+ .vidioc_g_input = cx25821_vidioc_g_input,
+ .vidioc_s_input = cx25821_vidioc_s_input,
+ .vidioc_log_status = vidioc_log_status,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static const struct video_device cx25821_video_device = {
+ .name = "cx25821-video",
+ .fops = &video_fops,
+ .release = video_device_release_empty,
+ .minor = -1,
+ .ioctl_ops = &video_ioctl_ops,
+ .tvnorms = CX25821_NORMS,
+ .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+ V4L2_CAP_STREAMING,
+};
+
+static const struct v4l2_file_operations video_out_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .write = vb2_fop_write,
+ .poll = vb2_fop_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .mmap = vb2_fop_mmap,
+};
+
+static const struct v4l2_ioctl_ops video_out_ioctl_ops = {
+ .vidioc_querycap = cx25821_vidioc_querycap,
+ .vidioc_enum_fmt_vid_out = cx25821_vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_out = cx25821_vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_out = cx25821_vidioc_try_fmt_vid_out,
+ .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
+ .vidioc_g_std = cx25821_vidioc_g_std,
+ .vidioc_s_std = cx25821_vidioc_s_std,
+ .vidioc_enum_output = cx25821_vidioc_enum_output,
+ .vidioc_g_output = cx25821_vidioc_g_output,
+ .vidioc_s_output = cx25821_vidioc_s_output,
+ .vidioc_log_status = vidioc_log_status,
+};
+
+static const struct video_device cx25821_video_out_device = {
+ .name = "cx25821-video",
+ .fops = &video_out_fops,
+ .release = video_device_release_empty,
+ .minor = -1,
+ .ioctl_ops = &video_out_ioctl_ops,
+ .tvnorms = CX25821_NORMS,
+ .device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_READWRITE,
+};
+
+void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num)
+{
+ cx_clear(PCI_INT_MSK, 1);
+
+ if (video_is_registered(&dev->channels[chan_num].vdev)) {
+ video_unregister_device(&dev->channels[chan_num].vdev);
+ v4l2_ctrl_handler_free(&dev->channels[chan_num].hdl);
+ }
+}
+
+int cx25821_video_register(struct cx25821_dev *dev)
+{
+ int err;
+ int i;
+
+ /* initial device configuration */
+ dev->tvnorm = V4L2_STD_NTSC_M;
+
+ spin_lock_init(&dev->slock);
+
+ for (i = 0; i < MAX_VID_CAP_CHANNEL_NUM - 1; ++i) {
+ struct cx25821_channel *chan = &dev->channels[i];
+ struct video_device *vdev = &chan->vdev;
+ struct v4l2_ctrl_handler *hdl = &chan->hdl;
+ struct vb2_queue *q;
+ bool is_output = i > SRAM_CH08;
+
+ if (i == SRAM_CH08) /* audio channel */
+ continue;
+
+ if (!is_output) {
+ v4l2_ctrl_handler_init(hdl, 4);
+ v4l2_ctrl_new_std(hdl, &cx25821_ctrl_ops,
+ V4L2_CID_BRIGHTNESS, 0, 10000, 1, 6200);
+ v4l2_ctrl_new_std(hdl, &cx25821_ctrl_ops,
+ V4L2_CID_CONTRAST, 0, 10000, 1, 5000);
+ v4l2_ctrl_new_std(hdl, &cx25821_ctrl_ops,
+ V4L2_CID_SATURATION, 0, 10000, 1, 5000);
+ v4l2_ctrl_new_std(hdl, &cx25821_ctrl_ops,
+ V4L2_CID_HUE, 0, 10000, 1, 5000);
+ if (hdl->error) {
+ err = hdl->error;
+ goto fail_unreg;
+ }
+ err = v4l2_ctrl_handler_setup(hdl);
+ if (err)
+ goto fail_unreg;
+ } else {
+ chan->out = &dev->vid_out_data[i - SRAM_CH09];
+ chan->out->chan = chan;
+ }
+
+ chan->sram_channels = &cx25821_sram_channels[i];
+ chan->width = 720;
+ chan->field = V4L2_FIELD_INTERLACED;
+ if (dev->tvnorm & V4L2_STD_625_50)
+ chan->height = 576;
+ else
+ chan->height = 480;
+
+ if (chan->pixel_formats == PIXEL_FRMT_411)
+ chan->fmt = cx25821_format_by_fourcc(V4L2_PIX_FMT_Y41P);
+ else
+ chan->fmt = cx25821_format_by_fourcc(V4L2_PIX_FMT_YUYV);
+
+ cx_write(chan->sram_channels->int_stat, 0xffffffff);
+
+ INIT_LIST_HEAD(&chan->dma_vidq.active);
+
+ q = &chan->vidq;
+
+ q->type = is_output ? V4L2_BUF_TYPE_VIDEO_OUTPUT :
+ V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+ q->io_modes |= is_output ? VB2_WRITE : VB2_READ;
+ q->gfp_flags = GFP_DMA32;
+ q->min_buffers_needed = 2;
+ q->drv_priv = chan;
+ q->buf_struct_size = sizeof(struct cx25821_buffer);
+ q->ops = &cx25821_video_qops;
+ q->mem_ops = &vb2_dma_sg_memops;
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ q->lock = &dev->lock;
+ q->dev = &dev->pci->dev;
+
+ if (!is_output) {
+ err = vb2_queue_init(q);
+ if (err < 0)
+ goto fail_unreg;
+ }
+
+ /* register v4l devices */
+ *vdev = is_output ? cx25821_video_out_device : cx25821_video_device;
+ vdev->v4l2_dev = &dev->v4l2_dev;
+ if (!is_output)
+ vdev->ctrl_handler = hdl;
+ else
+ vdev->vfl_dir = VFL_DIR_TX;
+ vdev->lock = &dev->lock;
+ vdev->queue = q;
+ snprintf(vdev->name, sizeof(vdev->name), "%s #%d", dev->name, i);
+ video_set_drvdata(vdev, chan);
+
+ err = video_register_device(vdev, VFL_TYPE_VIDEO,
+ video_nr[dev->nr]);
+
+ if (err < 0)
+ goto fail_unreg;
+ }
+
+ /* set PCI interrupt */
+ cx_set(PCI_INT_MSK, 0xff);
+
+ return 0;
+
+fail_unreg:
+ while (i >= 0)
+ cx25821_video_unregister(dev, i--);
+ return err;
+}
diff --git a/drivers/media/pci/cx25821/cx25821-video.h b/drivers/media/pci/cx25821/cx25821-video.h
new file mode 100644
index 000000000..cf0d3f550
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-video.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * 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
+ */
+
+#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>
+#include <media/v4l2-event.h>
+
+#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)
+
+#define FORMAT_FLAGS_PACKED 0x01
+extern void cx25821_video_wakeup(struct cx25821_dev *dev,
+ struct cx25821_dmaqueue *q, u32 count);
+
+extern int cx25821_start_video_dma(struct cx25821_dev *dev,
+ struct cx25821_dmaqueue *q,
+ struct cx25821_buffer *buf,
+ const struct sram_channel *channel);
+
+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);
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821.h b/drivers/media/pci/cx25821/cx25821.h
new file mode 100644
index 000000000..3aa7604fb
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821.h
@@ -0,0 +1,426 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * 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
+ */
+
+#ifndef CX25821_H_
+#define CX25821_H_
+
+#include <linux/pci.h>
+#include <linux/i2c.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/v4l2-ctrls.h>
+#include <media/videobuf2-v4l2.h>
+#include <media/videobuf2-dma-sg.h>
+
+#include "cx25821-reg.h"
+#include "cx25821-medusa-reg.h"
+#include "cx25821-sram.h"
+#include "cx25821-audio.h"
+
+#include <linux/mutex.h>
+
+#define UNSET (-1U)
+#define NO_SYNC_LINE (-1U)
+
+#define CX25821_MAXBOARDS 2
+
+#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 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 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
+
+/*
+ * Maximum capture-only channels. This can go away once video/audio output
+ * is fully supported in this driver.
+ */
+#define MAX_VID_CAP_CHANNEL_NUM 10
+
+#define VID_CHANNEL_NUM 8
+
+struct cx25821_fmt {
+ u32 fourcc; /* v4l2 format id */
+ int depth;
+ int flags;
+ u32 cxformat;
+};
+
+struct cx25821_tvnorm {
+ char *name;
+ v4l2_std_id id;
+ u32 cxiformat;
+ u32 cxoformat;
+};
+
+enum cx25821_src_sel_type {
+ CX25821_SRC_SEL_EXT_656_VIDEO = 0,
+ CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO
+};
+
+struct cx25821_riscmem {
+ unsigned int size;
+ __le32 *cpu;
+ __le32 *jmp;
+ dma_addr_t dma;
+};
+
+/* buffer for one video frame */
+struct cx25821_buffer {
+ /* common v4l buffer stuff -- must be first */
+ struct vb2_v4l2_buffer vb;
+ struct list_head queue;
+
+ /* cx25821 specific */
+ unsigned int bpl;
+ struct cx25821_riscmem risc;
+ const struct cx25821_fmt *fmt;
+};
+
+enum port {
+ CX25821_UNDEFINED = 0,
+ CX25821_RAW,
+ CX25821_264
+};
+
+struct cx25821_board {
+ const char *name;
+ enum port porta;
+ enum port portb;
+ enum port portc;
+
+ u32 clk_freq;
+};
+
+struct cx25821_i2c {
+ struct cx25821_dev *dev;
+
+ int nr;
+
+ /* i2c i/o */
+ struct i2c_adapter i2c_adap;
+ struct i2c_client i2c_client;
+ u32 i2c_rc;
+
+ /* cx25821 registers used for raw address */
+ 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;
+ u32 count;
+};
+
+struct cx25821_dev;
+
+struct cx25821_channel;
+
+struct cx25821_video_out_data {
+ struct cx25821_channel *chan;
+ 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;
+ 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;
+
+ u32 upstream_riscbuf_size;
+ u32 upstream_databuf_size;
+ int is_60hz;
+ int _frame_index;
+ int cur_frame_index;
+ int curpos;
+ wait_queue_head_t waitq;
+};
+
+struct cx25821_channel {
+ unsigned id;
+ struct cx25821_dev *dev;
+
+ struct v4l2_ctrl_handler hdl;
+
+ struct video_device vdev;
+ struct cx25821_dmaqueue dma_vidq;
+ struct vb2_queue vidq;
+
+ const struct sram_channel *sram_channels;
+
+ const struct cx25821_fmt *fmt;
+ unsigned field;
+ unsigned int width, height;
+ int pixel_formats;
+ int use_cif_resolution;
+ int cif_width;
+
+ /* video output data for the video output channel */
+ struct cx25821_video_out_data *out;
+};
+
+struct snd_card;
+
+struct cx25821_dev {
+ struct v4l2_device v4l2_dev;
+
+ /* 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;
+ /* used by cx25821-alsa */
+ struct snd_card *card;
+
+ u32 clk_freq;
+
+ /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
+ struct cx25821_i2c i2c_bus[3];
+
+ int nr;
+ struct mutex lock;
+
+ struct cx25821_channel channels[MAX_VID_CHANNEL_NUM];
+
+ /* board details */
+ unsigned int board;
+ char name[32];
+
+ /* Analog video */
+ unsigned int input;
+ v4l2_std_id tvnorm;
+ unsigned short _max_num_decoders;
+
+ /* 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;
+ 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;
+ u32 audio_upstream_riscbuf_size;
+ u32 audio_upstream_databuf_size;
+ int _audioframe_index;
+ struct work_struct _audio_work_entry;
+ char *input_audiofilename;
+
+ /* V4l */
+ spinlock_t slock;
+
+ /* Video Upstream */
+ struct cx25821_video_out_data vid_out_data[2];
+};
+
+static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev)
+{
+ return container_of(v4l2_dev, struct cx25821_dev, v4l2_dev);
+}
+
+extern struct cx25821_board cx25821_boards[];
+
+#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
+
+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 const struct sram_channel cx25821_sram_channels[];
+
+#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...) \
+ pr_err("(%d): " fmt, dev->board, ##args)
+#define CX25821_WARN(fmt, args...) \
+ pr_warn("(%d): " fmt, dev->board, ##args)
+#define CX25821_INFO(fmt, args...) \
+ pr_info("(%d): " fmt, dev->board, ##args)
+
+extern int cx25821_i2c_register(struct cx25821_i2c *bus);
+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,
+ const struct sram_channel *ch, unsigned int bpl,
+ u32 risc);
+
+extern int cx25821_riscmem_alloc(struct pci_dev *pci,
+ struct cx25821_riscmem *risc,
+ unsigned int size);
+extern int cx25821_risc_buffer(struct pci_dev *pci, struct cx25821_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 cx25821_riscmem *risc,
+ struct scatterlist *sglist,
+ unsigned int bpl,
+ unsigned int lines, unsigned int lpi);
+extern void cx25821_free_buffer(struct cx25821_dev *dev,
+ struct cx25821_buffer *buf);
+extern void cx25821_sram_channel_dump(struct cx25821_dev *dev,
+ const struct sram_channel *ch);
+extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
+ const 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,
+ const struct sram_channel *ch,
+ unsigned int bpl, u32 risc);
+
+extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel,
+ u32 format);
+
+#endif