diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-14 19:13:30 +0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-15 23:36:22 +0400 |
commit | b285192a43f0432d82c2c10974204e78af0da596 (patch) | |
tree | 618aa87e760c9c949eca9e4df6ae0eeffa11dcfc /drivers/media/video/cx88 | |
parent | 68de959f773a1d49096835c411390bceff5d1549 (diff) | |
download | linux-b285192a43f0432d82c2c10974204e78af0da596.tar.xz |
[media] rename most media/video pci drivers to media/pci
Rename all PCI drivers with their own directory under
drivers/media/video into drivers/media/pci and update the
building system.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx88')
-rw-r--r-- | drivers/media/video/cx88/Kconfig | 86 | ||||
-rw-r--r-- | drivers/media/video/cx88/Makefile | 16 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-alsa.c | 975 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-blackbird.c | 1299 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-cards.c | 3811 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-core.c | 1131 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-dsp.c | 322 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-dvb.c | 1778 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-i2c.c | 184 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-input.c | 635 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-mpeg.c | 929 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-reg.h | 836 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-tvaudio.c | 1059 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-vbi.c | 245 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-video.c | 2075 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-vp3054-i2c.c | 159 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-vp3054-i2c.h | 41 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88.h | 748 |
18 files changed, 0 insertions, 16329 deletions
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig deleted file mode 100644 index 3598dc087b08..000000000000 --- a/drivers/media/video/cx88/Kconfig +++ /dev/null @@ -1,86 +0,0 @@ -config VIDEO_CX88 - tristate "Conexant 2388x (bt878 successor) support" - depends on VIDEO_DEV && PCI && I2C && RC_CORE - select I2C_ALGOBIT - select VIDEO_BTCX - select VIDEOBUF_DMA_SG - select VIDEO_TUNER - select VIDEO_TVEEPROM - select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO - ---help--- - This is a video4linux driver for Conexant 2388x based - TV cards. - - To compile this driver as a module, choose M here: the - module will be called cx8800 - -config VIDEO_CX88_ALSA - tristate "Conexant 2388x DMA audio support" - depends on VIDEO_CX88 && SND - select SND_PCM - ---help--- - This is a video4linux driver for direct (DMA) audio on - Conexant 2388x based TV 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 cx88-alsa. - -config VIDEO_CX88_BLACKBIRD - tristate "Blackbird MPEG encoder support (cx2388x + cx23416)" - depends on VIDEO_CX88 - select VIDEO_CX2341X - ---help--- - This adds support for MPEG encoder cards based on the - Blackbird reference design, using the Conexant 2388x - and 23416 chips. - - To compile this driver as a module, choose M here: the - module will be called cx88-blackbird. - -config VIDEO_CX88_DVB - tristate "DVB/ATSC Support for cx2388x based TV cards" - depends on VIDEO_CX88 && DVB_CORE - select VIDEOBUF_DVB - select DVB_PLL if !DVB_FE_CUSTOMISE - select DVB_MT352 if !DVB_FE_CUSTOMISE - select DVB_ZL10353 if !DVB_FE_CUSTOMISE - select DVB_OR51132 if !DVB_FE_CUSTOMISE - select DVB_CX22702 if !DVB_FE_CUSTOMISE - select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_NXT200X if !DVB_FE_CUSTOMISE - select DVB_CX24123 if !DVB_FE_CUSTOMISE - select DVB_ISL6421 if !DVB_FE_CUSTOMISE - select DVB_S5H1411 if !DVB_FE_CUSTOMISE - select DVB_CX24116 if !DVB_FE_CUSTOMISE - select DVB_STV0299 if !DVB_FE_CUSTOMISE - select DVB_STV0288 if !DVB_FE_CUSTOMISE - select DVB_STB6000 if !DVB_FE_CUSTOMISE - select DVB_STV0900 if !DVB_FE_CUSTOMISE - select DVB_STB6100 if !DVB_FE_CUSTOMISE - select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE - ---help--- - This adds support for DVB/ATSC cards based on the - Conexant 2388x chip. - - To compile this driver as a module, choose M here: the - module will be called cx88-dvb. - -config VIDEO_CX88_VP3054 - tristate "VP-3054 Secondary I2C Bus Support" - default m - depends on VIDEO_CX88_DVB && DVB_MT352 - ---help--- - This adds DVB-T support for cards based on the - Conexant 2388x chip and the MT352 demodulator, - which also require support for the VP-3054 - Secondary I2C bus, such at DNTV Live! DVB-T Pro. - -config VIDEO_CX88_MPEG - tristate - depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD - default y diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile deleted file mode 100644 index 884b4cdd8ff0..000000000000 --- a/drivers/media/video/cx88/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -cx88xx-objs := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o \ - cx88-dsp.o cx88-input.o -cx8800-objs := cx88-video.o cx88-vbi.o -cx8802-objs := cx88-mpeg.o - -obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o -obj-$(CONFIG_VIDEO_CX88_MPEG) += cx8802.o -obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o -obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx88-blackbird.o -obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o -obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o - -ccflags-y += -Idrivers/media/video -ccflags-y += -Idrivers/media/tuners -ccflags-y += -Idrivers/media/dvb-core -ccflags-y += -Idrivers/media/dvb-frontends diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c deleted file mode 100644 index 3aa6856ead3b..000000000000 --- a/drivers/media/video/cx88/cx88-alsa.c +++ /dev/null @@ -1,975 +0,0 @@ -/* - * - * Support for audio capture - * PCI function #1 of the cx2388x. - * - * (c) 2007 Trent Piepho <xyzzy@speakeasy.org> - * (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org> - * (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org> - * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org> - * Based on dummy.c by Jaroslav Kysela <perex@perex.cz> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/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 <asm/delay.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/control.h> -#include <sound/initval.h> -#include <sound/tlv.h> -#include <media/wm8775.h> - -#include "cx88.h" -#include "cx88-reg.h" - -#define dprintk(level,fmt, arg...) if (debug >= level) \ - printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg) - -#define dprintk_core(level,fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg) - -/**************************************************************************** - Data type declarations - Can be moded to a header file later - ****************************************************************************/ - -struct cx88_audio_buffer { - unsigned int bpl; - struct btcx_riscmem risc; - struct videobuf_dmabuf dma; -}; - -struct cx88_audio_dev { - struct cx88_core *core; - struct cx88_dmaqueue q; - - /* pci i/o */ - struct pci_dev *pci; - - /* audio controls */ - int irq; - - struct snd_card *card; - - spinlock_t reg_lock; - atomic_t count; - - unsigned int dma_size; - unsigned int period_size; - unsigned int num_periods; - - struct videobuf_dmabuf *dma_risc; - - struct cx88_audio_buffer *buf; - - struct snd_pcm_substream *substream; -}; -typedef struct cx88_audio_dev snd_cx88_card_t; - - - -/**************************************************************************** - Module global static vars - ****************************************************************************/ - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ -static const char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; - -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled."); - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s)."); - - -/**************************************************************************** - Module macros - ****************************************************************************/ - -MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards"); -MODULE_AUTHOR("Ricardo Cerqueira"); -MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(CX88_VERSION); - -MODULE_SUPPORTED_DEVICE("{{Conexant,23881}," - "{{Conexant,23882}," - "{{Conexant,23883}"); -static unsigned int debug; -module_param(debug,int,0644); -MODULE_PARM_DESC(debug,"enable debug messages"); - -/**************************************************************************** - Module specific funtions - ****************************************************************************/ - -/* - * BOARD Specific: Sets audio DMA - */ - -static int _cx88_start_audio_dma(snd_cx88_card_t *chip) -{ - struct cx88_audio_buffer *buf = chip->buf; - struct cx88_core *core=chip->core; - const struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25]; - - /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */ - cx_clear(MO_AUD_DMACNTRL, 0x11); - - /* setup fifo + format - out channel */ - cx88_sram_channel_setup(chip->core, audio_ch, buf->bpl, buf->risc.dma); - - /* sets bpl size */ - cx_write(MO_AUDD_LNGTH, buf->bpl); - - /* reset counter */ - cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET); - atomic_set(&chip->count, 0); - - dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d " - "byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start + 8)>>1, - chip->num_periods, buf->bpl * chip->num_periods); - - /* Enables corresponding bits at AUD_INT_STAT */ - cx_write(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | - AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); - - /* Clean any pending interrupt bits already set */ - cx_write(MO_AUD_INTSTAT, ~0); - - /* enable audio irqs */ - cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | PCI_INT_AUDINT); - - /* start dma */ - cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */ - cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */ - - if (debug) - cx88_sram_channel_dump(chip->core, audio_ch); - - return 0; -} - -/* - * BOARD Specific: Resets audio DMA - */ -static int _cx88_stop_audio_dma(snd_cx88_card_t *chip) -{ - struct cx88_core *core=chip->core; - dprintk(1, "Stopping audio DMA\n"); - - /* stop dma */ - cx_clear(MO_AUD_DMACNTRL, 0x11); - - /* disable irqs */ - cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT); - cx_clear(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | - AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); - - if (debug) - cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]); - - return 0; -} - -#define MAX_IRQ_LOOP 50 - -/* - * BOARD Specific: IRQ dma bits - */ -static const char *cx88_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 cx8801_aud_irq(snd_cx88_card_t *chip) -{ - struct cx88_core *core = chip->core; - u32 status, mask; - - status = cx_read(MO_AUD_INTSTAT); - mask = cx_read(MO_AUD_INTMSK); - if (0 == (status & mask)) - return; - cx_write(MO_AUD_INTSTAT, status); - if (debug > 1 || (status & mask & ~0xff)) - cx88_print_irqbits(core->name, "irq aud", - cx88_aud_irqs, ARRAY_SIZE(cx88_aud_irqs), - status, mask); - /* risc op code error */ - if (status & AUD_INT_OPC_ERR) { - printk(KERN_WARNING "%s/1: Audio risc op code error\n",core->name); - cx_clear(MO_AUD_DMACNTRL, 0x11); - cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]); - } - if (status & AUD_INT_DN_SYNC) { - dprintk(1, "Downstream sync error\n"); - cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET); - return; - } - /* risc1 downstream */ - if (status & AUD_INT_DN_RISCI1) { - atomic_set(&chip->count, cx_read(MO_AUDD_GPCNT)); - snd_pcm_period_elapsed(chip->substream); - } - /* FIXME: Any other status should deserve a special handling? */ -} - -/* - * BOARD Specific: Handles IRQ calls - */ -static irqreturn_t cx8801_irq(int irq, void *dev_id) -{ - snd_cx88_card_t *chip = dev_id; - struct cx88_core *core = chip->core; - u32 status; - int loop, handled = 0; - - for (loop = 0; loop < MAX_IRQ_LOOP; loop++) { - status = cx_read(MO_PCI_INTSTAT) & - (core->pci_irqmask | PCI_INT_AUDINT); - if (0 == status) - goto out; - dprintk(3, "cx8801_irq loop %d/%d, status %x\n", - loop, MAX_IRQ_LOOP, status); - handled = 1; - cx_write(MO_PCI_INTSTAT, status); - - if (status & core->pci_irqmask) - cx88_core_irq(core, status); - if (status & PCI_INT_AUDINT) - cx8801_aud_irq(chip); - } - - if (MAX_IRQ_LOOP == loop) { - printk(KERN_ERR - "%s/1: IRQ loop detected, disabling interrupts\n", - core->name); - cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT); - } - - out: - return IRQ_RETVAL(handled); -} - - -static int dsp_buffer_free(snd_cx88_card_t *chip) -{ - BUG_ON(!chip->dma_size); - - dprintk(2,"Freeing buffer\n"); - videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc); - videobuf_dma_free(chip->dma_risc); - btcx_riscmem_free(chip->pci,&chip->buf->risc); - kfree(chip->buf); - - chip->dma_risc = NULL; - chip->dma_size = 0; - - return 0; -} - -/**************************************************************************** - ALSA PCM Interface - ****************************************************************************/ - -/* - * Digital hardware definition - */ -#define DEFAULT_FIFO_SIZE 4096 -static const struct snd_pcm_hardware snd_cx88_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/4, - .period_bytes_max = DEFAULT_FIFO_SIZE/4, - .periods_min = 1, - .periods_max = 1024, - .buffer_bytes_max = (1024*1024), -}; - -/* - * audio pcm capture open callback - */ -static int snd_cx88_pcm_open(struct snd_pcm_substream *substream) -{ - snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - if (!chip) { - printk(KERN_ERR "BUG: cx88 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_cx88_digital_hw; - - if (cx88_sram_channels[SRAM_CH25].fifo_size != DEFAULT_FIFO_SIZE) { - unsigned int bpl = cx88_sram_channels[SRAM_CH25].fifo_size / 4; - bpl &= ~7; /* must be multiple of 8 */ - 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_cx88_close(struct snd_pcm_substream *substream) -{ - return 0; -} - -/* - * hw_params callback - */ -static int snd_cx88_hw_params(struct snd_pcm_substream * substream, - struct snd_pcm_hw_params * hw_params) -{ - snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); - struct videobuf_dmabuf *dma; - - struct cx88_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; - - buf->bpl = chip->period_size; - - dma = &buf->dma; - videobuf_dma_init(dma); - ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, - (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT)); - if (ret < 0) - goto error; - - ret = videobuf_dma_map(&chip->pci->dev, dma); - if (ret < 0) - goto error; - - ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist, - chip->period_size, chip->num_periods, 1); - if (ret < 0) - 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); - - chip->buf = buf; - chip->dma_risc = dma; - - substream->runtime->dma_area = chip->dma_risc->vaddr; - substream->runtime->dma_bytes = chip->dma_size; - substream->runtime->dma_addr = 0; - return 0; - -error: - kfree(buf); - return ret; -} - -/* - * hw free callback - */ -static int snd_cx88_hw_free(struct snd_pcm_substream * substream) -{ - - snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); - - if (substream->runtime->dma_area) { - dsp_buffer_free(chip); - substream->runtime->dma_area = NULL; - } - - return 0; -} - -/* - * prepare callback - */ -static int snd_cx88_prepare(struct snd_pcm_substream *substream) -{ - return 0; -} - -/* - * trigger callback - */ -static int snd_cx88_card_trigger(struct snd_pcm_substream *substream, int cmd) -{ - snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); - int err; - - /* Local interrupts are already disabled by ALSA */ - spin_lock(&chip->reg_lock); - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - err=_cx88_start_audio_dma(chip); - break; - case SNDRV_PCM_TRIGGER_STOP: - err=_cx88_stop_audio_dma(chip); - break; - default: - err=-EINVAL; - break; - } - - spin_unlock(&chip->reg_lock); - - return err; -} - -/* - * pointer callback - */ -static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream) -{ - snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - u16 count; - - count = atomic_read(&chip->count); - -// dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __func__, -// count, new, count & (runtime->periods-1), -// runtime->period_size * (count & (runtime->periods-1))); - return runtime->period_size * (count & (runtime->periods-1)); -} - -/* - * page callback (needed for mmap) - */ -static struct page *snd_cx88_page(struct snd_pcm_substream *substream, - unsigned long offset) -{ - void *pageptr = substream->runtime->dma_area + offset; - return vmalloc_to_page(pageptr); -} - -/* - * operators - */ -static struct snd_pcm_ops snd_cx88_pcm_ops = { - .open = snd_cx88_pcm_open, - .close = snd_cx88_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_cx88_hw_params, - .hw_free = snd_cx88_hw_free, - .prepare = snd_cx88_prepare, - .trigger = snd_cx88_card_trigger, - .pointer = snd_cx88_pointer, - .page = snd_cx88_page, -}; - -/* - * create a PCM device - */ -static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, const char *name) -{ - int err; - struct snd_pcm *pcm; - - err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); - if (err < 0) - return err; - pcm->private_data = chip; - strcpy(pcm->name, name); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx88_pcm_ops); - - return 0; -} - -/**************************************************************************** - CONTROL INTERFACE - ****************************************************************************/ -static int snd_cx88_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 2; - info->value.integer.min = 0; - info->value.integer.max = 0x3f; - - return 0; -} - -static int snd_cx88_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); - struct cx88_core *core=chip->core; - int vol = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f), - bal = cx_read(AUD_BAL_CTL); - - value->value.integer.value[(bal & 0x40) ? 0 : 1] = vol; - vol -= (bal & 0x3f); - value->value.integer.value[(bal & 0x40) ? 1 : 0] = vol < 0 ? 0 : vol; - - return 0; -} - -static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); - struct cx88_core *core = chip->core; - int left = value->value.integer.value[0]; - int right = value->value.integer.value[1]; - int v, b; - - /* Pass volume & balance onto any WM8775 */ - if (left >= right) { - v = left << 10; - b = left ? (0x8000 * right) / left : 0x8000; - } else { - v = right << 10; - b = right ? 0xffff - (0x8000 * left) / right : 0x8000; - } - wm8775_s_ctrl(core, V4L2_CID_AUDIO_VOLUME, v); - wm8775_s_ctrl(core, V4L2_CID_AUDIO_BALANCE, b); -} - -/* OK - TODO: test it */ -static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); - struct cx88_core *core=chip->core; - int left, right, v, b; - int changed = 0; - u32 old; - - if (core->board.audio_chip == V4L2_IDENT_WM8775) - snd_cx88_wm8775_volume_put(kcontrol, value); - - left = value->value.integer.value[0] & 0x3f; - right = value->value.integer.value[1] & 0x3f; - b = right - left; - if (b < 0) { - v = 0x3f - left; - b = (-b) | 0x40; - } else { - v = 0x3f - right; - } - /* Do we really know this will always be called with IRQs on? */ - spin_lock_irq(&chip->reg_lock); - old = cx_read(AUD_VOL_CTL); - if (v != (old & 0x3f)) { - cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v); - changed = 1; - } - if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) { - cx_write(AUD_BAL_CTL, b); - changed = 1; - } - spin_unlock_irq(&chip->reg_lock); - - return changed; -} - -static const DECLARE_TLV_DB_SCALE(snd_cx88_db_scale, -6300, 100, 0); - -static const struct snd_kcontrol_new snd_cx88_volume = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .name = "Analog-TV Volume", - .info = snd_cx88_volume_info, - .get = snd_cx88_volume_get, - .put = snd_cx88_volume_put, - .tlv.p = snd_cx88_db_scale, -}; - -static int snd_cx88_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); - struct cx88_core *core = chip->core; - u32 bit = kcontrol->private_value; - - value->value.integer.value[0] = !(cx_read(AUD_VOL_CTL) & bit); - return 0; -} - -static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); - struct cx88_core *core = chip->core; - u32 bit = kcontrol->private_value; - int ret = 0; - u32 vol; - - spin_lock_irq(&chip->reg_lock); - vol = cx_read(AUD_VOL_CTL); - if (value->value.integer.value[0] != !(vol & bit)) { - vol ^= bit; - cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol); - /* Pass mute onto any WM8775 */ - if ((core->board.audio_chip == V4L2_IDENT_WM8775) && - ((1<<6) == bit)) - wm8775_s_ctrl(core, V4L2_CID_AUDIO_MUTE, 0 != (vol & bit)); - ret = 1; - } - spin_unlock_irq(&chip->reg_lock); - return ret; -} - -static const struct snd_kcontrol_new snd_cx88_dac_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Audio-Out Switch", - .info = snd_ctl_boolean_mono_info, - .get = snd_cx88_switch_get, - .put = snd_cx88_switch_put, - .private_value = (1<<8), -}; - -static const struct snd_kcontrol_new snd_cx88_source_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog-TV Switch", - .info = snd_ctl_boolean_mono_info, - .get = snd_cx88_switch_get, - .put = snd_cx88_switch_put, - .private_value = (1<<6), -}; - -static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); - struct cx88_core *core = chip->core; - s32 val; - - val = wm8775_g_ctrl(core, V4L2_CID_AUDIO_LOUDNESS); - value->value.integer.value[0] = val ? 1 : 0; - return 0; -} - -static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *value) -{ - snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); - struct cx88_core *core = chip->core; - struct v4l2_control client_ctl; - - memset(&client_ctl, 0, sizeof(client_ctl)); - client_ctl.value = 0 != value->value.integer.value[0]; - client_ctl.id = V4L2_CID_AUDIO_LOUDNESS; - call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); - - return 0; -} - -static struct snd_kcontrol_new snd_cx88_alc_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line-In ALC Switch", - .info = snd_ctl_boolean_mono_info, - .get = snd_cx88_alc_get, - .put = snd_cx88_alc_put, -}; - -/**************************************************************************** - 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 cx88_audio_pci_tbl[] __devinitdata = { - {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, - {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, - {0, } -}; -MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl); - -/* - * Chip-specific destructor - */ - -static int snd_cx88_free(snd_cx88_card_t *chip) -{ - - if (chip->irq >= 0) - free_irq(chip->irq, chip); - - cx88_core_put(chip->core,chip->pci); - - pci_disable_device(chip->pci); - return 0; -} - -/* - * Component Destructor - */ -static void snd_cx88_dev_free(struct snd_card * card) -{ - snd_cx88_card_t *chip = card->private_data; - - snd_cx88_free(chip); -} - - -/* - * Alsa Constructor - Component probe - */ - -static int devno; -static int __devinit snd_cx88_create(struct snd_card *card, - struct pci_dev *pci, - snd_cx88_card_t **rchip, - struct cx88_core **core_ptr) -{ - snd_cx88_card_t *chip; - struct cx88_core *core; - int err; - unsigned char pci_lat; - - *rchip = NULL; - - err = pci_enable_device(pci); - if (err < 0) - return err; - - pci_set_master(pci); - - chip = card->private_data; - - core = cx88_core_get(pci); - if (NULL == core) { - err = -EINVAL; - return err; - } - - if (!pci_dma_supported(pci,DMA_BIT_MASK(32))) { - dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name); - err = -EIO; - cx88_core_put(core, pci); - return err; - } - - - /* pci init */ - chip->card = card; - chip->pci = pci; - chip->irq = -1; - spin_lock_init(&chip->reg_lock); - - chip->core = core; - - /* get irq */ - err = request_irq(chip->pci->irq, cx8801_irq, - IRQF_SHARED | IRQF_DISABLED, chip->core->name, chip); - if (err < 0) { - dprintk(0, "%s: can't get IRQ %d\n", - chip->core->name, chip->pci->irq); - return err; - } - - /* print pci info */ - pci_read_config_byte(pci, PCI_LATENCY_TIMER, &pci_lat); - - dprintk(1,"ALSA %s/%i: found at %s, rev: %d, irq: %d, " - "latency: %d, mmio: 0x%llx\n", core->name, devno, - pci_name(pci), pci->revision, pci->irq, - pci_lat, (unsigned long long)pci_resource_start(pci,0)); - - chip->irq = pci->irq; - synchronize_irq(chip->irq); - - snd_card_set_dev(card, &pci->dev); - - *rchip = chip; - *core_ptr = core; - - return 0; -} - -static int __devinit cx88_audio_initdev(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - struct snd_card *card; - snd_cx88_card_t *chip; - struct cx88_core *core = NULL; - int err; - - if (devno >= SNDRV_CARDS) - return (-ENODEV); - - if (!enable[devno]) { - ++devno; - return (-ENOENT); - } - - err = snd_card_create(index[devno], id[devno], THIS_MODULE, - sizeof(snd_cx88_card_t), &card); - if (err < 0) - return err; - - card->private_free = snd_cx88_dev_free; - - err = snd_cx88_create(card, pci, &chip, &core); - if (err < 0) - goto error; - - err = snd_cx88_pcm(chip, 0, "CX88 Digital"); - if (err < 0) - goto error; - - err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_volume, chip)); - if (err < 0) - goto error; - err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_dac_switch, chip)); - if (err < 0) - goto error; - err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_source_switch, chip)); - if (err < 0) - goto error; - - /* If there's a wm8775 then add a Line-In ALC switch */ - if (core->board.audio_chip == V4L2_IDENT_WM8775) - snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, chip)); - - strcpy (card->driver, "CX88x"); - sprintf(card->shortname, "Conexant CX%x", pci->device); - sprintf(card->longname, "%s at %#llx", - card->shortname,(unsigned long long)pci_resource_start(pci, 0)); - strcpy (card->mixername, "CX88"); - - dprintk (0, "%s/%i: ALSA support for cx2388x boards\n", - card->driver,devno); - - err = snd_card_register(card); - if (err < 0) - goto error; - pci_set_drvdata(pci,card); - - devno++; - return 0; - -error: - snd_card_free(card); - return err; -} -/* - * ALSA destructor - */ -static void __devexit cx88_audio_finidev(struct pci_dev *pci) -{ - struct cx88_audio_dev *card = pci_get_drvdata(pci); - - snd_card_free((void *)card); - - pci_set_drvdata(pci, NULL); - - devno--; -} - -/* - * PCI driver definition - */ - -static struct pci_driver cx88_audio_pci_driver = { - .name = "cx88_audio", - .id_table = cx88_audio_pci_tbl, - .probe = cx88_audio_initdev, - .remove = __devexit_p(cx88_audio_finidev), -}; - -/**************************************************************************** - LINUX MODULE INIT - ****************************************************************************/ - -/* - * module init - */ -static int __init cx88_audio_init(void) -{ - printk(KERN_INFO "cx2388x alsa driver version %s loaded\n", - CX88_VERSION); - return pci_register_driver(&cx88_audio_pci_driver); -} - -/* - * module remove - */ -static void __exit cx88_audio_fini(void) -{ - pci_unregister_driver(&cx88_audio_pci_driver); -} - -module_init(cx88_audio_init); -module_exit(cx88_audio_fini); diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c deleted file mode 100644 index 843ffd9e533b..000000000000 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ /dev/null @@ -1,1299 +0,0 @@ -/* - * - * Support for a cx23416 mpeg encoder via cx2388x host port. - * "blackbird" reference design. - * - * (c) 2004 Jelle Foks <jelle@foks.us> - * (c) 2004 Gerd Knorr <kraxel@bytesex.org> - * - * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org> - * - video_ioctl2 conversion - * - * Includes parts from the ivtv driver <http://sourceforge.net/projects/ivtv/> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/firmware.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-event.h> -#include <media/cx2341x.h> - -#include "cx88.h" - -MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards"); -MODULE_AUTHOR("Jelle Foks <jelle@foks.us>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(CX88_VERSION); - -static unsigned int mpegbufs = 32; -module_param(mpegbufs,int,0644); -MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32"); - -static unsigned int debug; -module_param(debug,int,0644); -MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); - -#define dprintk(level,fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg) - - -/* ------------------------------------------------------------------ */ - -#define BLACKBIRD_FIRM_IMAGE_SIZE 376836 - -/* defines below are from ivtv-driver.h */ - -#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF - -/* Firmware API commands */ -#define IVTV_API_STD_TIMEOUT 500 - -enum blackbird_capture_type { - BLACKBIRD_MPEG_CAPTURE, - BLACKBIRD_RAW_CAPTURE, - BLACKBIRD_RAW_PASSTHRU_CAPTURE -}; -enum blackbird_capture_bits { - BLACKBIRD_RAW_BITS_NONE = 0x00, - BLACKBIRD_RAW_BITS_YUV_CAPTURE = 0x01, - BLACKBIRD_RAW_BITS_PCM_CAPTURE = 0x02, - BLACKBIRD_RAW_BITS_VBI_CAPTURE = 0x04, - BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08, - BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE = 0x10 -}; -enum blackbird_capture_end { - BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */ - BLACKBIRD_END_NOW, /* stop immediately, no irq */ -}; -enum blackbird_framerate { - BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */ - BLACKBIRD_FRAMERATE_PAL_25 /* PAL: 25fps */ -}; -enum blackbird_stream_port { - BLACKBIRD_OUTPUT_PORT_MEMORY, - BLACKBIRD_OUTPUT_PORT_STREAMING, - BLACKBIRD_OUTPUT_PORT_SERIAL -}; -enum blackbird_data_xfer_status { - BLACKBIRD_MORE_BUFFERS_FOLLOW, - BLACKBIRD_LAST_BUFFER, -}; -enum blackbird_picture_mask { - BLACKBIRD_PICTURE_MASK_NONE, - BLACKBIRD_PICTURE_MASK_I_FRAMES, - BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3, - BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7, -}; -enum blackbird_vbi_mode_bits { - BLACKBIRD_VBI_BITS_SLICED, - BLACKBIRD_VBI_BITS_RAW, -}; -enum blackbird_vbi_insertion_bits { - BLACKBIRD_VBI_BITS_INSERT_IN_XTENSION_USR_DATA, - BLACKBIRD_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1, - BLACKBIRD_VBI_BITS_SEPARATE_STREAM = 0x2 << 1, - BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1, - BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1, -}; -enum blackbird_dma_unit { - BLACKBIRD_DMA_BYTES, - BLACKBIRD_DMA_FRAMES, -}; -enum blackbird_dma_transfer_status_bits { - BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01, - BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04, - BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10, -}; -enum blackbird_pause { - BLACKBIRD_PAUSE_ENCODING, - BLACKBIRD_RESUME_ENCODING, -}; -enum blackbird_copyright { - BLACKBIRD_COPYRIGHT_OFF, - BLACKBIRD_COPYRIGHT_ON, -}; -enum blackbird_notification_type { - BLACKBIRD_NOTIFICATION_REFRESH, -}; -enum blackbird_notification_status { - BLACKBIRD_NOTIFICATION_OFF, - BLACKBIRD_NOTIFICATION_ON, -}; -enum blackbird_notification_mailbox { - BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1, -}; -enum blackbird_field1_lines { - BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */ - BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */ - BLACKBIRD_FIELD1_MICRONAS = 0x0105, /* 261 */ -}; -enum blackbird_field2_lines { - BLACKBIRD_FIELD2_SAA7114 = 0x00EF, /* 239 */ - BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */ - BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */ -}; -enum blackbird_custom_data_type { - BLACKBIRD_CUSTOM_EXTENSION_USR_DATA, - BLACKBIRD_CUSTOM_PRIVATE_PACKET, -}; -enum blackbird_mute { - BLACKBIRD_UNMUTE, - BLACKBIRD_MUTE, -}; -enum blackbird_mute_video_mask { - BLACKBIRD_MUTE_VIDEO_V_MASK = 0x0000FF00, - BLACKBIRD_MUTE_VIDEO_U_MASK = 0x00FF0000, - BLACKBIRD_MUTE_VIDEO_Y_MASK = 0xFF000000, -}; -enum blackbird_mute_video_shift { - BLACKBIRD_MUTE_VIDEO_V_SHIFT = 8, - BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16, - BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24, -}; - -/* Registers */ -#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/) -#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC /*| IVTV_REG_OFFSET*/) -#define IVTV_REG_SPU (0x9050 /*| IVTV_REG_OFFSET*/) -#define IVTV_REG_HW_BLOCKS (0x9054 /*| IVTV_REG_OFFSET*/) -#define IVTV_REG_VPU (0x9058 /*| IVTV_REG_OFFSET*/) -#define IVTV_REG_APU (0xA064 /*| IVTV_REG_OFFSET*/) - -/* ------------------------------------------------------------------ */ - -static void host_setup(struct cx88_core *core) -{ - /* toggle reset of the host */ - cx_write(MO_GPHST_SOFT_RST, 1); - udelay(100); - cx_write(MO_GPHST_SOFT_RST, 0); - udelay(100); - - /* host port setup */ - cx_write(MO_GPHST_WSC, 0x44444444U); - cx_write(MO_GPHST_XFR, 0); - cx_write(MO_GPHST_WDTH, 15); - cx_write(MO_GPHST_HDSHK, 0); - cx_write(MO_GPHST_MUX16, 0x44448888U); - cx_write(MO_GPHST_MODE, 0); -} - -/* ------------------------------------------------------------------ */ - -#define P1_MDATA0 0x390000 -#define P1_MDATA1 0x390001 -#define P1_MDATA2 0x390002 -#define P1_MDATA3 0x390003 -#define P1_MADDR2 0x390004 -#define P1_MADDR1 0x390005 -#define P1_MADDR0 0x390006 -#define P1_RDATA0 0x390008 -#define P1_RDATA1 0x390009 -#define P1_RDATA2 0x39000A -#define P1_RDATA3 0x39000B -#define P1_RADDR0 0x39000C -#define P1_RADDR1 0x39000D -#define P1_RRDWR 0x39000E - -static int wait_ready_gpio0_bit1(struct cx88_core *core, u32 state) -{ - unsigned long timeout = jiffies + msecs_to_jiffies(1); - u32 gpio0,need; - - need = state ? 2 : 0; - for (;;) { - gpio0 = cx_read(MO_GP0_IO) & 2; - if (need == gpio0) - return 0; - if (time_after(jiffies,timeout)) - return -1; - udelay(1); - } -} - -static int memory_write(struct cx88_core *core, u32 address, u32 value) -{ - /* Warning: address is dword address (4 bytes) */ - cx_writeb(P1_MDATA0, (unsigned int)value); - cx_writeb(P1_MDATA1, (unsigned int)(value >> 8)); - cx_writeb(P1_MDATA2, (unsigned int)(value >> 16)); - cx_writeb(P1_MDATA3, (unsigned int)(value >> 24)); - cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) | 0x40); - cx_writeb(P1_MADDR1, (unsigned int)(address >> 8)); - cx_writeb(P1_MADDR0, (unsigned int)address); - cx_read(P1_MDATA0); - cx_read(P1_MADDR0); - - return wait_ready_gpio0_bit1(core,1); -} - -static int memory_read(struct cx88_core *core, u32 address, u32 *value) -{ - int retval; - u32 val; - - /* Warning: address is dword address (4 bytes) */ - cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) & ~0xC0); - cx_writeb(P1_MADDR1, (unsigned int)(address >> 8)); - cx_writeb(P1_MADDR0, (unsigned int)address); - cx_read(P1_MADDR0); - - retval = wait_ready_gpio0_bit1(core,1); - - cx_writeb(P1_MDATA3, 0); - val = (unsigned char)cx_read(P1_MDATA3) << 24; - cx_writeb(P1_MDATA2, 0); - val |= (unsigned char)cx_read(P1_MDATA2) << 16; - cx_writeb(P1_MDATA1, 0); - val |= (unsigned char)cx_read(P1_MDATA1) << 8; - cx_writeb(P1_MDATA0, 0); - val |= (unsigned char)cx_read(P1_MDATA0); - - *value = val; - return retval; -} - -static int register_write(struct cx88_core *core, u32 address, u32 value) -{ - cx_writeb(P1_RDATA0, (unsigned int)value); - cx_writeb(P1_RDATA1, (unsigned int)(value >> 8)); - cx_writeb(P1_RDATA2, (unsigned int)(value >> 16)); - cx_writeb(P1_RDATA3, (unsigned int)(value >> 24)); - cx_writeb(P1_RADDR0, (unsigned int)address); - cx_writeb(P1_RADDR1, (unsigned int)(address >> 8)); - cx_writeb(P1_RRDWR, 1); - cx_read(P1_RDATA0); - cx_read(P1_RADDR0); - - return wait_ready_gpio0_bit1(core,1); -} - - -static int register_read(struct cx88_core *core, u32 address, u32 *value) -{ - int retval; - u32 val; - - cx_writeb(P1_RADDR0, (unsigned int)address); - cx_writeb(P1_RADDR1, (unsigned int)(address >> 8)); - cx_writeb(P1_RRDWR, 0); - cx_read(P1_RADDR0); - - retval = wait_ready_gpio0_bit1(core,1); - val = (unsigned char)cx_read(P1_RDATA0); - val |= (unsigned char)cx_read(P1_RDATA1) << 8; - val |= (unsigned char)cx_read(P1_RDATA2) << 16; - val |= (unsigned char)cx_read(P1_RDATA3) << 24; - - *value = val; - return retval; -} - -/* ------------------------------------------------------------------ */ - -static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]) -{ - struct cx8802_dev *dev = priv; - unsigned long timeout; - u32 value, flag, retval; - int i; - - dprintk(1,"%s: 0x%X\n", __func__, command); - - /* this may not be 100% safe if we can't read any memory location - without side effects */ - memory_read(dev->core, dev->mailbox - 4, &value); - if (value != 0x12345678) { - dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n"); - return -1; - } - - memory_read(dev->core, dev->mailbox, &flag); - if (flag) { - dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag); - return -1; - } - - flag |= 1; /* tell 'em we're working on it */ - memory_write(dev->core, dev->mailbox, flag); - - /* write command + args + fill remaining with zeros */ - memory_write(dev->core, dev->mailbox + 1, command); /* command code */ - memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */ - for (i = 0; i < in; i++) { - memory_write(dev->core, dev->mailbox + 4 + i, data[i]); - dprintk(1, "API Input %d = %d\n", i, data[i]); - } - for (; i < CX2341X_MBOX_MAX_DATA; i++) - memory_write(dev->core, dev->mailbox + 4 + i, 0); - - flag |= 3; /* tell 'em we're done writing */ - memory_write(dev->core, dev->mailbox, flag); - - /* wait for firmware to handle the API command */ - timeout = jiffies + msecs_to_jiffies(10); - for (;;) { - memory_read(dev->core, dev->mailbox, &flag); - if (0 != (flag & 4)) - break; - if (time_after(jiffies,timeout)) { - dprintk(0, "ERROR: API Mailbox timeout\n"); - return -1; - } - udelay(10); - } - - /* read output values */ - for (i = 0; i < out; i++) { - memory_read(dev->core, dev->mailbox + 4 + i, data + i); - dprintk(1, "API Output %d = %d\n", i, data[i]); - } - - memory_read(dev->core, dev->mailbox + 2, &retval); - dprintk(1, "API result = %d\n",retval); - - flag = 0; - memory_write(dev->core, dev->mailbox, flag); - return retval; -} -/* ------------------------------------------------------------------ */ - -/* We don't need to call the API often, so using just one mailbox will probably suffice */ -static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command, - u32 inputcnt, u32 outputcnt, ...) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - va_list vargs; - int i, err; - - va_start(vargs, outputcnt); - - for (i = 0; i < inputcnt; i++) { - data[i] = va_arg(vargs, int); - } - err = blackbird_mbox_func(dev, command, inputcnt, outputcnt, data); - for (i = 0; i < outputcnt; i++) { - int *vptr = va_arg(vargs, int *); - *vptr = data[i]; - } - va_end(vargs); - return err; -} - -static int blackbird_find_mailbox(struct cx8802_dev *dev) -{ - u32 signature[4]={0x12345678, 0x34567812, 0x56781234, 0x78123456}; - int signaturecnt=0; - u32 value; - int i; - - for (i = 0; i < BLACKBIRD_FIRM_IMAGE_SIZE; i++) { - memory_read(dev->core, i, &value); - if (value == signature[signaturecnt]) - signaturecnt++; - else - signaturecnt = 0; - if (4 == signaturecnt) { - dprintk(1, "Mailbox signature found\n"); - return i+1; - } - } - dprintk(0, "Mailbox signature values not found!\n"); - return -1; -} - -static int blackbird_load_firmware(struct cx8802_dev *dev) -{ - static const unsigned char magic[8] = { - 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa - }; - const struct firmware *firmware; - int i, retval = 0; - u32 value = 0; - u32 checksum = 0; - u32 *dataptr; - - retval = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED); - retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); - retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640); - retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); - msleep(1); - retval |= register_write(dev->core, IVTV_REG_APU, 0); - - if (retval < 0) - dprintk(0, "Error with register_write\n"); - - retval = request_firmware(&firmware, CX2341X_FIRM_ENC_FILENAME, - &dev->pci->dev); - - - if (retval != 0) { - dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n", - CX2341X_FIRM_ENC_FILENAME); - dprintk(0, "Please fix your hotplug setup, the board will " - "not work without firmware loaded!\n"); - return -1; - } - - if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) { - dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n", - firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE); - release_firmware(firmware); - return -1; - } - - if (0 != memcmp(firmware->data, magic, 8)) { - dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n"); - release_firmware(firmware); - return -1; - } - - /* transfer to the chip */ - dprintk(1,"Loading firmware ...\n"); - dataptr = (u32*)firmware->data; - for (i = 0; i < (firmware->size >> 2); i++) { - value = le32_to_cpu(*dataptr); - checksum += ~value; - memory_write(dev->core, i, value); - dataptr++; - } - - /* read back to verify with the checksum */ - for (i--; i >= 0; i--) { - memory_read(dev->core, i, &value); - checksum -= ~value; - } - if (checksum) { - dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n"); - release_firmware(firmware); - return -1; - } - release_firmware(firmware); - dprintk(0, "Firmware upload successful.\n"); - - retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); - retval |= register_read(dev->core, IVTV_REG_SPU, &value); - retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE); - msleep(1); - - retval |= register_read(dev->core, IVTV_REG_VPU, &value); - retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8); - - if (retval < 0) - dprintk(0, "Error with register_write\n"); - return 0; -} - -/** - Settings used by the windows tv app for PVR2000: -================================================================================================================= -Profile | Codec | Resolution | CBR/VBR | Video Qlty | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode ------------------------------------------------------------------------------------------------------------------ -MPEG-1 | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 2000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo -MPEG-2 | MPEG2 | 720x576PAL | VBR | 600 :Good | 4000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo -VCD | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 1150 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo -DVD | MPEG2 | 720x576PAL | VBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo -DB* DVD | MPEG2 | 720x576PAL | CBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo -================================================================================================================= -*DB: "DirectBurn" -*/ - -static void blackbird_codec_settings(struct cx8802_dev *dev) -{ - /* assign frame size */ - blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, - dev->height, dev->width); - - dev->cxhdl.width = dev->width; - dev->cxhdl.height = dev->height; - cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50); - cx2341x_handler_setup(&dev->cxhdl); -} - -static int blackbird_initialize_codec(struct cx8802_dev *dev) -{ - struct cx88_core *core = dev->core; - int version; - int retval; - - dprintk(1,"Initialize codec\n"); - retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ - if (retval < 0) { - - dev->mpeg_active = 0; - - /* ping was not successful, reset and upload firmware */ - cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ - cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */ - retval = blackbird_load_firmware(dev); - if (retval < 0) - return retval; - - retval = blackbird_find_mailbox(dev); - if (retval < 0) - return -1; - - dev->mailbox = retval; - - retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ - if (retval < 0) { - dprintk(0, "ERROR: Firmware ping failed!\n"); - return -1; - } - - retval = blackbird_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, &version); - if (retval < 0) { - dprintk(0, "ERROR: Firmware get encoder version failed!\n"); - return -1; - } - dprintk(0, "Firmware version is 0x%08x\n", version); - } - - cx_write(MO_PINMUX_IO, 0x88); /* 656-8bit IO and enable MPEG parallel IO */ - cx_clear(MO_INPUT_FORMAT, 0x100); /* chroma subcarrier lock to normal? */ - cx_write(MO_VBOS_CONTROL, 0x84A00); /* no 656 mode, 8-bit pixels, disable VBI */ - cx_clear(MO_OUTPUT_FORMAT, 0x0008); /* Normal Y-limits to let the mpeg encoder sync */ - - blackbird_codec_settings(dev); - - blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0, - BLACKBIRD_FIELD1_SAA7115, - BLACKBIRD_FIELD2_SAA7115 - ); - - blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0, - BLACKBIRD_CUSTOM_EXTENSION_USR_DATA, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - - return 0; -} - -static int blackbird_start_codec(struct file *file, void *priv) -{ - struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; - struct cx88_core *core = dev->core; - /* start capturing to the host interface */ - u32 reg; - - int i; - int lastchange = -1; - int lastval = 0; - - for (i = 0; (i < 10) && (i < (lastchange + 4)); i++) { - reg = cx_read(AUD_STATUS); - - dprintk(1, "AUD_STATUS:%dL: 0x%x\n", i, reg); - if ((reg & 0x0F) != lastval) { - lastval = reg & 0x0F; - lastchange = i; - } - msleep(100); - } - - /* unmute audio source */ - cx_clear(AUD_VOL_CTL, (1 << 6)); - - blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0, 0); - - /* initialize the video input */ - blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0); - - cx2341x_handler_set_busy(&dev->cxhdl, 1); - - /* start capturing to the host interface */ - blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, - BLACKBIRD_MPEG_CAPTURE, - BLACKBIRD_RAW_BITS_NONE - ); - - dev->mpeg_active = 1; - return 0; -} - -static int blackbird_stop_codec(struct cx8802_dev *dev) -{ - blackbird_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, - BLACKBIRD_END_NOW, - BLACKBIRD_MPEG_CAPTURE, - BLACKBIRD_RAW_BITS_NONE - ); - - cx2341x_handler_set_busy(&dev->cxhdl, 0); - - dev->mpeg_active = 0; - return 0; -} - -/* ------------------------------------------------------------------ */ - -static int bb_buf_setup(struct videobuf_queue *q, - unsigned int *count, unsigned int *size) -{ - struct cx8802_fh *fh = q->priv_data; - - fh->dev->ts_packet_size = 188 * 4; /* was: 512 */ - fh->dev->ts_packet_count = mpegbufs; /* was: 100 */ - - *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count; - *count = fh->dev->ts_packet_count; - return 0; -} - -static int -bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct cx8802_fh *fh = q->priv_data; - return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field); -} - -static void -bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct cx8802_fh *fh = q->priv_data; - cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb); -} - -static void -bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - cx88_free_buffer(q, (struct cx88_buffer*)vb); -} - -static struct videobuf_queue_ops blackbird_qops = { - .buf_setup = bb_buf_setup, - .buf_prepare = bb_buf_prepare, - .buf_queue = bb_buf_queue, - .buf_release = bb_buf_release, -}; - -/* ------------------------------------------------------------------ */ - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; - struct cx88_core *core = dev->core; - - strcpy(cap->driver, "cx88_blackbird"); - sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); - cx88_querycap(file, core, cap); - return 0; -} - -static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - if (f->index != 0) - return -EINVAL; - - strlcpy(f->description, "MPEG", sizeof(f->description)); - f->pixelformat = V4L2_PIX_FMT_MPEG; - f->flags = V4L2_FMT_FLAG_COMPRESSED; - return 0; -} - -static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx8802_fh *fh = priv; - struct cx8802_dev *dev = fh->dev; - - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */; - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.width = dev->width; - f->fmt.pix.height = dev->height; - f->fmt.pix.field = fh->mpegq.field; - dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", - dev->width, dev->height, fh->mpegq.field ); - return 0; -} - -static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx8802_fh *fh = priv; - struct cx8802_dev *dev = fh->dev; - - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */; - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", - dev->width, dev->height, fh->mpegq.field ); - return 0; -} - -static int vidioc_s_fmt_vid_cap (struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx8802_fh *fh = priv; - struct cx8802_dev *dev = fh->dev; - struct cx88_core *core = dev->core; - - f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; - f->fmt.pix.bytesperline = 0; - f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */; - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - dev->width = f->fmt.pix.width; - dev->height = f->fmt.pix.height; - fh->mpegq.field = f->fmt.pix.field; - cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); - blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, - f->fmt.pix.height, f->fmt.pix.width); - dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", - f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field ); - return 0; -} - -static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p) -{ - struct cx8802_fh *fh = priv; - return (videobuf_reqbufs(&fh->mpegq, p)); -} - -static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct cx8802_fh *fh = priv; - return (videobuf_querybuf(&fh->mpegq, p)); -} - -static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct cx8802_fh *fh = priv; - return (videobuf_qbuf(&fh->mpegq, p)); -} - -static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) -{ - struct cx8802_fh *fh = priv; - return (videobuf_dqbuf(&fh->mpegq, p, - file->f_flags & O_NONBLOCK)); -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx8802_fh *fh = priv; - struct cx8802_dev *dev = fh->dev; - - if (!dev->mpeg_active) - blackbird_start_codec(file, fh); - return videobuf_streamon(&fh->mpegq); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct cx8802_fh *fh = priv; - struct cx8802_dev *dev = fh->dev; - - if (dev->mpeg_active) - blackbird_stop_codec(dev); - return videobuf_streamoff(&fh->mpegq); -} - -static int vidioc_s_frequency (struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct cx8802_fh *fh = priv; - struct cx8802_dev *dev = fh->dev; - struct cx88_core *core = dev->core; - - if (unlikely(UNSET == core->board.tuner_type)) - return -EINVAL; - if (unlikely(f->tuner != 0)) - return -EINVAL; - if (dev->mpeg_active) - blackbird_stop_codec(dev); - - cx88_set_freq (core,f); - blackbird_initialize_codec(dev); - cx88_set_scale(dev->core, dev->width, dev->height, - fh->mpegq.field); - return 0; -} - -static int vidioc_log_status (struct file *file, void *priv) -{ - struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; - struct cx88_core *core = dev->core; - char name[32 + 2]; - - snprintf(name, sizeof(name), "%s/2", core->name); - call_all(core, core, log_status); - v4l2_ctrl_handler_log_status(&dev->cxhdl.hdl, name); - return 0; -} - -static int vidioc_enum_input (struct file *file, void *priv, - struct v4l2_input *i) -{ - struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; - return cx88_enum_input (core,i); -} - -static int vidioc_g_frequency (struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct cx8802_fh *fh = priv; - struct cx88_core *core = fh->dev->core; - - if (unlikely(UNSET == core->board.tuner_type)) - return -EINVAL; - if (unlikely(f->tuner != 0)) - return -EINVAL; - - f->frequency = core->freq; - call_all(core, tuner, g_frequency, f); - - return 0; -} - -static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) -{ - struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; - - *i = core->input; - return 0; -} - -static int vidioc_s_input (struct file *file, void *priv, unsigned int i) -{ - struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; - - if (i >= 4) - return -EINVAL; - if (0 == INPUT(i).type) - return -EINVAL; - - mutex_lock(&core->lock); - cx88_newstation(core); - cx88_video_mux(core,i); - mutex_unlock(&core->lock); - return 0; -} - -static int vidioc_g_tuner (struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; - u32 reg; - - if (unlikely(UNSET == core->board.tuner_type)) - return -EINVAL; - if (0 != t->index) - return -EINVAL; - - strcpy(t->name, "Television"); - t->capability = V4L2_TUNER_CAP_NORM; - t->rangehigh = 0xffffffffUL; - call_all(core, tuner, g_tuner, t); - - cx88_get_stereo(core ,t); - reg = cx_read(MO_DEVICE_STATUS); - t->signal = (reg & (1<<5)) ? 0xffff : 0x0000; - return 0; -} - -static int vidioc_s_tuner (struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; - - if (UNSET == core->board.tuner_type) - return -EINVAL; - if (0 != t->index) - return -EINVAL; - - cx88_set_stereo(core, t->audmode, 1); - return 0; -} - -static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) -{ - struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; - - *tvnorm = core->tvnorm; - return 0; -} - -static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id) -{ - struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; - - mutex_lock(&core->lock); - cx88_set_tvnorm(core,*id); - mutex_unlock(&core->lock); - return 0; -} - -/* FIXME: cx88_ioctl_hook not implemented */ - -static int mpeg_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx8802_dev *dev = video_drvdata(file); - struct cx8802_fh *fh; - struct cx8802_driver *drv = NULL; - int err; - - dprintk( 1, "%s\n", __func__); - - mutex_lock(&dev->core->lock); - - /* Make sure we can acquire the hardware */ - drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); - if (!drv) { - dprintk(1, "%s: blackbird driver is not loaded\n", __func__); - mutex_unlock(&dev->core->lock); - return -ENODEV; - } - - err = drv->request_acquire(drv); - if (err != 0) { - dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err); - mutex_unlock(&dev->core->lock); - return err; - } - - if (!dev->core->mpeg_users && blackbird_initialize_codec(dev) < 0) { - drv->request_release(drv); - mutex_unlock(&dev->core->lock); - return -EINVAL; - } - dprintk(1, "open dev=%s\n", video_device_node_name(vdev)); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh),GFP_KERNEL); - if (NULL == fh) { - drv->request_release(drv); - mutex_unlock(&dev->core->lock); - return -ENOMEM; - } - v4l2_fh_init(&fh->fh, vdev); - file->private_data = fh; - fh->dev = dev; - - videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx88_buffer), - fh, NULL); - - /* FIXME: locking against other video device */ - cx88_set_scale(dev->core, dev->width, dev->height, - fh->mpegq.field); - - dev->core->mpeg_users++; - mutex_unlock(&dev->core->lock); - v4l2_fh_add(&fh->fh); - return 0; -} - -static int mpeg_release(struct file *file) -{ - struct cx8802_fh *fh = file->private_data; - struct cx8802_dev *dev = fh->dev; - struct cx8802_driver *drv = NULL; - - mutex_lock(&dev->core->lock); - - if (dev->mpeg_active && dev->core->mpeg_users == 1) - blackbird_stop_codec(dev); - - cx8802_cancel_buffers(fh->dev); - /* stop mpeg capture */ - videobuf_stop(&fh->mpegq); - - videobuf_mmap_free(&fh->mpegq); - - v4l2_fh_del(&fh->fh); - v4l2_fh_exit(&fh->fh); - file->private_data = NULL; - kfree(fh); - - /* Make sure we release the hardware */ - drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); - WARN_ON(!drv); - if (drv) - drv->request_release(drv); - - dev->core->mpeg_users--; - - mutex_unlock(&dev->core->lock); - - return 0; -} - -static ssize_t -mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos) -{ - struct cx8802_fh *fh = file->private_data; - struct cx8802_dev *dev = fh->dev; - - if (!dev->mpeg_active) - blackbird_start_codec(file, fh); - - return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0, - file->f_flags & O_NONBLOCK); -} - -static unsigned int -mpeg_poll(struct file *file, struct poll_table_struct *wait) -{ - unsigned long req_events = poll_requested_events(wait); - struct cx8802_fh *fh = file->private_data; - struct cx8802_dev *dev = fh->dev; - - if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM))) - blackbird_start_codec(file, fh); - - return v4l2_ctrl_poll(file, wait) | videobuf_poll_stream(file, &fh->mpegq, wait); -} - -static int -mpeg_mmap(struct file *file, struct vm_area_struct * vma) -{ - struct cx8802_fh *fh = file->private_data; - - return videobuf_mmap_mapper(&fh->mpegq, vma); -} - -static const struct v4l2_file_operations mpeg_fops = -{ - .owner = THIS_MODULE, - .open = mpeg_open, - .release = mpeg_release, - .read = mpeg_read, - .poll = mpeg_poll, - .mmap = mpeg_mmap, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_log_status = vidioc_log_status, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_std = vidioc_g_std, - .vidioc_s_std = vidioc_s_std, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -static struct video_device cx8802_mpeg_template = { - .name = "cx8802", - .fops = &mpeg_fops, - .ioctl_ops = &mpeg_ioctl_ops, - .tvnorms = CX88_NORMS, -}; - -/* ------------------------------------------------------------------ */ - -/* The CX8802 MPEG API will call this when we can use the hardware */ -static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - int err = 0; - - switch (core->boardnr) { - case CX88_BOARD_HAUPPAUGE_HVR1300: - /* By default, core setup will leave the cx22702 out of reset, on the bus. - * We left the hardware on power up with the cx22702 active. - * We're being given access to re-arrange the GPIOs. - * Take the bus off the cx22702 and put the cx23416 on it. - */ - /* Toggle reset on cx22702 leaving i2c active */ - cx_set(MO_GP0_IO, 0x00000080); - udelay(1000); - cx_clear(MO_GP0_IO, 0x00000080); - udelay(50); - cx_set(MO_GP0_IO, 0x00000080); - udelay(1000); - /* tri-state the cx22702 pins */ - cx_set(MO_GP0_IO, 0x00000004); - udelay(1000); - break; - default: - err = -ENODEV; - } - return err; -} - -/* The CX8802 MPEG API will call this when we need to release the hardware */ -static int cx8802_blackbird_advise_release(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - int err = 0; - - switch (core->boardnr) { - case CX88_BOARD_HAUPPAUGE_HVR1300: - /* Exit leaving the cx23416 on the bus */ - break; - default: - err = -ENODEV; - } - return err; -} - -static void blackbird_unregister_video(struct cx8802_dev *dev) -{ - if (dev->mpeg_dev) { - if (video_is_registered(dev->mpeg_dev)) - video_unregister_device(dev->mpeg_dev); - else - video_device_release(dev->mpeg_dev); - dev->mpeg_dev = NULL; - } -} - -static int blackbird_register_video(struct cx8802_dev *dev) -{ - int err; - - dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci, - &cx8802_mpeg_template,"mpeg"); - dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl; - video_set_drvdata(dev->mpeg_dev, dev); - err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1); - if (err < 0) { - printk(KERN_INFO "%s/2: can't register mpeg device\n", - dev->core->name); - return err; - } - printk(KERN_INFO "%s/2: registered device %s [mpeg]\n", - dev->core->name, video_device_node_name(dev->mpeg_dev)); - return 0; -} - -/* ----------------------------------------------------------- */ - -static int cx8802_blackbird_probe(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - struct cx8802_dev *dev = core->dvbdev; - int err; - - dprintk( 1, "%s\n", __func__); - dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", - core->boardnr, - core->name, - core->pci_bus, - core->pci_slot); - - err = -ENODEV; - if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD)) - goto fail_core; - - dev->width = 720; - if (core->tvnorm & V4L2_STD_525_60) { - dev->height = 480; - } else { - dev->height = 576; - } - dev->cxhdl.port = CX2341X_PORT_STREAMING; - dev->cxhdl.width = dev->width; - dev->cxhdl.height = dev->height; - dev->cxhdl.func = blackbird_mbox_func; - dev->cxhdl.priv = dev; - err = cx2341x_handler_init(&dev->cxhdl, 36); - if (err) - goto fail_core; - v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl); - - /* blackbird stuff */ - printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n", - core->name); - host_setup(dev->core); - - blackbird_initialize_codec(dev); - - /* initial device configuration: needed ? */ -// init_controls(core); - cx88_set_tvnorm(core,core->tvnorm); - cx88_video_mux(core,0); - cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576); - cx2341x_handler_setup(&dev->cxhdl); - blackbird_register_video(dev); - - return 0; - - fail_core: - return err; -} - -static int cx8802_blackbird_remove(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - struct cx8802_dev *dev = core->dvbdev; - - /* blackbird */ - blackbird_unregister_video(drv->core->dvbdev); - v4l2_ctrl_handler_free(&dev->cxhdl.hdl); - - return 0; -} - -static struct cx8802_driver cx8802_blackbird_driver = { - .type_id = CX88_MPEG_BLACKBIRD, - .hw_access = CX8802_DRVCTL_SHARED, - .probe = cx8802_blackbird_probe, - .remove = cx8802_blackbird_remove, - .advise_acquire = cx8802_blackbird_advise_acquire, - .advise_release = cx8802_blackbird_advise_release, -}; - -static int __init blackbird_init(void) -{ - printk(KERN_INFO "cx2388x blackbird driver version %s loaded\n", - CX88_VERSION); - return cx8802_register_driver(&cx8802_blackbird_driver); -} - -static void __exit blackbird_fini(void) -{ - cx8802_unregister_driver(&cx8802_blackbird_driver); -} - -module_init(blackbird_init); -module_exit(blackbird_fini); - -module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644); -MODULE_PARM_DESC(debug,"enable debug messages [video]"); diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c deleted file mode 100644 index 4e9d4f722960..000000000000 --- a/drivers/media/video/cx88/cx88-cards.c +++ /dev/null @@ -1,3811 +0,0 @@ -/* - * - * device driver for Conexant 2388x based TV cards - * card-specific stuff. - * - * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/slab.h> - -#include "cx88.h" -#include "tea5767.h" -#include "xc4000.h" - -static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; -static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; -static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; - -module_param_array(tuner, int, NULL, 0444); -module_param_array(radio, int, NULL, 0444); -module_param_array(card, int, NULL, 0444); - -MODULE_PARM_DESC(tuner,"tuner type"); -MODULE_PARM_DESC(radio,"radio tuner type"); -MODULE_PARM_DESC(card,"card type"); - -static unsigned int latency = UNSET; -module_param(latency,int,0444); -MODULE_PARM_DESC(latency,"pci latency timer"); - -static int disable_ir; -module_param(disable_ir, int, 0444); -MODULE_PARM_DESC(disable_ir, "Disable IR support"); - -#define info_printk(core, fmt, arg...) \ - printk(KERN_INFO "%s: " fmt, core->name , ## arg) - -#define warn_printk(core, fmt, arg...) \ - printk(KERN_WARNING "%s: " fmt, core->name , ## arg) - -#define err_printk(core, fmt, arg...) \ - printk(KERN_ERR "%s: " fmt, core->name , ## arg) - - -/* ------------------------------------------------------------------ */ -/* board config info */ - -/* If radio_type !=UNSET, radio_addr should be specified - */ - -static const struct cx88_board cx88_boards[] = { - [CX88_BOARD_UNKNOWN] = { - .name = "UNKNOWN/GENERIC", - .tuner_type = UNSET, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 0, - },{ - .type = CX88_VMUX_COMPOSITE2, - .vmux = 1, - },{ - .type = CX88_VMUX_COMPOSITE3, - .vmux = 2, - },{ - .type = CX88_VMUX_COMPOSITE4, - .vmux = 3, - }}, - }, - [CX88_BOARD_HAUPPAUGE] = { - .name = "Hauppauge WinTV 34xxx models", - .tuner_type = UNSET, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0xff00, // internal decoder - },{ - .type = CX88_VMUX_DEBUG, - .vmux = 0, - .gpio0 = 0xff01, // mono from tuner chip - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0xff02, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0xff02, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0xff01, - }, - }, - [CX88_BOARD_GDI] = { - .name = "GDI Black Gold", - .tuner_type = UNSET, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - }}, - }, - [CX88_BOARD_PIXELVIEW] = { - .name = "PixelView", - .tuner_type = TUNER_PHILIPS_PAL, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0xff00, // internal decoder - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0xff10, - }, - }, - [CX88_BOARD_ATI_WONDER_PRO] = { - .name = "ATI TV Wonder Pro", - .tuner_type = TUNER_PHILIPS_4IN1, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x03ff, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x03fe, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x03fe, - }}, - }, - [CX88_BOARD_WINFAST2000XP_EXPERT] = { - .name = "Leadtek Winfast 2000XP Expert", - .tuner_type = TUNER_PHILIPS_4IN1, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x00F5e700, - .gpio1 = 0x00003004, - .gpio2 = 0x00F5e700, - .gpio3 = 0x02000000, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x00F5c700, - .gpio1 = 0x00003004, - .gpio2 = 0x00F5c700, - .gpio3 = 0x02000000, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x00F5c700, - .gpio1 = 0x00003004, - .gpio2 = 0x00F5c700, - .gpio3 = 0x02000000, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x00F5d700, - .gpio1 = 0x00003004, - .gpio2 = 0x00F5d700, - .gpio3 = 0x02000000, - }, - }, - [CX88_BOARD_AVERTV_STUDIO_303] = { - .name = "AverTV Studio 303 (M126)", - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio1 = 0xe09f, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio1 = 0xe05f, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio1 = 0xe05f, - }}, - .radio = { - .gpio1 = 0xe0df, - .type = CX88_RADIO, - }, - }, - [CX88_BOARD_MSI_TVANYWHERE_MASTER] = { - // added gpio values thanks to Michal - // values for PAL from DScaler - .name = "MSI TV-@nywhere Master", - .tuner_type = TUNER_MT2032, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER_NTSC, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x000040bf, - .gpio1 = 0x000080c0, - .gpio2 = 0x0000ff40, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x000040bf, - .gpio1 = 0x000080c0, - .gpio2 = 0x0000ff40, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x000040bf, - .gpio1 = 0x000080c0, - .gpio2 = 0x0000ff40, - }}, - .radio = { - .type = CX88_RADIO, - .vmux = 3, - .gpio0 = 0x000040bf, - .gpio1 = 0x000080c0, - .gpio2 = 0x0000ff20, - }, - }, - [CX88_BOARD_WINFAST_DV2000] = { - .name = "Leadtek Winfast DV2000", - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0035e700, - .gpio1 = 0x00003004, - .gpio2 = 0x0035e700, - .gpio3 = 0x02000000, - },{ - - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0035c700, - .gpio1 = 0x00003004, - .gpio2 = 0x0035c700, - .gpio3 = 0x02000000, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x0035c700, - .gpio1 = 0x0035c700, - .gpio2 = 0x02000000, - .gpio3 = 0x02000000, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x0035d700, - .gpio1 = 0x00007004, - .gpio2 = 0x0035d700, - .gpio3 = 0x02000000, - }, - }, - [CX88_BOARD_LEADTEK_PVR2000] = { - // gpio values for PAL version from regspy by DScaler - .name = "Leadtek PVR 2000", - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0000bde2, - .audioroute = 1, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0000bde6, - .audioroute = 1, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x0000bde6, - .audioroute = 1, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x0000bd62, - .audioroute = 1, - }, - .mpeg = CX88_MPEG_BLACKBIRD, - }, - [CX88_BOARD_IODATA_GVVCP3PCI] = { - .name = "IODATA GV-VCP3/PCI", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 0, - },{ - .type = CX88_VMUX_COMPOSITE2, - .vmux = 1, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - }}, - }, - [CX88_BOARD_PROLINK_PLAYTVPVR] = { - .name = "Prolink PlayTV PVR", - .tuner_type = TUNER_PHILIPS_FM1236_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0xbff0, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0xbff3, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0xbff3, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0xbff0, - }, - }, - [CX88_BOARD_ASUS_PVR_416] = { - .name = "ASUS PVR-416", - .tuner_type = TUNER_PHILIPS_FM1236_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0000fde6, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? - .audioroute = 1, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x0000fde2, - }, - .mpeg = CX88_MPEG_BLACKBIRD, - }, - [CX88_BOARD_MSI_TVANYWHERE] = { - .name = "MSI TV-@nywhere", - .tuner_type = TUNER_MT2032, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x00000fbf, - .gpio2 = 0x0000fc08, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x00000fbf, - .gpio2 = 0x0000fc68, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x00000fbf, - .gpio2 = 0x0000fc68, - }}, - }, - [CX88_BOARD_KWORLD_DVB_T] = { - .name = "KWorld/VStream XPert DVB-T", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0700, - .gpio2 = 0x0101, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x0700, - .gpio2 = 0x0101, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = { - .name = "DViCO FusionHDTV DVB-T1", - .tuner_type = TUNER_ABSENT, /* No analog tuner */ - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x000027df, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x000027df, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_KWORLD_LTV883] = { - .name = "KWorld LTV883RF", - .tuner_type = TUNER_TNF_8831BGFF, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x07f8, - },{ - .type = CX88_VMUX_DEBUG, - .vmux = 0, - .gpio0 = 0x07f9, // mono from tuner chip - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x000007fa, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x000007fa, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x000007f8, - }, - }, - [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q] = { - .name = "DViCO FusionHDTV 3 Gold-Q", - .tuner_type = TUNER_MICROTUNE_4042FI5, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - /* - GPIO[0] resets DT3302 DTV receiver - 0 - reset asserted - 1 - normal operation - GPIO[1] mutes analog audio output connector - 0 - enable selected source - 1 - mute - GPIO[2] selects source for analog audio output connector - 0 - analog audio input connector on tab - 1 - analog DAC output from CX23881 chip - GPIO[3] selects RF input connector on tuner module - 0 - RF connector labeled CABLE - 1 - RF connector labeled ANT - GPIO[4] selects high RF for QAM256 mode - 0 - normal RF - 1 - high RF - */ - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0f0d, - },{ - .type = CX88_VMUX_CABLE, - .vmux = 0, - .gpio0 = 0x0f05, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0f00, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x0f00, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_HAUPPAUGE_DVB_T1] = { - .name = "Hauppauge Nova-T DVB-T", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_CONEXANT_DVB_T1] = { - .name = "Conexant DVB-T reference design", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_PROVIDEO_PV259] = { - .name = "Provideo PV259", - .tuner_type = TUNER_PHILIPS_FQ1216ME, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .audioroute = 1, - }}, - .mpeg = CX88_MPEG_BLACKBIRD, - }, - [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = { - .name = "DViCO FusionHDTV DVB-T Plus", - .tuner_type = TUNER_ABSENT, /* No analog tuner */ - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x000027df, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x000027df, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_DNTV_LIVE_DVB_T] = { - .name = "digitalnow DNTV Live! DVB-T", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x00000700, - .gpio2 = 0x00000101, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x00000700, - .gpio2 = 0x00000101, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_PCHDTV_HD3000] = { - .name = "pcHDTV HD3000 HDTV", - .tuner_type = TUNER_THOMSON_DTT761X, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - /* GPIO[2] = audio source for analog audio out connector - * 0 = analog audio input connector - * 1 = CX88 audio DACs - * - * GPIO[7] = input to CX88's audio/chroma ADC - * 0 = FM 10.7 MHz IF - * 1 = Sound 4.5 MHz IF - * - * GPIO[1,5,6] = Oren 51132 pins 27,35,28 respectively - * - * GPIO[16] = Remote control input - */ - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x00008484, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x00008400, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x00008400, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x00008404, - }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_HAUPPAUGE_ROSLYN] = { - // entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu> - // GPIO values obtained from regspy, courtesy Sean Covel - .name = "Hauppauge WinTV 28xxx (Roslyn) models", - .tuner_type = UNSET, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0xed1a, - .gpio2 = 0x00ff, - },{ - .type = CX88_VMUX_DEBUG, - .vmux = 0, - .gpio0 = 0xff01, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0xff02, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0xed92, - .gpio2 = 0x00ff, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0xed96, - .gpio2 = 0x00ff, - }, - .mpeg = CX88_MPEG_BLACKBIRD, - }, - [CX88_BOARD_DIGITALLOGIC_MEC] = { - .name = "Digital-Logic MICROSPACE Entertainment Center (MEC)", - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x00009d80, - .audioroute = 1, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x00009d76, - .audioroute = 1, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x00009d76, - .audioroute = 1, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x00009d00, - .audioroute = 1, - }, - .mpeg = CX88_MPEG_BLACKBIRD, - }, - [CX88_BOARD_IODATA_GVBCTV7E] = { - .name = "IODATA GV/BCTV7E", - .tuner_type = TUNER_PHILIPS_FQ1286, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 1, - .gpio1 = 0x0000e03f, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 2, - .gpio1 = 0x0000e07f, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 3, - .gpio1 = 0x0000e07f, - }} - }, - [CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO] = { - .name = "PixelView PlayTV Ultra Pro (Stereo)", - /* May be also TUNER_YMEC_TVF_5533MF for NTSC/M or PAL/M */ - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - /* Some variants use a tda9874 and so need the tvaudio module. */ - .audio_chip = V4L2_IDENT_TVAUDIO, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0xbf61, /* internal decoder */ - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0xbf63, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0xbf63, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0xbf60, - }, - }, - [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = { - .name = "DViCO FusionHDTV 3 Gold-T", - .tuner_type = TUNER_THOMSON_DTT761X, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x97ed, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x97e9, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x97e9, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_ADSTECH_DVB_T_PCI] = { - .name = "ADS Tech Instant TV DVB-T PCI", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0700, - .gpio2 = 0x0101, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x0700, - .gpio2 = 0x0101, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1] = { - .name = "TerraTec Cinergy 1400 DVB-T", - .tuner_type = TUNER_ABSENT, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 2, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = { - .name = "DViCO FusionHDTV 5 Gold", - .tuner_type = TUNER_LG_TDVS_H06XF, /* TDVS-H062F */ - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x87fd, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x87f9, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x87f9, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_AVERMEDIA_ULTRATV_MC_550] = { - .name = "AverMedia UltraTV Media Center PCI 550", - .tuner_type = TUNER_PHILIPS_FM1236_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 0, - .gpio0 = 0x0000cd73, - .audioroute = 1, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 1, - .gpio0 = 0x0000cd73, - .audioroute = 1, - },{ - .type = CX88_VMUX_TELEVISION, - .vmux = 3, - .gpio0 = 0x0000cdb3, - .audioroute = 1, - }}, - .radio = { - .type = CX88_RADIO, - .vmux = 2, - .gpio0 = 0x0000cdf3, - .audioroute = 1, - }, - .mpeg = CX88_MPEG_BLACKBIRD, - }, - [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = { - /* Alexander Wold <awold@bigfoot.com> */ - .name = "Kworld V-Stream Xpert DVD", - .tuner_type = UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x03000000, - .gpio1 = 0x01000000, - .gpio2 = 0x02000000, - .gpio3 = 0x00100000, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x03000000, - .gpio1 = 0x01000000, - .gpio2 = 0x02000000, - .gpio3 = 0x00100000, - }}, - }, - [CX88_BOARD_ATI_HDTVWONDER] = { - .name = "ATI HDTV Wonder", - .tuner_type = TUNER_PHILIPS_TUV1236D, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x00000ff7, - .gpio1 = 0x000000ff, - .gpio2 = 0x00000001, - .gpio3 = 0x00000000, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x00000ffe, - .gpio1 = 0x000000ff, - .gpio2 = 0x00000001, - .gpio3 = 0x00000000, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x00000ffe, - .gpio1 = 0x000000ff, - .gpio2 = 0x00000001, - .gpio3 = 0x00000000, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_WINFAST_DTV1000] = { - .name = "WinFast DTV1000-T", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_AVERTV_303] = { - .name = "AVerTV 303 (M126)", - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x00ff, - .gpio1 = 0xe09f, - .gpio2 = 0x0010, - .gpio3 = 0x0000, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x00ff, - .gpio1 = 0xe05f, - .gpio2 = 0x0010, - .gpio3 = 0x0000, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x00ff, - .gpio1 = 0xe05f, - .gpio2 = 0x0010, - .gpio3 = 0x0000, - }}, - }, - [CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1] = { - .name = "Hauppauge Nova-S-Plus DVB-S", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .audio_chip = V4L2_IDENT_WM8775, - .i2sinputcntl = 2, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - /* 2: Line-In */ - .audioroute = 2, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - /* 2: Line-In */ - .audioroute = 2, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - /* 2: Line-In */ - .audioroute = 2, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_HAUPPAUGE_NOVASE2_S1] = { - .name = "Hauppauge Nova-SE2 DVB-S", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_KWORLD_DVBS_100] = { - .name = "KWorld DVB-S 100", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .audio_chip = V4L2_IDENT_WM8775, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - /* 2: Line-In */ - .audioroute = 2, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - /* 2: Line-In */ - .audioroute = 2, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - /* 2: Line-In */ - .audioroute = 2, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_HAUPPAUGE_HVR1100] = { - .name = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid", - .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - }}, - /* fixme: Add radio support */ - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_HAUPPAUGE_HVR1100LP] = { - .name = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)", - .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - }}, - /* fixme: Add radio support */ - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_DNTV_LIVE_DVB_T_PRO] = { - .name = "digitalnow DNTV Live! DVB-T Pro", - .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE | - TDA9887_PORT2_ACTIVE, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0xf80808, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0xf80808, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0xf80808, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0xf80808, - }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_KWORLD_DVB_T_CX22702] = { - /* Kworld V-stream Xpert DVB-T with Thomson tuner */ - /* DTT 7579 Conexant CX22702-19 Conexant CX2388x */ - /* Manenti Marco <marco_manenti@colman.it> */ - .name = "KWorld/VStream XPert DVB-T with cx22702", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0700, - .gpio2 = 0x0101, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x0700, - .gpio2 = 0x0101, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = { - .name = "DViCO FusionHDTV DVB-T Dual Digital", - .tuner_type = TUNER_ABSENT, /* No analog tuner */ - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x000067df, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x000067df, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = { - .name = "KWorld HardwareMpegTV XPert", - .tuner_type = TUNER_PHILIPS_TDA8290, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x3de2, - .gpio2 = 0x00ff, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x3de6, - .audioroute = 1, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x3de6, - .audioroute = 1, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x3de6, - .gpio2 = 0x00ff, - }, - .mpeg = CX88_MPEG_BLACKBIRD, - }, - [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = { - .name = "DViCO FusionHDTV DVB-T Hybrid", - .tuner_type = TUNER_THOMSON_FE6600, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0000a75f, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0000a75b, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x0000a75b, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_PCHDTV_HD5500] = { - .name = "pcHDTV HD5500 HDTV", - .tuner_type = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */ - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x87fd, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x87f9, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x87f9, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_KWORLD_MCE200_DELUXE] = { - /* FIXME: tested TV input only, disabled composite, - svideo and radio until they can be tested also. */ - .name = "Kworld MCE 200 Deluxe", - .tuner_type = TUNER_TENA_9533_DI, - .radio_type = UNSET, - .tda9887_conf = TDA9887_PRESENT, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0000BDE6 - }}, - .mpeg = CX88_MPEG_BLACKBIRD, - }, - [CX88_BOARD_PIXELVIEW_PLAYTV_P7000] = { - /* FIXME: SVideo, Composite and FM inputs are untested */ - .name = "PixelView PlayTV P7000", - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE | - TDA9887_PORT2_ACTIVE, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x5da6, - }}, - .mpeg = CX88_MPEG_BLACKBIRD, - }, - [CX88_BOARD_NPGTECH_REALTV_TOP10FM] = { - .name = "NPG Tech Real TV FM Top 10", - .tuner_type = TUNER_TNF_5335MF, /* Actually a TNF9535 */ - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0788, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x078b, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x078b, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x074a, - }, - }, - [CX88_BOARD_WINFAST_DTV2000H] = { - .name = "WinFast DTV2000 H", - .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x00017304, - .gpio1 = 0x00008203, - .gpio2 = 0x00017304, - .gpio3 = 0x02000000, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0001d701, - .gpio1 = 0x0000b207, - .gpio2 = 0x0001d701, - .gpio3 = 0x02000000, - }, { - .type = CX88_VMUX_COMPOSITE2, - .vmux = 2, - .gpio0 = 0x0001d503, - .gpio1 = 0x0000b207, - .gpio2 = 0x0001d503, - .gpio3 = 0x02000000, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 3, - .gpio0 = 0x0001d701, - .gpio1 = 0x0000b207, - .gpio2 = 0x0001d701, - .gpio3 = 0x02000000, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x00015702, - .gpio1 = 0x0000f207, - .gpio2 = 0x00015702, - .gpio3 = 0x02000000, - }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_WINFAST_DTV2000H_J] = { - .name = "WinFast DTV2000 H rev. J", - .tuner_type = TUNER_PHILIPS_FMD1216MEX_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x00017300, - .gpio1 = 0x00008207, - .gpio2 = 0x00000000, - .gpio3 = 0x02000000, - },{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x00018300, - .gpio1 = 0x0000f207, - .gpio2 = 0x00017304, - .gpio3 = 0x02000000, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x00018301, - .gpio1 = 0x0000f207, - .gpio2 = 0x00017304, - .gpio3 = 0x02000000, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x00018301, - .gpio1 = 0x0000f207, - .gpio2 = 0x00017304, - .gpio3 = 0x02000000, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x00015702, - .gpio1 = 0x0000f207, - .gpio2 = 0x00015702, - .gpio3 = 0x02000000, - }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_GENIATECH_DVBS] = { - .name = "Geniatech DVB-S", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_HAUPPAUGE_HVR3000] = { - .name = "Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T", - .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .audio_chip = V4L2_IDENT_WM8775, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x84bf, - /* 1: TV Audio / FM Mono */ - .audioroute = 1, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x84bf, - /* 2: Line-In */ - .audioroute = 2, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x84bf, - /* 2: Line-In */ - .audioroute = 2, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x84bf, - /* 4: FM Stereo (untested) */ - .audioroute = 8, - }, - .mpeg = CX88_MPEG_DVB, - .num_frontends = 2, - }, - [CX88_BOARD_NORWOOD_MICRO] = { - .name = "Norwood Micro TV Tuner", - .tuner_type = TUNER_TNF_5335MF, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0709, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x070b, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x070b, - }}, - }, - [CX88_BOARD_TE_DTV_250_OEM_SWANN] = { - .name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM", - .tuner_type = TUNER_LG_PAL_NEW_TAPC, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x003fffff, - .gpio1 = 0x00e00000, - .gpio2 = 0x003fffff, - .gpio3 = 0x02000000, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x003fffff, - .gpio1 = 0x00e00000, - .gpio2 = 0x003fffff, - .gpio3 = 0x02000000, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x003fffff, - .gpio1 = 0x00e00000, - .gpio2 = 0x003fffff, - .gpio3 = 0x02000000, - }}, - }, - [CX88_BOARD_HAUPPAUGE_HVR1300] = { - .name = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder", - .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .audio_chip = V4L2_IDENT_WM8775, - /* - * gpio0 as reported by Mike Crash <mike AT mikecrash.com> - */ - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0xef88, - /* 1: TV Audio / FM Mono */ - .audioroute = 1, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0xef88, - /* 2: Line-In */ - .audioroute = 2, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0xef88, - /* 2: Line-In */ - .audioroute = 2, - }}, - .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0xef88, - /* 4: FM Stereo (untested) */ - .audioroute = 8, - }, - }, - [CX88_BOARD_SAMSUNG_SMT_7020] = { - .name = "Samsung SMT 7020 DVB-S", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = { { - .type = CX88_VMUX_DVB, - .vmux = 0, - } }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_ADSTECH_PTV_390] = { - .name = "ADS Tech Instant Video PCI", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DEBUG, - .vmux = 3, - .gpio0 = 0x04ff, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x07fa, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x07fa, - }}, - }, - [CX88_BOARD_PINNACLE_PCTV_HD_800i] = { - .name = "Pinnacle PCTV HD 800i", - .tuner_type = TUNER_XC5000, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x04fb, - .gpio1 = 0x10ff, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x04fb, - .gpio1 = 0x10ef, - .audioroute = 1, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x04fb, - .gpio1 = 0x10ef, - .audioroute = 1, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = { - .name = "DViCO FusionHDTV 5 PCI nano", - /* xc3008 tuner, digital only for now */ - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x000027df, /* Unconfirmed */ - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x000027df, /* Unconfirmed */ - .audioroute = 1, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x000027df, /* Unconfirmed */ - .audioroute = 1, - } }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_PINNACLE_HYBRID_PCTV] = { - .name = "Pinnacle Hybrid PCTV", - .tuner_type = TUNER_XC2028, - .tuner_addr = 0x61, - .radio_type = UNSET, - .radio_addr = ADDR_UNSET, - .input = { { - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x004ff, - .gpio1 = 0x010ff, - .gpio2 = 0x00001, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x004fb, - .gpio1 = 0x010ef, - .audioroute = 1, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x004fb, - .gpio1 = 0x010ef, - .audioroute = 1, - } }, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x004ff, - .gpio1 = 0x010ff, - .gpio2 = 0x0ff, - }, - .mpeg = CX88_MPEG_DVB, - }, - /* Terry Wu <terrywu2009@gmail.com> */ - /* TV Audio : set GPIO 2, 18, 19 value to 0, 1, 0 */ - /* FM Audio : set GPIO 2, 18, 19 value to 0, 0, 0 */ - /* Line-in Audio : set GPIO 2, 18, 19 value to 0, 1, 1 */ - /* Mute Audio : set GPIO 2 value to 1 */ - [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { - .name = "Leadtek TV2000 XP Global", - .tuner_type = TUNER_XC2028, - .tuner_addr = 0x61, - .radio_type = UNSET, - .radio_addr = ADDR_UNSET, - .input = { { - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x0000, - .gpio2 = 0x0C04, /* pin 18 = 1, pin 19 = 0 */ - .gpio3 = 0x0000, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x0000, - .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */ - .gpio3 = 0x0000, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x0000, - .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */ - .gpio3 = 0x0000, - } }, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x0000, - .gpio2 = 0x0C00, /* pin 18 = 0, pin 19 = 0 */ - .gpio3 = 0x0000, - }, - }, - [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36] = { - .name = "Leadtek TV2000 XP Global (SC4100)", - .tuner_type = TUNER_XC4000, - .tuner_addr = 0x61, - .radio_type = UNSET, - .radio_addr = ADDR_UNSET, - .input = { { - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x0000, - .gpio2 = 0x0C04, /* pin 18 = 1, pin 19 = 0 */ - .gpio3 = 0x0000, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x0000, - .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */ - .gpio3 = 0x0000, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x0000, - .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */ - .gpio3 = 0x0000, - } }, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x0000, - .gpio2 = 0x0C00, /* pin 18 = 0, pin 19 = 0 */ - .gpio3 = 0x0000, - }, - }, - [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43] = { - .name = "Leadtek TV2000 XP Global (XC4100)", - .tuner_type = TUNER_XC4000, - .tuner_addr = 0x61, - .radio_type = UNSET, - .radio_addr = ADDR_UNSET, - .input = { { - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x6040, /* pin 14 = 1, pin 13 = 0 */ - .gpio2 = 0x0000, - .gpio3 = 0x0000, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x6060, /* pin 14 = 1, pin 13 = 1 */ - .gpio2 = 0x0000, - .gpio3 = 0x0000, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x6060, /* pin 14 = 1, pin 13 = 1 */ - .gpio2 = 0x0000, - .gpio3 = 0x0000, - } }, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x6000, /* pin 14 = 1, pin 13 = 0 */ - .gpio2 = 0x0000, - .gpio3 = 0x0000, - }, - }, - [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { - .name = "PowerColor RA330", /* Long names may confuse LIRC. */ - .tuner_type = TUNER_XC2028, - .tuner_addr = 0x61, - .input = { { - .type = CX88_VMUX_DEBUG, - .vmux = 3, /* Due to the way the cx88 driver is written, */ - .gpio0 = 0x00ff, /* there is no way to deactivate audio pass- */ - .gpio1 = 0xf39d, /* through without this entry. Furthermore, if */ - .gpio3 = 0x0000, /* the TV mux entry is first, you get audio */ - }, { /* from the tuner on boot for a little while. */ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x00ff, - .gpio1 = 0xf35d, - .gpio3 = 0x0000, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x00ff, - .gpio1 = 0xf37d, - .gpio3 = 0x0000, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x000ff, - .gpio1 = 0x0f37d, - .gpio3 = 0x00000, - } }, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x000ff, - .gpio1 = 0x0f35d, - .gpio3 = 0x00000, - }, - }, - [CX88_BOARD_GENIATECH_X8000_MT] = { - /* Also PowerColor Real Angel 330 and Geniatech X800 OEM */ - .name = "Geniatech X8000-MT DVBT", - .tuner_type = TUNER_XC2028, - .tuner_addr = 0x61, - .input = { { - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x00000000, - .gpio1 = 0x00e3e341, - .gpio2 = 0x00000000, - .gpio3 = 0x00000000, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x00000000, - .gpio1 = 0x00e3e361, - .gpio2 = 0x00000000, - .gpio3 = 0x00000000, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x00000000, - .gpio1 = 0x00e3e361, - .gpio2 = 0x00000000, - .gpio3 = 0x00000000, - } }, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x00000000, - .gpio1 = 0x00e3e341, - .gpio2 = 0x00000000, - .gpio3 = 0x00000000, - }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = { - .name = "DViCO FusionHDTV DVB-T PRO", - .tuner_type = TUNER_XC2028, - .tuner_addr = 0x61, - .radio_type = UNSET, - .radio_addr = ADDR_UNSET, - .input = { { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x000067df, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x000067df, - } }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD] = { - .name = "DViCO FusionHDTV 7 Gold", - .tuner_type = TUNER_XC5000, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x10df, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x16d9, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x16d9, - }}, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_PROLINK_PV_8000GT] = { - .name = "Prolink Pixelview MPEG 8000GT", - .tuner_type = TUNER_XC2028, - .tuner_addr = 0x61, - .input = { { - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0ff, - .gpio2 = 0x0cfb, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio2 = 0x0cfb, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio2 = 0x0cfb, - } }, - .radio = { - .type = CX88_RADIO, - .gpio2 = 0x0cfb, - }, - }, - [CX88_BOARD_PROLINK_PV_GLOBAL_XTREME] = { - .name = "Prolink Pixelview Global Extreme", - .tuner_type = TUNER_XC2028, - .tuner_addr = 0x61, - .input = { { - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x04fb, - .gpio1 = 0x04080, - .gpio2 = 0x0cf7, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x04fb, - .gpio1 = 0x04080, - .gpio2 = 0x0cfb, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x04fb, - .gpio1 = 0x04080, - .gpio2 = 0x0cfb, - } }, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x04ff, - .gpio1 = 0x04080, - .gpio2 = 0x0cf7, - }, - }, - /* Both radio, analog and ATSC work with this board. - However, for analog to work, s5h1409 gate should be open, - otherwise, tuner-xc3028 won't be detected. - A proper fix require using the newer i2c methods to add - tuner-xc3028 without doing an i2c probe. - */ - [CX88_BOARD_KWORLD_ATSC_120] = { - .name = "Kworld PlusTV HD PCI 120 (ATSC 120)", - .tuner_type = TUNER_XC2028, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = { { - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x000000ff, - .gpio1 = 0x0000f35d, - .gpio2 = 0x00000000, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x000000ff, - .gpio1 = 0x0000f37e, - .gpio2 = 0x00000000, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x000000ff, - .gpio1 = 0x0000f37e, - .gpio2 = 0x00000000, - } }, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x000000ff, - .gpio1 = 0x0000f35d, - .gpio2 = 0x00000000, - }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_HAUPPAUGE_HVR4000] = { - .name = "Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid", - .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .audio_chip = V4L2_IDENT_WM8775, - /* - * GPIO0 (WINTV2000) - * - * Analogue SAT DVB-T - * Antenna 0xc4bf 0xc4bb - * Composite 0xc4bf 0xc4bb - * S-Video 0xc4bf 0xc4bb - * Composite1 0xc4ff 0xc4fb - * S-Video1 0xc4ff 0xc4fb - * - * BIT VALUE FUNCTION GP{x}_IO - * 0 1 I:? - * 1 1 I:? - * 2 1 O:MPEG PORT 0=DVB-T 1=DVB-S - * 3 1 I:? - * 4 1 I:? - * 5 1 I:? - * 6 0 O:INPUT SELECTOR 0=INTERNAL 1=EXPANSION - * 7 1 O:DVB-T DEMOD RESET LOW - * - * BIT VALUE FUNCTION GP{x}_OE - * 8 0 I - * 9 0 I - * a 1 O - * b 0 I - * c 0 I - * d 0 I - * e 1 O - * f 1 O - * - * WM8775 ADC - * - * 1: TV Audio / FM Mono - * 2: Line-In - * 3: Line-In Expansion - * 4: FM Stereo - */ - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0xc4bf, - /* 1: TV Audio / FM Mono */ - .audioroute = 1, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0xc4bf, - /* 2: Line-In */ - .audioroute = 2, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0xc4bf, - /* 2: Line-In */ - .audioroute = 2, - } }, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0xc4bf, - /* 4: FM Stereo */ - .audioroute = 8, - }, - .mpeg = CX88_MPEG_DVB, - .num_frontends = 2, - }, - [CX88_BOARD_HAUPPAUGE_HVR4000LITE] = { - .name = "Hauppauge WinTV-HVR4000(Lite) DVB-S/S2", - .tuner_type = UNSET, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - } }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_TEVII_S420] = { - .name = "TeVii S420 DVB-S", - .tuner_type = UNSET, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - } }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_TEVII_S460] = { - .name = "TeVii S460 DVB-S/S2", - .tuner_type = UNSET, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - } }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_TEVII_S464] = { - .name = "TeVii S464 DVB-S/S2", - .tuner_type = UNSET, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - } }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_OMICOM_SS4_PCI] = { - .name = "Omicom SS4 DVB-S/S2 PCI", - .tuner_type = UNSET, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - } }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_TBS_8910] = { - .name = "TBS 8910 DVB-S", - .tuner_type = UNSET, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - } }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_TBS_8920] = { - .name = "TBS 8920 DVB-S/S2", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - .gpio0 = 0x8080, - } }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_PROF_6200] = { - .name = "Prof 6200 DVB-S", - .tuner_type = UNSET, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - } }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_PROF_7300] = { - .name = "PROF 7300 DVB-S/S2", - .tuner_type = UNSET, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - } }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_SATTRADE_ST4200] = { - .name = "SATTRADE ST4200 DVB-S/S2", - .tuner_type = UNSET, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - } }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII] = { - .name = "Terratec Cinergy HT PCI MKII", - .tuner_type = TUNER_XC2028, - .tuner_addr = 0x61, - .radio_type = UNSET, - .radio_addr = ADDR_UNSET, - .input = { { - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x004ff, - .gpio1 = 0x010ff, - .gpio2 = 0x00001, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x004fb, - .gpio1 = 0x010ef, - .audioroute = 1, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x004fb, - .gpio1 = 0x010ef, - .audioroute = 1, - } }, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x004ff, - .gpio1 = 0x010ff, - .gpio2 = 0x0ff, - }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_HAUPPAUGE_IRONLY] = { - .name = "Hauppauge WinTV-IR Only", - .tuner_type = UNSET, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - }, - [CX88_BOARD_WINFAST_DTV1800H] = { - .name = "Leadtek WinFast DTV1800 Hybrid", - .tuner_type = TUNER_XC2028, - .radio_type = UNSET, - .tuner_addr = 0x61, - .radio_addr = ADDR_UNSET, - /* - * GPIO setting - * - * 2: mute (0=off,1=on) - * 12: tuner reset pin - * 13: audio source (0=tuner audio,1=line in) - * 14: FM (0=on,1=off ???) - */ - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x6040, /* pin 13 = 0, pin 14 = 1 */ - .gpio2 = 0x0000, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */ - .gpio2 = 0x0000, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */ - .gpio2 = 0x0000, - } }, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x6000, /* pin 13 = 0, pin 14 = 0 */ - .gpio2 = 0x0000, - }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_WINFAST_DTV1800H_XC4000] = { - .name = "Leadtek WinFast DTV1800 H (XC4000)", - .tuner_type = TUNER_XC4000, - .radio_type = UNSET, - .tuner_addr = 0x61, - .radio_addr = ADDR_UNSET, - /* - * GPIO setting - * - * 2: mute (0=off,1=on) - * 12: tuner reset pin - * 13: audio source (0=tuner audio,1=line in) - * 14: FM (0=on,1=off ???) - */ - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x6040, /* pin 13 = 0, pin 14 = 1 */ - .gpio2 = 0x0000, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */ - .gpio2 = 0x0000, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x6060, /* pin 13 = 1, pin 14 = 1 */ - .gpio2 = 0x0000, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x0400, /* pin 2 = 0 */ - .gpio1 = 0x6000, /* pin 13 = 0, pin 14 = 0 */ - .gpio2 = 0x0000, - }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_WINFAST_DTV2000H_PLUS] = { - .name = "Leadtek WinFast DTV2000 H PLUS", - .tuner_type = TUNER_XC4000, - .radio_type = UNSET, - .tuner_addr = 0x61, - .radio_addr = ADDR_UNSET, - /* - * GPIO - * 2: 1: mute audio - * 12: 0: reset XC4000 - * 13: 1: audio input is line in (0: tuner) - * 14: 0: FM radio - * 16: 0: RF input is cable - */ - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x0403, - .gpio1 = 0xF0D7, - .gpio2 = 0x0101, - .gpio3 = 0x0000, - }, { - .type = CX88_VMUX_CABLE, - .vmux = 0, - .gpio0 = 0x0403, - .gpio1 = 0xF0D7, - .gpio2 = 0x0100, - .gpio3 = 0x0000, - }, { - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x0403, /* was 0x0407 */ - .gpio1 = 0xF0F7, - .gpio2 = 0x0101, - .gpio3 = 0x0000, - }, { - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x0403, /* was 0x0407 */ - .gpio1 = 0xF0F7, - .gpio2 = 0x0101, - .gpio3 = 0x0000, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x0403, - .gpio1 = 0xF097, - .gpio2 = 0x0100, - .gpio3 = 0x0000, - }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_PROF_7301] = { - .name = "Prof 7301 DVB-S/S2", - .tuner_type = UNSET, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = { { - .type = CX88_VMUX_DVB, - .vmux = 0, - } }, - .mpeg = CX88_MPEG_DVB, - }, - [CX88_BOARD_TWINHAN_VP1027_DVBS] = { - .name = "Twinhan VP-1027 DVB-S", - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - } }, - .mpeg = CX88_MPEG_DVB, - }, -}; - -/* ------------------------------------------------------------------ */ -/* PCI subsystem IDs */ - -static const struct cx88_subid cx88_subids[] = { - { - .subvendor = 0x0070, - .subdevice = 0x3400, - .card = CX88_BOARD_HAUPPAUGE, - },{ - .subvendor = 0x0070, - .subdevice = 0x3401, - .card = CX88_BOARD_HAUPPAUGE, - },{ - .subvendor = 0x14c7, - .subdevice = 0x0106, - .card = CX88_BOARD_GDI, - },{ - .subvendor = 0x14c7, - .subdevice = 0x0107, /* with mpeg encoder */ - .card = CX88_BOARD_GDI, - },{ - .subvendor = PCI_VENDOR_ID_ATI, - .subdevice = 0x00f8, - .card = CX88_BOARD_ATI_WONDER_PRO, - }, { - .subvendor = PCI_VENDOR_ID_ATI, - .subdevice = 0x00f9, - .card = CX88_BOARD_ATI_WONDER_PRO, - }, { - .subvendor = 0x107d, - .subdevice = 0x6611, - .card = CX88_BOARD_WINFAST2000XP_EXPERT, - },{ - .subvendor = 0x107d, - .subdevice = 0x6613, /* NTSC */ - .card = CX88_BOARD_WINFAST2000XP_EXPERT, - },{ - .subvendor = 0x107d, - .subdevice = 0x6620, - .card = CX88_BOARD_WINFAST_DV2000, - },{ - .subvendor = 0x107d, - .subdevice = 0x663b, - .card = CX88_BOARD_LEADTEK_PVR2000, - },{ - .subvendor = 0x107d, - .subdevice = 0x663c, - .card = CX88_BOARD_LEADTEK_PVR2000, - },{ - .subvendor = 0x1461, - .subdevice = 0x000b, - .card = CX88_BOARD_AVERTV_STUDIO_303, - },{ - .subvendor = 0x1462, - .subdevice = 0x8606, - .card = CX88_BOARD_MSI_TVANYWHERE_MASTER, - },{ - .subvendor = 0x10fc, - .subdevice = 0xd003, - .card = CX88_BOARD_IODATA_GVVCP3PCI, - },{ - .subvendor = 0x1043, - .subdevice = 0x4823, /* with mpeg encoder */ - .card = CX88_BOARD_ASUS_PVR_416, - },{ - .subvendor = 0x17de, - .subdevice = 0x08a6, - .card = CX88_BOARD_KWORLD_DVB_T, - },{ - .subvendor = 0x18ac, - .subdevice = 0xd810, - .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q, - },{ - .subvendor = 0x18ac, - .subdevice = 0xd820, - .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T, - },{ - .subvendor = 0x18ac, - .subdevice = 0xdb00, - .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1, - },{ - .subvendor = 0x0070, - .subdevice = 0x9002, - .card = CX88_BOARD_HAUPPAUGE_DVB_T1, - },{ - .subvendor = 0x14f1, - .subdevice = 0x0187, - .card = CX88_BOARD_CONEXANT_DVB_T1, - },{ - .subvendor = 0x1540, - .subdevice = 0x2580, - .card = CX88_BOARD_PROVIDEO_PV259, - },{ - .subvendor = 0x18ac, - .subdevice = 0xdb10, - .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS, - },{ - .subvendor = 0x1554, - .subdevice = 0x4811, - .card = CX88_BOARD_PIXELVIEW, - },{ - .subvendor = 0x7063, - .subdevice = 0x3000, /* HD-3000 card */ - .card = CX88_BOARD_PCHDTV_HD3000, - },{ - .subvendor = 0x17de, - .subdevice = 0xa8a6, - .card = CX88_BOARD_DNTV_LIVE_DVB_T, - },{ - .subvendor = 0x0070, - .subdevice = 0x2801, - .card = CX88_BOARD_HAUPPAUGE_ROSLYN, - },{ - .subvendor = 0x14f1, - .subdevice = 0x0342, - .card = CX88_BOARD_DIGITALLOGIC_MEC, - },{ - .subvendor = 0x10fc, - .subdevice = 0xd035, - .card = CX88_BOARD_IODATA_GVBCTV7E, - },{ - .subvendor = 0x1421, - .subdevice = 0x0334, - .card = CX88_BOARD_ADSTECH_DVB_T_PCI, - },{ - .subvendor = 0x153b, - .subdevice = 0x1166, - .card = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1, - },{ - .subvendor = 0x18ac, - .subdevice = 0xd500, - .card = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD, - },{ - .subvendor = 0x1461, - .subdevice = 0x8011, - .card = CX88_BOARD_AVERMEDIA_ULTRATV_MC_550, - },{ - .subvendor = PCI_VENDOR_ID_ATI, - .subdevice = 0xa101, - .card = CX88_BOARD_ATI_HDTVWONDER, - },{ - .subvendor = 0x107d, - .subdevice = 0x665f, - .card = CX88_BOARD_WINFAST_DTV1000, - },{ - .subvendor = 0x1461, - .subdevice = 0x000a, - .card = CX88_BOARD_AVERTV_303, - },{ - .subvendor = 0x0070, - .subdevice = 0x9200, - .card = CX88_BOARD_HAUPPAUGE_NOVASE2_S1, - },{ - .subvendor = 0x0070, - .subdevice = 0x9201, - .card = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1, - },{ - .subvendor = 0x0070, - .subdevice = 0x9202, - .card = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1, - },{ - .subvendor = 0x17de, - .subdevice = 0x08b2, - .card = CX88_BOARD_KWORLD_DVBS_100, - },{ - .subvendor = 0x0070, - .subdevice = 0x9400, - .card = CX88_BOARD_HAUPPAUGE_HVR1100, - },{ - .subvendor = 0x0070, - .subdevice = 0x9402, - .card = CX88_BOARD_HAUPPAUGE_HVR1100, - },{ - .subvendor = 0x0070, - .subdevice = 0x9800, - .card = CX88_BOARD_HAUPPAUGE_HVR1100LP, - },{ - .subvendor = 0x0070, - .subdevice = 0x9802, - .card = CX88_BOARD_HAUPPAUGE_HVR1100LP, - },{ - .subvendor = 0x0070, - .subdevice = 0x9001, - .card = CX88_BOARD_HAUPPAUGE_DVB_T1, - },{ - .subvendor = 0x1822, - .subdevice = 0x0025, - .card = CX88_BOARD_DNTV_LIVE_DVB_T_PRO, - },{ - .subvendor = 0x17de, - .subdevice = 0x08a1, - .card = CX88_BOARD_KWORLD_DVB_T_CX22702, - },{ - .subvendor = 0x18ac, - .subdevice = 0xdb50, - .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL, - },{ - .subvendor = 0x18ac, - .subdevice = 0xdb54, - .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL, - /* Re-branded DViCO: DigitalNow DVB-T Dual */ - },{ - .subvendor = 0x18ac, - .subdevice = 0xdb11, - .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS, - /* Re-branded DViCO: UltraView DVB-T Plus */ - }, { - .subvendor = 0x18ac, - .subdevice = 0xdb30, - .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO, - }, { - .subvendor = 0x17de, - .subdevice = 0x0840, - .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, - },{ - .subvendor = 0x1421, - .subdevice = 0x0305, - .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, - },{ - .subvendor = 0x18ac, - .subdevice = 0xdb40, - .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID, - },{ - .subvendor = 0x18ac, - .subdevice = 0xdb44, - .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID, - },{ - .subvendor = 0x7063, - .subdevice = 0x5500, - .card = CX88_BOARD_PCHDTV_HD5500, - },{ - .subvendor = 0x17de, - .subdevice = 0x0841, - .card = CX88_BOARD_KWORLD_MCE200_DELUXE, - },{ - .subvendor = 0x1822, - .subdevice = 0x0019, - .card = CX88_BOARD_DNTV_LIVE_DVB_T_PRO, - },{ - .subvendor = 0x1554, - .subdevice = 0x4813, - .card = CX88_BOARD_PIXELVIEW_PLAYTV_P7000, - },{ - .subvendor = 0x14f1, - .subdevice = 0x0842, - .card = CX88_BOARD_NPGTECH_REALTV_TOP10FM, - },{ - .subvendor = 0x107d, - .subdevice = 0x665e, - .card = CX88_BOARD_WINFAST_DTV2000H, - },{ - .subvendor = 0x107d, - .subdevice = 0x6f2b, - .card = CX88_BOARD_WINFAST_DTV2000H_J, - },{ - .subvendor = 0x18ac, - .subdevice = 0xd800, /* FusionHDTV 3 Gold (original revision) */ - .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q, - },{ - .subvendor = 0x14f1, - .subdevice = 0x0084, - .card = CX88_BOARD_GENIATECH_DVBS, - },{ - .subvendor = 0x0070, - .subdevice = 0x1404, - .card = CX88_BOARD_HAUPPAUGE_HVR3000, - }, { - .subvendor = 0x18ac, - .subdevice = 0xdc00, - .card = CX88_BOARD_SAMSUNG_SMT_7020, - }, { - .subvendor = 0x18ac, - .subdevice = 0xdccd, - .card = CX88_BOARD_SAMSUNG_SMT_7020, - },{ - .subvendor = 0x1461, - .subdevice = 0xc111, /* AverMedia M150-D */ - /* This board is known to work with the ASUS PVR416 config */ - .card = CX88_BOARD_ASUS_PVR_416, - },{ - .subvendor = 0xc180, - .subdevice = 0xc980, - .card = CX88_BOARD_TE_DTV_250_OEM_SWANN, - },{ - .subvendor = 0x0070, - .subdevice = 0x9600, - .card = CX88_BOARD_HAUPPAUGE_HVR1300, - },{ - .subvendor = 0x0070, - .subdevice = 0x9601, - .card = CX88_BOARD_HAUPPAUGE_HVR1300, - },{ - .subvendor = 0x0070, - .subdevice = 0x9602, - .card = CX88_BOARD_HAUPPAUGE_HVR1300, - },{ - .subvendor = 0x107d, - .subdevice = 0x6632, - .card = CX88_BOARD_LEADTEK_PVR2000, - },{ - .subvendor = 0x12ab, - .subdevice = 0x2300, /* Club3D Zap TV2100 */ - .card = CX88_BOARD_KWORLD_DVB_T_CX22702, - },{ - .subvendor = 0x0070, - .subdevice = 0x9000, - .card = CX88_BOARD_HAUPPAUGE_DVB_T1, - },{ - .subvendor = 0x0070, - .subdevice = 0x1400, - .card = CX88_BOARD_HAUPPAUGE_HVR3000, - },{ - .subvendor = 0x0070, - .subdevice = 0x1401, - .card = CX88_BOARD_HAUPPAUGE_HVR3000, - },{ - .subvendor = 0x0070, - .subdevice = 0x1402, - .card = CX88_BOARD_HAUPPAUGE_HVR3000, - },{ - .subvendor = 0x1421, - .subdevice = 0x0341, /* ADS Tech InstantTV DVB-S */ - .card = CX88_BOARD_KWORLD_DVBS_100, - },{ - .subvendor = 0x1421, - .subdevice = 0x0390, - .card = CX88_BOARD_ADSTECH_PTV_390, - },{ - .subvendor = 0x11bd, - .subdevice = 0x0051, - .card = CX88_BOARD_PINNACLE_PCTV_HD_800i, - }, { - .subvendor = 0x18ac, - .subdevice = 0xd530, - .card = CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO, - }, { - .subvendor = 0x12ab, - .subdevice = 0x1788, - .card = CX88_BOARD_PINNACLE_HYBRID_PCTV, - }, { - .subvendor = 0x14f1, - .subdevice = 0xea3d, - .card = CX88_BOARD_POWERCOLOR_REAL_ANGEL, - }, { - .subvendor = 0x107d, - .subdevice = 0x6f18, - .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, - }, { - .subvendor = 0x14f1, - .subdevice = 0x8852, - .card = CX88_BOARD_GENIATECH_X8000_MT, - }, { - .subvendor = 0x18ac, - .subdevice = 0xd610, - .card = CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD, - }, { - .subvendor = 0x1554, - .subdevice = 0x4935, - .card = CX88_BOARD_PROLINK_PV_8000GT, - }, { - .subvendor = 0x1554, - .subdevice = 0x4976, - .card = CX88_BOARD_PROLINK_PV_GLOBAL_XTREME, - }, { - .subvendor = 0x17de, - .subdevice = 0x08c1, - .card = CX88_BOARD_KWORLD_ATSC_120, - }, { - .subvendor = 0x0070, - .subdevice = 0x6900, - .card = CX88_BOARD_HAUPPAUGE_HVR4000, - }, { - .subvendor = 0x0070, - .subdevice = 0x6904, - .card = CX88_BOARD_HAUPPAUGE_HVR4000, - }, { - .subvendor = 0x0070, - .subdevice = 0x6902, - .card = CX88_BOARD_HAUPPAUGE_HVR4000, - }, { - .subvendor = 0x0070, - .subdevice = 0x6905, - .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE, - }, { - .subvendor = 0x0070, - .subdevice = 0x6906, - .card = CX88_BOARD_HAUPPAUGE_HVR4000LITE, - }, { - .subvendor = 0xd420, - .subdevice = 0x9022, - .card = CX88_BOARD_TEVII_S420, - }, { - .subvendor = 0xd460, - .subdevice = 0x9022, - .card = CX88_BOARD_TEVII_S460, - }, { - .subvendor = 0xd464, - .subdevice = 0x9022, - .card = CX88_BOARD_TEVII_S464, - }, { - .subvendor = 0xA044, - .subdevice = 0x2011, - .card = CX88_BOARD_OMICOM_SS4_PCI, - }, { - .subvendor = 0x8910, - .subdevice = 0x8888, - .card = CX88_BOARD_TBS_8910, - }, { - .subvendor = 0x8920, - .subdevice = 0x8888, - .card = CX88_BOARD_TBS_8920, - }, { - .subvendor = 0xb022, - .subdevice = 0x3022, - .card = CX88_BOARD_PROF_6200, - }, { - .subvendor = 0xB033, - .subdevice = 0x3033, - .card = CX88_BOARD_PROF_7300, - }, { - .subvendor = 0xb200, - .subdevice = 0x4200, - .card = CX88_BOARD_SATTRADE_ST4200, - }, { - .subvendor = 0x153b, - .subdevice = 0x1177, - .card = CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII, - }, { - .subvendor = 0x0070, - .subdevice = 0x9290, - .card = CX88_BOARD_HAUPPAUGE_IRONLY, - }, { - .subvendor = 0x107d, - .subdevice = 0x6654, - .card = CX88_BOARD_WINFAST_DTV1800H, - }, { - /* WinFast DTV1800 H with XC4000 tuner */ - .subvendor = 0x107d, - .subdevice = 0x6f38, - .card = CX88_BOARD_WINFAST_DTV1800H_XC4000, - }, { - .subvendor = 0x107d, - .subdevice = 0x6f42, - .card = CX88_BOARD_WINFAST_DTV2000H_PLUS, - }, { - /* PVR2000 PAL Model [107d:6630] */ - .subvendor = 0x107d, - .subdevice = 0x6630, - .card = CX88_BOARD_LEADTEK_PVR2000, - }, { - /* PVR2000 PAL Model [107d:6638] */ - .subvendor = 0x107d, - .subdevice = 0x6638, - .card = CX88_BOARD_LEADTEK_PVR2000, - }, { - /* PVR2000 NTSC Model [107d:6631] */ - .subvendor = 0x107d, - .subdevice = 0x6631, - .card = CX88_BOARD_LEADTEK_PVR2000, - }, { - /* PVR2000 NTSC Model [107d:6637] */ - .subvendor = 0x107d, - .subdevice = 0x6637, - .card = CX88_BOARD_LEADTEK_PVR2000, - }, { - /* PVR2000 NTSC Model [107d:663d] */ - .subvendor = 0x107d, - .subdevice = 0x663d, - .card = CX88_BOARD_LEADTEK_PVR2000, - }, { - /* DV2000 NTSC Model [107d:6621] */ - .subvendor = 0x107d, - .subdevice = 0x6621, - .card = CX88_BOARD_WINFAST_DV2000, - }, { - /* TV2000 XP Global [107d:6618] */ - .subvendor = 0x107d, - .subdevice = 0x6618, - .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, - }, { - /* TV2000 XP Global [107d:6618] */ - .subvendor = 0x107d, - .subdevice = 0x6619, - .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, - }, { - /* WinFast TV2000 XP Global with XC4000 tuner */ - .subvendor = 0x107d, - .subdevice = 0x6f36, - .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36, - }, { - /* WinFast TV2000 XP Global with XC4000 tuner and different GPIOs */ - .subvendor = 0x107d, - .subdevice = 0x6f43, - .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43, - }, { - .subvendor = 0xb034, - .subdevice = 0x3034, - .card = CX88_BOARD_PROF_7301, - }, { - .subvendor = 0x1822, - .subdevice = 0x0023, - .card = CX88_BOARD_TWINHAN_VP1027_DVBS, - }, -}; - -/* ----------------------------------------------------------------------- */ -/* some leadtek specific stuff */ - -static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) -{ - if (eeprom_data[4] != 0x7d || - eeprom_data[5] != 0x10 || - eeprom_data[7] != 0x66) { - warn_printk(core, "Leadtek eeprom invalid.\n"); - return; - } - - /* Terry Wu <terrywu2009@gmail.com> */ - switch (eeprom_data[6]) { - case 0x13: /* SSID 6613 for TV2000 XP Expert NTSC Model */ - case 0x21: /* SSID 6621 for DV2000 NTSC Model */ - case 0x31: /* SSID 6631 for PVR2000 NTSC Model */ - case 0x37: /* SSID 6637 for PVR2000 NTSC Model */ - case 0x3d: /* SSID 6637 for PVR2000 NTSC Model */ - core->board.tuner_type = TUNER_PHILIPS_FM1236_MK3; - break; - default: - core->board.tuner_type = TUNER_PHILIPS_FM1216ME_MK3; - break; - } - - info_printk(core, "Leadtek Winfast 2000XP Expert config: " - "tuner=%d, eeprom[0]=0x%02x\n", - core->board.tuner_type, eeprom_data[0]); -} - -static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) -{ - struct tveeprom tv; - - tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data); - core->board.tuner_type = tv.tuner_type; - core->tuner_formats = tv.tuner_formats; - core->board.radio.type = tv.has_radio ? CX88_RADIO : 0; - - /* Make sure we support the board model */ - switch (tv.model) - { - case 14009: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in) */ - case 14019: /* WinTV-HVR3000 (Retail, IR Blaster, b/panel video, 3.5mm audio in) */ - case 14029: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - 880 bridge) */ - case 14109: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - low profile) */ - case 14129: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - 880 bridge - LP) */ - case 14559: /* WinTV-HVR3000 (OEM, no IR, b/panel video, 3.5mm audio in) */ - case 14569: /* WinTV-HVR3000 (OEM, no IR, no back panel video) */ - case 14659: /* WinTV-HVR3000 (OEM, no IR, b/panel video, RCA audio in - Low profile) */ - case 14669: /* WinTV-HVR3000 (OEM, no IR, no b/panel video - Low profile) */ - case 28552: /* WinTV-PVR 'Roslyn' (No IR) */ - case 34519: /* WinTV-PCI-FM */ - case 69009: - /* WinTV-HVR4000 (DVBS/S2/T, Video and IR, back panel inputs) */ - case 69100: /* WinTV-HVR4000LITE (DVBS/S2, IR) */ - case 69500: /* WinTV-HVR4000LITE (DVBS/S2, No IR) */ - case 69559: - /* WinTV-HVR4000 (DVBS/S2/T, Video no IR, back panel inputs) */ - case 69569: /* WinTV-HVR4000 (DVBS/S2/T, Video no IR) */ - case 90002: /* Nova-T-PCI (9002) */ - case 92001: /* Nova-S-Plus (Video and IR) */ - case 92002: /* Nova-S-Plus (Video and IR) */ - case 90003: /* Nova-T-PCI (9002 No RF out) */ - case 90500: /* Nova-T-PCI (oem) */ - case 90501: /* Nova-T-PCI (oem/IR) */ - case 92000: /* Nova-SE2 (OEM, No Video or IR) */ - case 92900: /* WinTV-IROnly (No analog or digital Video inputs) */ - case 94009: /* WinTV-HVR1100 (Video and IR Retail) */ - case 94501: /* WinTV-HVR1100 (Video and IR OEM) */ - case 96009: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX) */ - case 96019: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX/TX) */ - case 96559: /* WinTV-HVR1300 (PAL Video, MPEG Video no IR) */ - case 96569: /* WinTV-HVR1300 () */ - case 96659: /* WinTV-HVR1300 () */ - case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */ - /* known */ - break; - case CX88_BOARD_SAMSUNG_SMT_7020: - cx_set(MO_GP0_IO, 0x008989FF); - break; - default: - warn_printk(core, "warning: unknown hauppauge model #%d\n", - tv.model); - break; - } - - info_printk(core, "hauppauge eeprom: model=%d\n", tv.model); -} - -/* ----------------------------------------------------------------------- */ -/* some GDI (was: Modular Technology) specific stuff */ - -static const struct { - int id; - int fm; - const char *name; -} gdi_tuner[] = { - [ 0x01 ] = { .id = TUNER_ABSENT, - .name = "NTSC_M" }, - [ 0x02 ] = { .id = TUNER_ABSENT, - .name = "PAL_B" }, - [ 0x03 ] = { .id = TUNER_ABSENT, - .name = "PAL_I" }, - [ 0x04 ] = { .id = TUNER_ABSENT, - .name = "PAL_D" }, - [ 0x05 ] = { .id = TUNER_ABSENT, - .name = "SECAM" }, - - [ 0x10 ] = { .id = TUNER_ABSENT, - .fm = 1, - .name = "TEMIC_4049" }, - [ 0x11 ] = { .id = TUNER_TEMIC_4136FY5, - .name = "TEMIC_4136" }, - [ 0x12 ] = { .id = TUNER_ABSENT, - .name = "TEMIC_4146" }, - - [ 0x20 ] = { .id = TUNER_PHILIPS_FQ1216ME, - .fm = 1, - .name = "PHILIPS_FQ1216_MK3" }, - [ 0x21 ] = { .id = TUNER_ABSENT, .fm = 1, - .name = "PHILIPS_FQ1236_MK3" }, - [ 0x22 ] = { .id = TUNER_ABSENT, - .name = "PHILIPS_FI1236_MK3" }, - [ 0x23 ] = { .id = TUNER_ABSENT, - .name = "PHILIPS_FI1216_MK3" }, -}; - -static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) -{ - const char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner)) - ? gdi_tuner[eeprom_data[0x0d]].name : NULL; - - info_printk(core, "GDI: tuner=%s\n", name ? name : "unknown"); - if (NULL == name) - return; - core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id; - core->board.radio.type = gdi_tuner[eeprom_data[0x0d]].fm ? - CX88_RADIO : 0; -} - -/* ------------------------------------------------------------------- */ -/* some Divco specific stuff */ -static int cx88_dvico_xc2028_callback(struct cx88_core *core, - int command, int arg) -{ - switch (command) { - case XC2028_TUNER_RESET: - switch (core->boardnr) { - case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: - /* GPIO-4 xc3028 tuner */ - - cx_set(MO_GP0_IO, 0x00001000); - cx_clear(MO_GP0_IO, 0x00000010); - msleep(100); - cx_set(MO_GP0_IO, 0x00000010); - msleep(100); - break; - default: - cx_write(MO_GP0_IO, 0x101000); - mdelay(5); - cx_set(MO_GP0_IO, 0x101010); - } - break; - default: - return -EINVAL; - } - - return 0; -} - - -/* ----------------------------------------------------------------------- */ -/* some Geniatech specific stuff */ - -static int cx88_xc3028_geniatech_tuner_callback(struct cx88_core *core, - int command, int mode) -{ - switch (command) { - case XC2028_TUNER_RESET: - switch (INPUT(core->input).type) { - case CX88_RADIO: - break; - case CX88_VMUX_DVB: - cx_write(MO_GP1_IO, 0x030302); - mdelay(50); - break; - default: - cx_write(MO_GP1_IO, 0x030301); - mdelay(50); - } - cx_write(MO_GP1_IO, 0x101010); - mdelay(50); - cx_write(MO_GP1_IO, 0x101000); - mdelay(50); - cx_write(MO_GP1_IO, 0x101010); - mdelay(50); - return 0; - } - return -EINVAL; -} - -static int cx88_xc3028_winfast1800h_callback(struct cx88_core *core, - int command, int arg) -{ - switch (command) { - case XC2028_TUNER_RESET: - /* GPIO 12 (xc3028 tuner reset) */ - cx_set(MO_GP1_IO, 0x1010); - mdelay(50); - cx_clear(MO_GP1_IO, 0x10); - mdelay(50); - cx_set(MO_GP1_IO, 0x10); - mdelay(50); - return 0; - } - return -EINVAL; -} - -static int cx88_xc4000_winfast2000h_plus_callback(struct cx88_core *core, - int command, int arg) -{ - switch (command) { - case XC4000_TUNER_RESET: - /* GPIO 12 (xc4000 tuner reset) */ - cx_set(MO_GP1_IO, 0x1010); - mdelay(50); - cx_clear(MO_GP1_IO, 0x10); - mdelay(75); - cx_set(MO_GP1_IO, 0x10); - mdelay(75); - return 0; - } - return -EINVAL; -} - -/* ------------------------------------------------------------------- */ -/* some Divco specific stuff */ -static int cx88_pv_8000gt_callback(struct cx88_core *core, - int command, int arg) -{ - switch (command) { - case XC2028_TUNER_RESET: - cx_write(MO_GP2_IO, 0xcf7); - mdelay(50); - cx_write(MO_GP2_IO, 0xef5); - mdelay(50); - cx_write(MO_GP2_IO, 0xcf7); - break; - default: - return -EINVAL; - } - - return 0; -} - -/* ----------------------------------------------------------------------- */ -/* some DViCO specific stuff */ - -static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core) -{ - struct i2c_msg msg = { .addr = 0x45, .flags = 0 }; - int i, err; - static u8 init_bufs[13][5] = { - { 0x10, 0x00, 0x20, 0x01, 0x03 }, - { 0x10, 0x10, 0x01, 0x00, 0x21 }, - { 0x10, 0x10, 0x10, 0x00, 0xCA }, - { 0x10, 0x10, 0x12, 0x00, 0x08 }, - { 0x10, 0x10, 0x13, 0x00, 0x0A }, - { 0x10, 0x10, 0x16, 0x01, 0xC0 }, - { 0x10, 0x10, 0x22, 0x01, 0x3D }, - { 0x10, 0x10, 0x73, 0x01, 0x2E }, - { 0x10, 0x10, 0x72, 0x00, 0xC5 }, - { 0x10, 0x10, 0x71, 0x01, 0x97 }, - { 0x10, 0x10, 0x70, 0x00, 0x0F }, - { 0x10, 0x10, 0xB0, 0x00, 0x01 }, - { 0x03, 0x0C }, - }; - - for (i = 0; i < ARRAY_SIZE(init_bufs); i++) { - msg.buf = init_bufs[i]; - msg.len = (i != 12 ? 5 : 2); - err = i2c_transfer(&core->i2c_adap, &msg, 1); - if (err != 1) { - warn_printk(core, "dvico_fusionhdtv_hybrid_init buf %d " - "failed (err = %d)!\n", i, err); - return; - } - } -} - -static int cx88_xc2028_tuner_callback(struct cx88_core *core, - int command, int arg) -{ - /* Board-specific callbacks */ - switch (core->boardnr) { - case CX88_BOARD_POWERCOLOR_REAL_ANGEL: - case CX88_BOARD_GENIATECH_X8000_MT: - case CX88_BOARD_KWORLD_ATSC_120: - return cx88_xc3028_geniatech_tuner_callback(core, - command, arg); - case CX88_BOARD_PROLINK_PV_8000GT: - case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: - return cx88_pv_8000gt_callback(core, command, arg); - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: - case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: - return cx88_dvico_xc2028_callback(core, command, arg); - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: - case CX88_BOARD_WINFAST_DTV1800H: - return cx88_xc3028_winfast1800h_callback(core, command, arg); - } - - switch (command) { - case XC2028_TUNER_RESET: - switch (INPUT(core->input).type) { - case CX88_RADIO: - info_printk(core, "setting GPIO to radio!\n"); - cx_write(MO_GP0_IO, 0x4ff); - mdelay(250); - cx_write(MO_GP2_IO, 0xff); - mdelay(250); - break; - case CX88_VMUX_DVB: /* Digital TV*/ - default: /* Analog TV */ - info_printk(core, "setting GPIO to TV!\n"); - break; - } - cx_write(MO_GP1_IO, 0x101010); - mdelay(250); - cx_write(MO_GP1_IO, 0x101000); - mdelay(250); - cx_write(MO_GP1_IO, 0x101010); - mdelay(250); - return 0; - } - return -EINVAL; -} - -static int cx88_xc4000_tuner_callback(struct cx88_core *core, - int command, int arg) -{ - /* Board-specific callbacks */ - switch (core->boardnr) { - case CX88_BOARD_WINFAST_DTV1800H_XC4000: - case CX88_BOARD_WINFAST_DTV2000H_PLUS: - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36: - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43: - return cx88_xc4000_winfast2000h_plus_callback(core, - command, arg); - } - return -EINVAL; -} - -/* ----------------------------------------------------------------------- */ -/* Tuner callback function. Currently only needed for the Pinnacle * - * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both * - * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c) */ - -static int cx88_xc5000_tuner_callback(struct cx88_core *core, - int command, int arg) -{ - switch (core->boardnr) { - case CX88_BOARD_PINNACLE_PCTV_HD_800i: - if (command == 0) { /* This is the reset command from xc5000 */ - - /* djh - According to the engineer at PCTV Systems, - the xc5000 reset pin is supposed to be on GPIO12. - However, despite three nights of effort, pulling - that GPIO low didn't reset the xc5000. While - pulling MO_SRST_IO low does reset the xc5000, this - also resets in the s5h1409 being reset as well. - This causes tuning to always fail since the internal - state of the s5h1409 does not match the driver's - state. Given that the only two conditions in which - the driver performs a reset is during firmware load - and powering down the chip, I am taking out the - reset. We know that the chip is being reset - when the cx88 comes online, and not being able to - do power management for this board is worse than - not having any tuning at all. */ - return 0; - } else { - err_printk(core, "xc5000: unknown tuner " - "callback command.\n"); - return -EINVAL; - } - break; - case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: - if (command == 0) { /* This is the reset command from xc5000 */ - cx_clear(MO_GP0_IO, 0x00000010); - msleep(10); - cx_set(MO_GP0_IO, 0x00000010); - return 0; - } else { - printk(KERN_ERR - "xc5000: unknown tuner callback command.\n"); - return -EINVAL; - } - break; - } - return 0; /* Should never be here */ -} - -int cx88_tuner_callback(void *priv, int component, int command, int arg) -{ - struct i2c_algo_bit_data *i2c_algo = priv; - struct cx88_core *core; - - if (!i2c_algo) { - printk(KERN_ERR "cx88: Error - i2c private data undefined.\n"); - return -EINVAL; - } - - core = i2c_algo->data; - - if (!core) { - printk(KERN_ERR "cx88: Error - device struct undefined.\n"); - return -EINVAL; - } - - if (component != DVB_FRONTEND_COMPONENT_TUNER) - return -EINVAL; - - switch (core->board.tuner_type) { - case TUNER_XC2028: - info_printk(core, "Calling XC2028/3028 callback\n"); - return cx88_xc2028_tuner_callback(core, command, arg); - case TUNER_XC4000: - info_printk(core, "Calling XC4000 callback\n"); - return cx88_xc4000_tuner_callback(core, command, arg); - case TUNER_XC5000: - info_printk(core, "Calling XC5000 callback\n"); - return cx88_xc5000_tuner_callback(core, command, arg); - } - err_printk(core, "Error: Calling callback for tuner %d\n", - core->board.tuner_type); - return -EINVAL; -} -EXPORT_SYMBOL(cx88_tuner_callback); - -/* ----------------------------------------------------------------------- */ - -static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci) -{ - int i; - - if (0 == pci->subsystem_vendor && - 0 == pci->subsystem_device) { - printk(KERN_ERR - "%s: Your board has no valid PCI Subsystem ID and thus can't\n" - "%s: be autodetected. Please pass card=<n> insmod option to\n" - "%s: workaround that. Redirect complaints to the vendor of\n" - "%s: the TV card. Best regards,\n" - "%s: -- tux\n", - core->name,core->name,core->name,core->name,core->name); - } else { - printk(KERN_ERR - "%s: Your board isn't known (yet) to the driver. You can\n" - "%s: try to pick one of the existing card configs via\n" - "%s: card=<n> insmod option. Updating to the latest\n" - "%s: version might help as well.\n", - core->name,core->name,core->name,core->name); - } - err_printk(core, "Here is a list of valid choices for the card=<n> " - "insmod option:\n"); - for (i = 0; i < ARRAY_SIZE(cx88_boards); i++) - printk(KERN_ERR "%s: card=%d -> %s\n", - core->name, i, cx88_boards[i].name); -} - -static void cx88_card_setup_pre_i2c(struct cx88_core *core) -{ - switch (core->boardnr) { - case CX88_BOARD_HAUPPAUGE_HVR1300: - /* - * Bring the 702 demod up before i2c scanning/attach or devices are hidden - * We leave here with the 702 on the bus - * - * "reset the IR receiver on GPIO[3]" - * Reported by Mike Crash <mike AT mikecrash.com> - */ - cx_write(MO_GP0_IO, 0x0000ef88); - udelay(1000); - cx_clear(MO_GP0_IO, 0x00000088); - udelay(50); - cx_set(MO_GP0_IO, 0x00000088); /* 702 out of reset */ - udelay(1000); - break; - - case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: - case CX88_BOARD_PROLINK_PV_8000GT: - cx_write(MO_GP2_IO, 0xcf7); - mdelay(50); - cx_write(MO_GP2_IO, 0xef5); - mdelay(50); - cx_write(MO_GP2_IO, 0xcf7); - msleep(10); - break; - - case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: - /* Enable the xc5000 tuner */ - cx_set(MO_GP0_IO, 0x00001010); - break; - - case CX88_BOARD_WINFAST_DTV2000H_J: - case CX88_BOARD_HAUPPAUGE_HVR3000: - case CX88_BOARD_HAUPPAUGE_HVR4000: - /* Init GPIO */ - cx_write(MO_GP0_IO, core->board.input[0].gpio0); - udelay(1000); - cx_clear(MO_GP0_IO, 0x00000080); - udelay(50); - cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */ - udelay(1000); - break; - - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: - case CX88_BOARD_WINFAST_DTV1800H: - cx88_xc3028_winfast1800h_callback(core, XC2028_TUNER_RESET, 0); - break; - - case CX88_BOARD_WINFAST_DTV1800H_XC4000: - case CX88_BOARD_WINFAST_DTV2000H_PLUS: - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36: - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43: - cx88_xc4000_winfast2000h_plus_callback(core, - XC4000_TUNER_RESET, 0); - break; - - case CX88_BOARD_TWINHAN_VP1027_DVBS: - cx_write(MO_GP0_IO, 0x00003230); - cx_write(MO_GP0_IO, 0x00003210); - msleep(1); - cx_write(MO_GP0_IO, 0x00001230); - break; - } -} - -/* - * Sets board-dependent xc3028 configuration - */ -void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) -{ - memset(ctl, 0, sizeof(*ctl)); - - ctl->fname = XC2028_DEFAULT_FIRMWARE; - ctl->max_len = 64; - - switch (core->boardnr) { - case CX88_BOARD_POWERCOLOR_REAL_ANGEL: - /* Now works with firmware version 2.7 */ - if (core->i2c_algo.udelay < 16) - core->i2c_algo.udelay = 16; - break; - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: - case CX88_BOARD_WINFAST_DTV1800H: - ctl->demod = XC3028_FE_ZARLINK456; - break; - case CX88_BOARD_KWORLD_ATSC_120: - case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: - ctl->demod = XC3028_FE_OREN538; - break; - case CX88_BOARD_GENIATECH_X8000_MT: - /* FIXME: For this board, the xc3028 never recovers after being - powered down (the reset GPIO probably is not set properly). - We don't have access to the hardware so we cannot determine - which GPIO is used for xc3028, so just disable power xc3028 - power management for now */ - ctl->disable_power_mgmt = 1; - break; - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: - case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: - case CX88_BOARD_PROLINK_PV_8000GT: - /* - * Those boards uses non-MTS firmware - */ - break; - case CX88_BOARD_PINNACLE_HYBRID_PCTV: - case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII: - ctl->demod = XC3028_FE_ZARLINK456; - ctl->mts = 1; - break; - default: - ctl->demod = XC3028_FE_OREN538; - ctl->mts = 1; - } -} -EXPORT_SYMBOL_GPL(cx88_setup_xc3028); - -static void cx88_card_setup(struct cx88_core *core) -{ - static u8 eeprom[256]; - struct tuner_setup tun_setup; - unsigned int mode_mask = T_RADIO | T_ANALOG_TV; - - memset(&tun_setup, 0, sizeof(tun_setup)); - - if (0 == core->i2c_rc) { - core->i2c_client.addr = 0xa0 >> 1; - tveeprom_read(&core->i2c_client, eeprom, sizeof(eeprom)); - } - - switch (core->boardnr) { - case CX88_BOARD_HAUPPAUGE: - case CX88_BOARD_HAUPPAUGE_ROSLYN: - if (0 == core->i2c_rc) - hauppauge_eeprom(core, eeprom+8); - break; - case CX88_BOARD_GDI: - if (0 == core->i2c_rc) - gdi_eeprom(core, eeprom); - break; - case CX88_BOARD_LEADTEK_PVR2000: - case CX88_BOARD_WINFAST_DV2000: - case CX88_BOARD_WINFAST2000XP_EXPERT: - if (0 == core->i2c_rc) - leadtek_eeprom(core, eeprom); - break; - case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: - case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: - case CX88_BOARD_HAUPPAUGE_DVB_T1: - case CX88_BOARD_HAUPPAUGE_HVR1100: - case CX88_BOARD_HAUPPAUGE_HVR1100LP: - case CX88_BOARD_HAUPPAUGE_HVR3000: - case CX88_BOARD_HAUPPAUGE_HVR1300: - case CX88_BOARD_HAUPPAUGE_HVR4000: - case CX88_BOARD_HAUPPAUGE_HVR4000LITE: - case CX88_BOARD_HAUPPAUGE_IRONLY: - if (0 == core->i2c_rc) - hauppauge_eeprom(core, eeprom); - break; - case CX88_BOARD_KWORLD_DVBS_100: - cx_write(MO_GP0_IO, 0x000007f8); - cx_write(MO_GP1_IO, 0x00000001); - break; - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: - /* GPIO0:0 is hooked to demod reset */ - /* GPIO0:4 is hooked to xc3028 reset */ - cx_write(MO_GP0_IO, 0x00111100); - msleep(1); - cx_write(MO_GP0_IO, 0x00111111); - break; - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: - /* GPIO0:6 is hooked to FX2 reset pin */ - cx_set(MO_GP0_IO, 0x00004040); - cx_clear(MO_GP0_IO, 0x00000040); - msleep(1000); - cx_set(MO_GP0_IO, 0x00004040); - /* FALLTHROUGH */ - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: - /* GPIO0:0 is hooked to mt352 reset pin */ - cx_set(MO_GP0_IO, 0x00000101); - cx_clear(MO_GP0_IO, 0x00000001); - msleep(1); - cx_set(MO_GP0_IO, 0x00000101); - if (0 == core->i2c_rc && - core->boardnr == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID) - dvico_fusionhdtv_hybrid_init(core); - break; - case CX88_BOARD_KWORLD_DVB_T: - case CX88_BOARD_DNTV_LIVE_DVB_T: - cx_set(MO_GP0_IO, 0x00000707); - cx_set(MO_GP2_IO, 0x00000101); - cx_clear(MO_GP2_IO, 0x00000001); - msleep(1); - cx_clear(MO_GP0_IO, 0x00000007); - cx_set(MO_GP2_IO, 0x00000101); - break; - case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: - cx_write(MO_GP0_IO, 0x00080808); - break; - case CX88_BOARD_ATI_HDTVWONDER: - if (0 == core->i2c_rc) { - /* enable tuner */ - int i; - static const u8 buffer [][2] = { - {0x10,0x12}, - {0x13,0x04}, - {0x16,0x00}, - {0x14,0x04}, - {0x17,0x00} - }; - core->i2c_client.addr = 0x0a; - - for (i = 0; i < ARRAY_SIZE(buffer); i++) - if (2 != i2c_master_send(&core->i2c_client, - buffer[i],2)) - warn_printk(core, "Unable to enable " - "tuner(%i).\n", i); - } - break; - case CX88_BOARD_MSI_TVANYWHERE_MASTER: - { - struct v4l2_priv_tun_config tea5767_cfg; - struct tea5767_ctrl ctl; - - memset(&ctl, 0, sizeof(ctl)); - - ctl.high_cut = 1; - ctl.st_noise = 1; - ctl.deemph_75 = 1; - ctl.xtal_freq = TEA5767_HIGH_LO_13MHz; - - tea5767_cfg.tuner = TUNER_TEA5767; - tea5767_cfg.priv = &ctl; - - call_all(core, tuner, s_config, &tea5767_cfg); - break; - } - case CX88_BOARD_TEVII_S420: - case CX88_BOARD_TEVII_S460: - case CX88_BOARD_TEVII_S464: - case CX88_BOARD_OMICOM_SS4_PCI: - case CX88_BOARD_TBS_8910: - case CX88_BOARD_TBS_8920: - case CX88_BOARD_PROF_6200: - case CX88_BOARD_PROF_7300: - case CX88_BOARD_PROF_7301: - case CX88_BOARD_SATTRADE_ST4200: - cx_write(MO_GP0_IO, 0x8000); - msleep(100); - cx_write(MO_SRST_IO, 0); - msleep(10); - cx_write(MO_GP0_IO, 0x8080); - msleep(100); - cx_write(MO_SRST_IO, 1); - msleep(100); - break; - } /*end switch() */ - - - /* Setup tuners */ - if ((core->board.radio_type != UNSET)) { - tun_setup.mode_mask = T_RADIO; - tun_setup.type = core->board.radio_type; - tun_setup.addr = core->board.radio_addr; - tun_setup.tuner_callback = cx88_tuner_callback; - call_all(core, tuner, s_type_addr, &tun_setup); - mode_mask &= ~T_RADIO; - } - - if (core->board.tuner_type != TUNER_ABSENT) { - tun_setup.mode_mask = mode_mask; - tun_setup.type = core->board.tuner_type; - tun_setup.addr = core->board.tuner_addr; - tun_setup.tuner_callback = cx88_tuner_callback; - - call_all(core, tuner, s_type_addr, &tun_setup); - } - - if (core->board.tda9887_conf) { - struct v4l2_priv_tun_config tda9887_cfg; - - tda9887_cfg.tuner = TUNER_TDA9887; - tda9887_cfg.priv = &core->board.tda9887_conf; - - call_all(core, tuner, s_config, &tda9887_cfg); - } - - if (core->board.tuner_type == TUNER_XC2028) { - struct v4l2_priv_tun_config xc2028_cfg; - struct xc2028_ctrl ctl; - - /* Fills device-dependent initialization parameters */ - cx88_setup_xc3028(core, &ctl); - - /* Sends parameters to xc2028/3028 tuner */ - memset(&xc2028_cfg, 0, sizeof(xc2028_cfg)); - xc2028_cfg.tuner = TUNER_XC2028; - xc2028_cfg.priv = &ctl; - info_printk(core, "Asking xc2028/3028 to load firmware %s\n", - ctl.fname); - call_all(core, tuner, s_config, &xc2028_cfg); - } - call_all(core, core, s_power, 0); -} - -/* ------------------------------------------------------------------ */ - -static int cx88_pci_quirks(const char *name, struct pci_dev *pci) -{ - unsigned int lat = UNSET; - u8 ctrl = 0; - u8 value; - - /* check pci quirks */ - if (pci_pci_problems & PCIPCI_TRITON) { - printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n", - name); - ctrl |= CX88X_EN_TBFX; - } - if (pci_pci_problems & PCIPCI_NATOMA) { - printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n", - name); - ctrl |= CX88X_EN_TBFX; - } - if (pci_pci_problems & PCIPCI_VIAETBF) { - printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n", - name); - ctrl |= CX88X_EN_TBFX; - } - if (pci_pci_problems & PCIPCI_VSFX) { - printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n", - name); - ctrl |= CX88X_EN_VSFX; - } -#ifdef PCIPCI_ALIMAGIK - if (pci_pci_problems & PCIPCI_ALIMAGIK) { - printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n", - name); - lat = 0x0A; - } -#endif - - /* check insmod options */ - if (UNSET != latency) - lat = latency; - - /* apply stuff */ - if (ctrl) { - pci_read_config_byte(pci, CX88X_DEVCTRL, &value); - value |= ctrl; - pci_write_config_byte(pci, CX88X_DEVCTRL, value); - } - if (UNSET != lat) { - printk(KERN_INFO "%s: setting pci latency timer to %d\n", - name, latency); - pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency); - } - return 0; -} - -int cx88_get_resources(const struct cx88_core *core, struct pci_dev *pci) -{ - if (request_mem_region(pci_resource_start(pci,0), - pci_resource_len(pci,0), - core->name)) - return 0; - printk(KERN_ERR - "%s/%d: Can't get MMIO memory @ 0x%llx, subsystem: %04x:%04x\n", - core->name, PCI_FUNC(pci->devfn), - (unsigned long long)pci_resource_start(pci, 0), - pci->subsystem_vendor, pci->subsystem_device); - return -EBUSY; -} - -/* Allocate and initialize the cx88 core struct. One should hold the - * devlist mutex before calling this. */ -struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) -{ - struct cx88_core *core; - int i; - - core = kzalloc(sizeof(*core), GFP_KERNEL); - if (core == NULL) - return NULL; - - atomic_inc(&core->refcount); - core->pci_bus = pci->bus->number; - core->pci_slot = PCI_SLOT(pci->devfn); - core->pci_irqmask = PCI_INT_RISC_RD_BERRINT | PCI_INT_RISC_WR_BERRINT | - PCI_INT_BRDG_BERRINT | PCI_INT_SRC_DMA_BERRINT | - PCI_INT_DST_DMA_BERRINT | PCI_INT_IPB_DMA_BERRINT; - mutex_init(&core->lock); - - core->nr = nr; - sprintf(core->name, "cx88[%d]", core->nr); - - strcpy(core->v4l2_dev.name, core->name); - if (v4l2_device_register(NULL, &core->v4l2_dev)) { - kfree(core); - return NULL; - } - - if (v4l2_ctrl_handler_init(&core->video_hdl, 13)) { - v4l2_device_unregister(&core->v4l2_dev); - kfree(core); - return NULL; - } - - if (v4l2_ctrl_handler_init(&core->audio_hdl, 13)) { - v4l2_ctrl_handler_free(&core->video_hdl); - v4l2_device_unregister(&core->v4l2_dev); - kfree(core); - return NULL; - } - - if (0 != cx88_get_resources(core, pci)) { - v4l2_ctrl_handler_free(&core->video_hdl); - v4l2_ctrl_handler_free(&core->audio_hdl); - v4l2_device_unregister(&core->v4l2_dev); - kfree(core); - return NULL; - } - - /* PCI stuff */ - cx88_pci_quirks(core->name, pci); - core->lmmio = ioremap(pci_resource_start(pci, 0), - pci_resource_len(pci, 0)); - core->bmmio = (u8 __iomem *)core->lmmio; - - if (core->lmmio == NULL) { - release_mem_region(pci_resource_start(pci, 0), - pci_resource_len(pci, 0)); - v4l2_ctrl_handler_free(&core->video_hdl); - v4l2_ctrl_handler_free(&core->audio_hdl); - v4l2_device_unregister(&core->v4l2_dev); - kfree(core); - return NULL; - } - - /* board config */ - core->boardnr = UNSET; - if (card[core->nr] < ARRAY_SIZE(cx88_boards)) - core->boardnr = card[core->nr]; - for (i = 0; UNSET == core->boardnr && i < ARRAY_SIZE(cx88_subids); i++) - if (pci->subsystem_vendor == cx88_subids[i].subvendor && - pci->subsystem_device == cx88_subids[i].subdevice) - core->boardnr = cx88_subids[i].card; - if (UNSET == core->boardnr) { - core->boardnr = CX88_BOARD_UNKNOWN; - cx88_card_list(core, pci); - } - - memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board)); - - if (!core->board.num_frontends && (core->board.mpeg & CX88_MPEG_DVB)) - core->board.num_frontends = 1; - - info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s], frontend(s): %d\n", - pci->subsystem_vendor, pci->subsystem_device, core->board.name, - core->boardnr, card[core->nr] == core->boardnr ? - "insmod option" : "autodetected", - core->board.num_frontends); - - if (tuner[core->nr] != UNSET) - core->board.tuner_type = tuner[core->nr]; - if (radio[core->nr] != UNSET) - core->board.radio_type = radio[core->nr]; - - info_printk(core, "TV tuner type %d, Radio tuner type %d\n", - core->board.tuner_type, core->board.radio_type); - - /* init hardware */ - cx88_reset(core); - cx88_card_setup_pre_i2c(core); - cx88_i2c_init(core, pci); - - /* load tuner module, if needed */ - if (TUNER_ABSENT != core->board.tuner_type) { - /* Ignore 0x6b and 0x6f on cx88 boards. - * FusionHDTV5 RT Gold has an ir receiver at 0x6b - * and an RTC at 0x6f which can get corrupted if probed. */ - static const unsigned short tv_addrs[] = { - 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6c, 0x6d, 0x6e, - I2C_CLIENT_END - }; - int has_demod = (core->board.tda9887_conf & TDA9887_PRESENT); - - /* I don't trust the radio_type as is stored in the card - definitions, so we just probe for it. - The radio_type is sometimes missing, or set to UNSET but - later code configures a tea5767. - */ - v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO)); - if (has_demod) - v4l2_i2c_new_subdev(&core->v4l2_dev, - &core->i2c_adap, "tuner", - 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD)); - if (core->board.tuner_addr == ADDR_UNSET) { - v4l2_i2c_new_subdev(&core->v4l2_dev, - &core->i2c_adap, "tuner", - 0, has_demod ? tv_addrs + 4 : tv_addrs); - } else { - v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - "tuner", core->board.tuner_addr, NULL); - } - } - - cx88_card_setup(core); - if (!disable_ir) { - cx88_i2c_init_ir(core); - cx88_ir_init(core, pci); - } - - return core; -} diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c deleted file mode 100644 index c97b174be3ab..000000000000 --- a/drivers/media/video/cx88/cx88-core.c +++ /dev/null @@ -1,1131 +0,0 @@ -/* - * - * device driver for Conexant 2388x based TV cards - * driver core - * - * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] - * - * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org> - * - Multituner support - * - video_ioctl2 conversion - * - PAL/M fixes - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/init.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/kmod.h> -#include <linux/sound.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/videodev2.h> -#include <linux/mutex.h> - -#include "cx88.h" -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> - -MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); -MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); -MODULE_LICENSE("GPL"); - -/* ------------------------------------------------------------------ */ - -static unsigned int core_debug; -module_param(core_debug,int,0644); -MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); - -static unsigned int nicam; -module_param(nicam,int,0644); -MODULE_PARM_DESC(nicam,"tv audio is nicam"); - -static unsigned int nocomb; -module_param(nocomb,int,0644); -MODULE_PARM_DESC(nocomb,"disable comb filter"); - -#define dprintk(level,fmt, arg...) if (core_debug >= level) \ - printk(KERN_DEBUG "%s: " fmt, core->name , ## arg) - -static unsigned int cx88_devcount; -static LIST_HEAD(cx88_devlist); -static DEFINE_MUTEX(devlist); - -#define NO_SYNC_LINE (-1U) - -/* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be - generated _after_ lpi lines are transferred. */ -static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist, - unsigned int offset, u32 sync_line, - unsigned int bpl, unsigned int padding, - unsigned int lines, unsigned int lpi) -{ - struct scatterlist *sg; - unsigned int line,todo,sol; - - /* sync instruction */ - if (sync_line != NO_SYNC_LINE) - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); - - /* scan lines */ - sg = sglist; - for (line = 0; line < lines; line++) { - while (offset && offset >= sg_dma_len(sg)) { - offset -= sg_dma_len(sg); - sg++; - } - if (lpi && line>0 && !(line % lpi)) - sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC; - else - sol = RISC_SOL; - if (bpl <= sg_dma_len(sg)-offset) { - /* fits into current chunk */ - *(rp++)=cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - 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); - todo -= (sg_dma_len(sg)-offset); - offset = 0; - sg++; - while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(RISC_WRITE| - sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); - todo -= sg_dma_len(sg); - sg++; - } - *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); - offset += todo; - } - offset += padding; - } - - return rp; -} - -int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, - struct scatterlist *sglist, - unsigned int top_offset, unsigned int bottom_offset, - unsigned int bpl, unsigned int padding, unsigned int lines) -{ - u32 instructions,fields; - __le32 *rp; - int rc; - - fields = 0; - if (UNSET != top_offset) - fields++; - if (UNSET != bottom_offset) - fields++; - - /* estimate risc mem: worst case is one write per page border + - one write per scan line + syncs + jump (all 2 dwords). Padding - can cause next bpl to start close to a page border. First DMA - region may be smaller than PAGE_SIZE */ - instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); - instructions += 2; - if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0) - return rc; - - /* write risc instructions */ - rp = risc->cpu; - if (UNSET != top_offset) - rp = cx88_risc_field(rp, sglist, top_offset, 0, - bpl, padding, lines, 0); - if (UNSET != bottom_offset) - rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200, - bpl, padding, lines, 0); - - /* save pointer to jmp instruction address */ - risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size); - return 0; -} - -int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, - struct scatterlist *sglist, unsigned int bpl, - unsigned int lines, unsigned int lpi) -{ - u32 instructions; - __le32 *rp; - int rc; - - /* estimate risc mem: worst case is one write per page border + - one write per scan line + syncs + jump (all 2 dwords). Here - there is no padding and no sync. First DMA region may be smaller - than PAGE_SIZE */ - instructions = 1 + (bpl * lines) / PAGE_SIZE + lines; - instructions += 1; - if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0) - return rc; - - /* write risc instructions */ - rp = risc->cpu; - rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi); - - /* save pointer to jmp instruction address */ - risc->jmp = rp; - BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size); - return 0; -} - -int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, - u32 reg, u32 mask, u32 value) -{ - __le32 *rp; - int rc; - - if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0) - return rc; - - /* write risc instructions */ - rp = risc->cpu; - *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ2 | RISC_IMM); - *(rp++) = cpu_to_le32(reg); - *(rp++) = cpu_to_le32(value); - *(rp++) = cpu_to_le32(mask); - *(rp++) = cpu_to_le32(RISC_JUMP); - *(rp++) = cpu_to_le32(risc->dma); - return 0; -} - -void -cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf) -{ - struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); - - BUG_ON(in_interrupt()); - videobuf_waiton(q, &buf->vb, 0, 0); - videobuf_dma_unmap(q->dev, dma); - videobuf_dma_free(dma); - btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); - buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -/* ------------------------------------------------------------------ */ -/* our SRAM memory layout */ - -/* we are going to put all thr risc programs into host memory, so we - * can use the whole SDRAM for the DMA fifos. To simplify things, we - * use a static memory layout. That surely will waste memory in case - * we don't use all DMA channels at the same time (which will be the - * case most of the time). But that still gives us enough FIFO space - * to be able to deal with insane long pci latencies ... - * - * FIFO space allocations: - * channel 21 (y video) - 10.0k - * channel 22 (u video) - 2.0k - * channel 23 (v video) - 2.0k - * channel 24 (vbi) - 4.0k - * channels 25+26 (audio) - 4.0k - * channel 28 (mpeg) - 4.0k - * channel 27 (audio rds)- 3.0k - * TOTAL = 29.0k - * - * Every channel has 160 bytes control data (64 bytes instruction - * queue and 6 CDT entries), which is close to 2k total. - * - * Address layout: - * 0x0000 - 0x03ff CMDs / reserved - * 0x0400 - 0x0bff instruction queues + CDs - * 0x0c00 - FIFOs - */ - -const struct sram_channel cx88_sram_channels[] = { - [SRAM_CH21] = { - .name = "video y / packed", - .cmds_start = 0x180040, - .ctrl_start = 0x180400, - .cdt = 0x180400 + 64, - .fifo_start = 0x180c00, - .fifo_size = 0x002800, - .ptr1_reg = MO_DMA21_PTR1, - .ptr2_reg = MO_DMA21_PTR2, - .cnt1_reg = MO_DMA21_CNT1, - .cnt2_reg = MO_DMA21_CNT2, - }, - [SRAM_CH22] = { - .name = "video u", - .cmds_start = 0x180080, - .ctrl_start = 0x1804a0, - .cdt = 0x1804a0 + 64, - .fifo_start = 0x183400, - .fifo_size = 0x000800, - .ptr1_reg = MO_DMA22_PTR1, - .ptr2_reg = MO_DMA22_PTR2, - .cnt1_reg = MO_DMA22_CNT1, - .cnt2_reg = MO_DMA22_CNT2, - }, - [SRAM_CH23] = { - .name = "video v", - .cmds_start = 0x1800c0, - .ctrl_start = 0x180540, - .cdt = 0x180540 + 64, - .fifo_start = 0x183c00, - .fifo_size = 0x000800, - .ptr1_reg = MO_DMA23_PTR1, - .ptr2_reg = MO_DMA23_PTR2, - .cnt1_reg = MO_DMA23_CNT1, - .cnt2_reg = MO_DMA23_CNT2, - }, - [SRAM_CH24] = { - .name = "vbi", - .cmds_start = 0x180100, - .ctrl_start = 0x1805e0, - .cdt = 0x1805e0 + 64, - .fifo_start = 0x184400, - .fifo_size = 0x001000, - .ptr1_reg = MO_DMA24_PTR1, - .ptr2_reg = MO_DMA24_PTR2, - .cnt1_reg = MO_DMA24_CNT1, - .cnt2_reg = MO_DMA24_CNT2, - }, - [SRAM_CH25] = { - .name = "audio from", - .cmds_start = 0x180140, - .ctrl_start = 0x180680, - .cdt = 0x180680 + 64, - .fifo_start = 0x185400, - .fifo_size = 0x001000, - .ptr1_reg = MO_DMA25_PTR1, - .ptr2_reg = MO_DMA25_PTR2, - .cnt1_reg = MO_DMA25_CNT1, - .cnt2_reg = MO_DMA25_CNT2, - }, - [SRAM_CH26] = { - .name = "audio to", - .cmds_start = 0x180180, - .ctrl_start = 0x180720, - .cdt = 0x180680 + 64, /* same as audio IN */ - .fifo_start = 0x185400, /* same as audio IN */ - .fifo_size = 0x001000, /* same as audio IN */ - .ptr1_reg = MO_DMA26_PTR1, - .ptr2_reg = MO_DMA26_PTR2, - .cnt1_reg = MO_DMA26_CNT1, - .cnt2_reg = MO_DMA26_CNT2, - }, - [SRAM_CH28] = { - .name = "mpeg", - .cmds_start = 0x180200, - .ctrl_start = 0x1807C0, - .cdt = 0x1807C0 + 64, - .fifo_start = 0x186400, - .fifo_size = 0x001000, - .ptr1_reg = MO_DMA28_PTR1, - .ptr2_reg = MO_DMA28_PTR2, - .cnt1_reg = MO_DMA28_CNT1, - .cnt2_reg = MO_DMA28_CNT2, - }, - [SRAM_CH27] = { - .name = "audio rds", - .cmds_start = 0x1801C0, - .ctrl_start = 0x180860, - .cdt = 0x180860 + 64, - .fifo_start = 0x187400, - .fifo_size = 0x000C00, - .ptr1_reg = MO_DMA27_PTR1, - .ptr2_reg = MO_DMA27_PTR2, - .cnt1_reg = MO_DMA27_CNT1, - .cnt2_reg = MO_DMA27_CNT2, - }, -}; - -int cx88_sram_channel_setup(struct cx88_core *core, - const struct sram_channel *ch, - unsigned int bpl, u32 risc) -{ - unsigned int i,lines; - u32 cdt; - - bpl = (bpl + 7) & ~7; /* alignment */ - cdt = ch->cdt; - lines = ch->fifo_size / bpl; - if (lines > 6) - lines = 6; - BUG_ON(lines < 2); - - /* write CDT */ - for (i = 0; i < lines; i++) - cx_write(cdt + 16*i, ch->fifo_start + bpl*i); - - /* write CMDS */ - cx_write(ch->cmds_start + 0, risc); - cx_write(ch->cmds_start + 4, cdt); - cx_write(ch->cmds_start + 8, (lines*16) >> 3); - cx_write(ch->cmds_start + 12, ch->ctrl_start); - cx_write(ch->cmds_start + 16, 64 >> 2); - for (i = 20; i < 64; 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->cnt1_reg, (bpl >> 3) -1); - cx_write(ch->cnt2_reg, (lines*16) >> 3); - - dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines); - return 0; -} - -/* ------------------------------------------------------------------ */ -/* debug helper code */ - -static int cx88_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 int const incr[16] = { - [ RISC_WRITE >> 28 ] = 2, - [ RISC_JUMP >> 28 ] = 2, - [ 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; - - printk("0x%08x [ %s", risc, - instr[risc >> 28] ? instr[risc >> 28] : "INVALID"); - for (i = ARRAY_SIZE(bits)-1; i >= 0; i--) - if (risc & (1 << (i + 12))) - printk(" %s",bits[i]); - printk(" count=%d ]\n", risc & 0xfff); - return incr[risc >> 28] ? incr[risc >> 28] : 1; -} - - -void cx88_sram_channel_dump(struct cx88_core *core, - const struct sram_channel *ch) -{ - static const char * const name[] = { - "initial risc", - "cdt base", - "cdt size", - "iq base", - "iq size", - "risc pc", - "iq wr ptr", - "iq rd ptr", - "cdt current", - "pci target", - "line / byte", - }; - u32 risc; - unsigned int i,j,n; - - printk("%s: %s - dma channel status dump\n", - core->name,ch->name); - for (i = 0; i < ARRAY_SIZE(name); i++) - printk("%s: cmds: %-12s: 0x%08x\n", - core->name,name[i], - cx_read(ch->cmds_start + 4*i)); - for (n = 1, i = 0; i < 4; i++) { - risc = cx_read(ch->cmds_start + 4 * (i+11)); - printk("%s: risc%d: ", core->name, i); - if (--n) - printk("0x%08x [ arg #%d ]\n", risc, n); - else - n = cx88_risc_decode(risc); - } - for (i = 0; i < 16; i += n) { - risc = cx_read(ch->ctrl_start + 4 * i); - printk("%s: iq %x: ", core->name, i); - n = cx88_risc_decode(risc); - for (j = 1; j < n; j++) { - risc = cx_read(ch->ctrl_start + 4 * (i+j)); - printk("%s: iq %x: 0x%08x [ arg #%d ]\n", - core->name, i+j, risc, j); - } - } - - printk("%s: fifo: 0x%08x -> 0x%x\n", - core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size); - printk("%s: ctrl: 0x%08x -> 0x%x\n", - core->name, ch->ctrl_start, ch->ctrl_start+6*16); - printk("%s: ptr1_reg: 0x%08x\n", - core->name,cx_read(ch->ptr1_reg)); - printk("%s: ptr2_reg: 0x%08x\n", - core->name,cx_read(ch->ptr2_reg)); - printk("%s: cnt1_reg: 0x%08x\n", - core->name,cx_read(ch->cnt1_reg)); - printk("%s: cnt2_reg: 0x%08x\n", - core->name,cx_read(ch->cnt2_reg)); -} - -static const char *cx88_pci_irqs[32] = { - "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1", - "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err", - "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err", - "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1" -}; - -void cx88_print_irqbits(const char *name, const char *tag, const char *strings[], - int len, u32 bits, u32 mask) -{ - unsigned int i; - - printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits); - for (i = 0; i < len; i++) { - if (!(bits & (1 << i))) - continue; - if (strings[i]) - printk(" %s", strings[i]); - else - printk(" %d", i); - if (!(mask & (1 << i))) - continue; - printk("*"); - } - printk("\n"); -} - -/* ------------------------------------------------------------------ */ - -int cx88_core_irq(struct cx88_core *core, u32 status) -{ - int handled = 0; - - if (status & PCI_INT_IR_SMPINT) { - cx88_ir_irq(core); - handled++; - } - if (!handled) - cx88_print_irqbits(core->name, "irq pci", - cx88_pci_irqs, ARRAY_SIZE(cx88_pci_irqs), - status, core->pci_irqmask); - return handled; -} - -void cx88_wakeup(struct cx88_core *core, - struct cx88_dmaqueue *q, u32 count) -{ - struct cx88_buffer *buf; - int bc; - - for (bc = 0;; bc++) { - if (list_empty(&q->active)) - break; - buf = list_entry(q->active.next, - struct cx88_buffer, vb.queue); - /* count comes from the hw and is is 16bit wide -- - * this trick handles wrap-arounds correctly for - * up to 32767 buffers in flight... */ - if ((s16) (count - buf->count) < 0) - break; - do_gettimeofday(&buf->vb.ts); - dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i, - count, buf->count); - buf->vb.state = VIDEOBUF_DONE; - list_del(&buf->vb.queue); - wake_up(&buf->vb.done); - } - if (list_empty(&q->active)) { - del_timer(&q->timeout); - } else { - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - } - if (bc != 1) - dprintk(2, "%s: %d buffers handled (should be 1)\n", - __func__, bc); -} - -void cx88_shutdown(struct cx88_core *core) -{ - /* disable RISC controller + IRQs */ - cx_write(MO_DEV_CNTRL2, 0); - - /* stop dma transfers */ - cx_write(MO_VID_DMACNTRL, 0x0); - cx_write(MO_AUD_DMACNTRL, 0x0); - cx_write(MO_TS_DMACNTRL, 0x0); - cx_write(MO_VIP_DMACNTRL, 0x0); - cx_write(MO_GPHST_DMACNTRL, 0x0); - - /* stop interrupts */ - cx_write(MO_PCI_INTMSK, 0x0); - cx_write(MO_VID_INTMSK, 0x0); - cx_write(MO_AUD_INTMSK, 0x0); - cx_write(MO_TS_INTMSK, 0x0); - cx_write(MO_VIP_INTMSK, 0x0); - cx_write(MO_GPHST_INTMSK, 0x0); - - /* stop capturing */ - cx_write(VID_CAPTURE_CONTROL, 0); -} - -int cx88_reset(struct cx88_core *core) -{ - dprintk(1,"%s\n",__func__); - cx88_shutdown(core); - - /* clear irq status */ - cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int - cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int - cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int - - /* wait a bit */ - msleep(100); - - /* init sram */ - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0); - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0); - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0); - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0); - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0); - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0); - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0); - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], 128, 0); - - /* misc init ... */ - cx_write(MO_INPUT_FORMAT, ((1 << 13) | // agc enable - (1 << 12) | // agc gain - (1 << 11) | // adaptibe agc - (0 << 10) | // chroma agc - (0 << 9) | // ckillen - (7))); - - /* setup image format */ - cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000); - - /* setup FIFO Thresholds */ - cx_write(MO_PDMA_STHRSH, 0x0807); - cx_write(MO_PDMA_DTHRSH, 0x0807); - - /* fixes flashing of image */ - cx_write(MO_AGC_SYNC_TIP1, 0x0380000F); - cx_write(MO_AGC_BACK_VBI, 0x00E00555); - - cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int - cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int - cx_write(MO_INT1_STAT, 0xFFFFFFFF); // Clear RISC int - - /* Reset on-board parts */ - cx_write(MO_SRST_IO, 0); - msleep(10); - cx_write(MO_SRST_IO, 1); - - return 0; -} - -/* ------------------------------------------------------------------ */ - -static unsigned int inline norm_swidth(v4l2_std_id norm) -{ - return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922; -} - -static unsigned int inline norm_hdelay(v4l2_std_id norm) -{ - return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186; -} - -static unsigned int inline norm_vdelay(v4l2_std_id norm) -{ - return (norm & V4L2_STD_625_50) ? 0x24 : 0x18; -} - -static unsigned int inline norm_fsc8(v4l2_std_id norm) -{ - if (norm & V4L2_STD_PAL_M) - return 28604892; // 3.575611 MHz - - if (norm & (V4L2_STD_PAL_Nc)) - return 28656448; // 3.582056 MHz - - if (norm & V4L2_STD_NTSC) // All NTSC/M and variants - return 28636360; // 3.57954545 MHz +/- 10 Hz - - /* SECAM have also different sub carrier for chroma, - but step_db and step_dr, at cx88_set_tvnorm already handles that. - - The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N - */ - - return 35468950; // 4.43361875 MHz +/- 5 Hz -} - -static unsigned int inline norm_htotal(v4l2_std_id norm) -{ - - unsigned int fsc4=norm_fsc8(norm)/2; - - /* returns 4*FSC / vtotal / frames per seconds */ - return (norm & V4L2_STD_625_50) ? - ((fsc4+312)/625+12)/25 : - ((fsc4+262)/525*1001+15000)/30000; -} - -static unsigned int inline norm_vbipack(v4l2_std_id norm) -{ - return (norm & V4L2_STD_625_50) ? 511 : 400; -} - -int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height, - enum v4l2_field field) -{ - unsigned int swidth = norm_swidth(core->tvnorm); - unsigned int sheight = norm_maxh(core->tvnorm); - u32 value; - - dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height, - V4L2_FIELD_HAS_TOP(field) ? "T" : "", - V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "", - v4l2_norm_to_name(core->tvnorm)); - if (!V4L2_FIELD_HAS_BOTH(field)) - height *= 2; - - // recalc H delay and scale registers - value = (width * norm_hdelay(core->tvnorm)) / swidth; - value &= 0x3fe; - cx_write(MO_HDELAY_EVEN, value); - cx_write(MO_HDELAY_ODD, value); - dprintk(1,"set_scale: hdelay 0x%04x (width %d)\n", value,swidth); - - value = (swidth * 4096 / width) - 4096; - cx_write(MO_HSCALE_EVEN, value); - cx_write(MO_HSCALE_ODD, value); - dprintk(1,"set_scale: hscale 0x%04x\n", value); - - cx_write(MO_HACTIVE_EVEN, width); - cx_write(MO_HACTIVE_ODD, width); - dprintk(1,"set_scale: hactive 0x%04x\n", width); - - // recalc V scale Register (delay is constant) - cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm)); - cx_write(MO_VDELAY_ODD, norm_vdelay(core->tvnorm)); - dprintk(1,"set_scale: vdelay 0x%04x\n", norm_vdelay(core->tvnorm)); - - value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff; - cx_write(MO_VSCALE_EVEN, value); - cx_write(MO_VSCALE_ODD, value); - dprintk(1,"set_scale: vscale 0x%04x\n", value); - - cx_write(MO_VACTIVE_EVEN, sheight); - cx_write(MO_VACTIVE_ODD, sheight); - dprintk(1,"set_scale: vactive 0x%04x\n", sheight); - - // setup filters - value = 0; - value |= (1 << 19); // CFILT (default) - if (core->tvnorm & V4L2_STD_SECAM) { - value |= (1 << 15); - value |= (1 << 16); - } - if (INPUT(core->input).type == CX88_VMUX_SVIDEO) - value |= (1 << 13) | (1 << 5); - if (V4L2_FIELD_INTERLACED == field) - value |= (1 << 3); // VINT (interlaced vertical scaling) - if (width < 385) - value |= (1 << 0); // 3-tap interpolation - if (width < 193) - value |= (1 << 1); // 5-tap interpolation - if (nocomb) - value |= (3 << 5); // disable comb filter - - cx_andor(MO_FILTER_EVEN, 0x7ffc7f, value); /* preserve PEAKEN, PSEL */ - cx_andor(MO_FILTER_ODD, 0x7ffc7f, value); - dprintk(1,"set_scale: filter 0x%04x\n", value); - - return 0; -} - -static const u32 xtal = 28636363; - -static int set_pll(struct cx88_core *core, int prescale, u32 ofreq) -{ - static const u32 pre[] = { 0, 0, 0, 3, 2, 1 }; - u64 pll; - u32 reg; - int i; - - if (prescale < 2) - prescale = 2; - if (prescale > 5) - prescale = 5; - - pll = ofreq * 8 * prescale * (u64)(1 << 20); - do_div(pll,xtal); - reg = (pll & 0x3ffffff) | (pre[prescale] << 26); - if (((reg >> 20) & 0x3f) < 14) { - printk("%s/0: pll out of range\n",core->name); - return -1; - } - - dprintk(1,"set_pll: MO_PLL_REG 0x%08x [old=0x%08x,freq=%d]\n", - reg, cx_read(MO_PLL_REG), ofreq); - cx_write(MO_PLL_REG, reg); - for (i = 0; i < 100; i++) { - reg = cx_read(MO_DEVICE_STATUS); - if (reg & (1<<2)) { - dprintk(1,"pll locked [pre=%d,ofreq=%d]\n", - prescale,ofreq); - return 0; - } - dprintk(1,"pll not locked yet, waiting ...\n"); - msleep(10); - } - dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq); - return -1; -} - -int cx88_start_audio_dma(struct cx88_core *core) -{ - /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */ - int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4; - - int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size/AUD_RDS_LINES; - - /* If downstream RISC is enabled, bail out; ALSA is managing DMA */ - if (cx_read(MO_AUD_DMACNTRL) & 0x10) - return 0; - - /* setup fifo + format */ - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0); - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0); - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], - rds_bpl, 0); - - cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */ - cx_write(MO_AUDR_LNGTH, rds_bpl); /* fifo bpl size */ - - /* enable Up, Down and Audio RDS fifo */ - cx_write(MO_AUD_DMACNTRL, 0x0007); - - return 0; -} - -int cx88_stop_audio_dma(struct cx88_core *core) -{ - /* If downstream RISC is enabled, bail out; ALSA is managing DMA */ - if (cx_read(MO_AUD_DMACNTRL) & 0x10) - return 0; - - /* stop dma */ - cx_write(MO_AUD_DMACNTRL, 0x0000); - - return 0; -} - -static int set_tvaudio(struct cx88_core *core) -{ - v4l2_std_id norm = core->tvnorm; - - if (CX88_VMUX_TELEVISION != INPUT(core->input).type && - CX88_VMUX_CABLE != INPUT(core->input).type) - return 0; - - if (V4L2_STD_PAL_BG & norm) { - core->tvaudio = WW_BG; - - } else if (V4L2_STD_PAL_DK & norm) { - core->tvaudio = WW_DK; - - } else if (V4L2_STD_PAL_I & norm) { - core->tvaudio = WW_I; - - } else if (V4L2_STD_SECAM_L & norm) { - core->tvaudio = WW_L; - - } else if ((V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H) & norm) { - core->tvaudio = WW_BG; - - } else if (V4L2_STD_SECAM_DK & norm) { - core->tvaudio = WW_DK; - - } else if ((V4L2_STD_NTSC_M & norm) || - (V4L2_STD_PAL_M & norm)) { - core->tvaudio = WW_BTSC; - - } else if (V4L2_STD_NTSC_M_JP & norm) { - core->tvaudio = WW_EIAJ; - - } else { - printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n", - core->name, v4l2_norm_to_name(core->tvnorm)); - core->tvaudio = WW_NONE; - return 0; - } - - cx_andor(MO_AFECFG_IO, 0x1f, 0x0); - cx88_set_tvaudio(core); - /* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */ - -/* - This should be needed only on cx88-alsa. It seems that some cx88 chips have - bugs and does require DMA enabled for it to work. - */ - cx88_start_audio_dma(core); - return 0; -} - - - -int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm) -{ - u32 fsc8; - u32 adc_clock; - u32 vdec_clock; - u32 step_db,step_dr; - u64 tmp64; - u32 bdelay,agcdelay,htotal; - u32 cxiformat, cxoformat; - - core->tvnorm = norm; - fsc8 = norm_fsc8(norm); - adc_clock = xtal; - vdec_clock = fsc8; - step_db = fsc8; - step_dr = fsc8; - - if (norm & V4L2_STD_NTSC_M_JP) { - cxiformat = VideoFormatNTSCJapan; - cxoformat = 0x181f0008; - } else if (norm & V4L2_STD_NTSC_443) { - cxiformat = VideoFormatNTSC443; - cxoformat = 0x181f0008; - } else if (norm & V4L2_STD_PAL_M) { - cxiformat = VideoFormatPALM; - cxoformat = 0x1c1f0008; - } else if (norm & V4L2_STD_PAL_N) { - cxiformat = VideoFormatPALN; - cxoformat = 0x1c1f0008; - } else if (norm & V4L2_STD_PAL_Nc) { - cxiformat = VideoFormatPALNC; - cxoformat = 0x1c1f0008; - } else if (norm & V4L2_STD_PAL_60) { - cxiformat = VideoFormatPAL60; - cxoformat = 0x181f0008; - } else if (norm & V4L2_STD_NTSC) { - cxiformat = VideoFormatNTSC; - cxoformat = 0x181f0008; - } else if (norm & V4L2_STD_SECAM) { - step_db = 4250000 * 8; - step_dr = 4406250 * 8; - - cxiformat = VideoFormatSECAM; - cxoformat = 0x181f0008; - } else { /* PAL */ - cxiformat = VideoFormatPAL; - cxoformat = 0x181f0008; - } - - dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n", - v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock, - step_db, step_dr); - set_pll(core,2,vdec_clock); - - dprintk(1,"set_tvnorm: MO_INPUT_FORMAT 0x%08x [old=0x%08x]\n", - cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f); - /* Chroma AGC must be disabled if SECAM is used, we enable it - by default on PAL and NTSC */ - cx_andor(MO_INPUT_FORMAT, 0x40f, - norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400); - - // FIXME: as-is from DScaler - dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n", - cxoformat, cx_read(MO_OUTPUT_FORMAT)); - cx_write(MO_OUTPUT_FORMAT, cxoformat); - - // MO_SCONV_REG = adc clock / video dec clock * 2^17 - tmp64 = adc_clock * (u64)(1 << 17); - do_div(tmp64, vdec_clock); - dprintk(1,"set_tvnorm: MO_SCONV_REG 0x%08x [old=0x%08x]\n", - (u32)tmp64, cx_read(MO_SCONV_REG)); - cx_write(MO_SCONV_REG, (u32)tmp64); - - // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22 - tmp64 = step_db * (u64)(1 << 22); - do_div(tmp64, vdec_clock); - dprintk(1,"set_tvnorm: MO_SUB_STEP 0x%08x [old=0x%08x]\n", - (u32)tmp64, cx_read(MO_SUB_STEP)); - cx_write(MO_SUB_STEP, (u32)tmp64); - - // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22 - tmp64 = step_dr * (u64)(1 << 22); - do_div(tmp64, vdec_clock); - dprintk(1,"set_tvnorm: MO_SUB_STEP_DR 0x%08x [old=0x%08x]\n", - (u32)tmp64, cx_read(MO_SUB_STEP_DR)); - cx_write(MO_SUB_STEP_DR, (u32)tmp64); - - // bdelay + agcdelay - bdelay = vdec_clock * 65 / 20000000 + 21; - agcdelay = vdec_clock * 68 / 20000000 + 15; - dprintk(1,"set_tvnorm: MO_AGC_BURST 0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n", - (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay); - cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay); - - // htotal - tmp64 = norm_htotal(norm) * (u64)vdec_clock; - do_div(tmp64, fsc8); - htotal = (u32)tmp64; - dprintk(1,"set_tvnorm: MO_HTOTAL 0x%08x [old=0x%08x,htotal=%d]\n", - htotal, cx_read(MO_HTOTAL), (u32)tmp64); - cx_andor(MO_HTOTAL, 0x07ff, htotal); - - // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes - // the effective vbi offset ~244 samples, the same as the Bt8x8 - cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm)); - - // this is needed as well to set all tvnorm parameter - cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED); - - // audio - set_tvaudio(core); - - // tell i2c chips - call_all(core, core, s_std, norm); - - /* The chroma_agc control should be inaccessible if the video format is SECAM */ - v4l2_ctrl_grab(core->chroma_agc, cxiformat == VideoFormatSECAM); - - // done - return 0; -} - -/* ------------------------------------------------------------------ */ - -struct video_device *cx88_vdev_init(struct cx88_core *core, - struct pci_dev *pci, - const struct video_device *template_, - const char *type) -{ - struct video_device *vfd; - - vfd = video_device_alloc(); - if (NULL == vfd) - return NULL; - *vfd = *template_; - vfd->v4l2_dev = &core->v4l2_dev; - vfd->release = video_device_release; - snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", - core->name, type, core->board.name); - set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags); - return vfd; -} - -struct cx88_core* cx88_core_get(struct pci_dev *pci) -{ - struct cx88_core *core; - - mutex_lock(&devlist); - list_for_each_entry(core, &cx88_devlist, devlist) { - if (pci->bus->number != core->pci_bus) - continue; - if (PCI_SLOT(pci->devfn) != core->pci_slot) - continue; - - if (0 != cx88_get_resources(core, pci)) { - mutex_unlock(&devlist); - return NULL; - } - atomic_inc(&core->refcount); - mutex_unlock(&devlist); - return core; - } - - core = cx88_core_create(pci, cx88_devcount); - if (NULL != core) { - cx88_devcount++; - list_add_tail(&core->devlist, &cx88_devlist); - } - - mutex_unlock(&devlist); - return core; -} - -void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) -{ - release_mem_region(pci_resource_start(pci,0), - pci_resource_len(pci,0)); - - if (!atomic_dec_and_test(&core->refcount)) - return; - - mutex_lock(&devlist); - cx88_ir_fini(core); - if (0 == core->i2c_rc) { - if (core->i2c_rtc) - i2c_unregister_device(core->i2c_rtc); - i2c_del_adapter(&core->i2c_adap); - } - list_del(&core->devlist); - iounmap(core->lmmio); - cx88_devcount--; - mutex_unlock(&devlist); - v4l2_ctrl_handler_free(&core->video_hdl); - v4l2_ctrl_handler_free(&core->audio_hdl); - v4l2_device_unregister(&core->v4l2_dev); - kfree(core); -} - -/* ------------------------------------------------------------------ */ - -EXPORT_SYMBOL(cx88_print_irqbits); - -EXPORT_SYMBOL(cx88_core_irq); -EXPORT_SYMBOL(cx88_wakeup); -EXPORT_SYMBOL(cx88_reset); -EXPORT_SYMBOL(cx88_shutdown); - -EXPORT_SYMBOL(cx88_risc_buffer); -EXPORT_SYMBOL(cx88_risc_databuffer); -EXPORT_SYMBOL(cx88_risc_stopper); -EXPORT_SYMBOL(cx88_free_buffer); - -EXPORT_SYMBOL(cx88_sram_channels); -EXPORT_SYMBOL(cx88_sram_channel_setup); -EXPORT_SYMBOL(cx88_sram_channel_dump); - -EXPORT_SYMBOL(cx88_set_tvnorm); -EXPORT_SYMBOL(cx88_set_scale); - -EXPORT_SYMBOL(cx88_vdev_init); -EXPORT_SYMBOL(cx88_core_get); -EXPORT_SYMBOL(cx88_core_put); - -EXPORT_SYMBOL(cx88_ir_start); -EXPORT_SYMBOL(cx88_ir_stop); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off - */ diff --git a/drivers/media/video/cx88/cx88-dsp.c b/drivers/media/video/cx88/cx88-dsp.c deleted file mode 100644 index a9907265ff66..000000000000 --- a/drivers/media/video/cx88/cx88-dsp.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * - * Stereo and SAP detection for cx88 - * - * Copyright (c) 2009 Marton Balint <cus@fazekas.hu> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/slab.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/jiffies.h> -#include <asm/div64.h> - -#include "cx88.h" -#include "cx88-reg.h" - -#define INT_PI ((s32)(3.141592653589 * 32768.0)) - -#define compat_remainder(a, b) \ - ((float)(((s32)((a)*100))%((s32)((b)*100)))/100.0) - -#define baseband_freq(carrier, srate, tone) ((s32)( \ - (compat_remainder(carrier + tone, srate)) / srate * 2 * INT_PI)) - -/* We calculate the baseband frequencies of the carrier and the pilot tones - * based on the the sampling rate of the audio rds fifo. */ - -#define FREQ_A2_CARRIER baseband_freq(54687.5, 2689.36, 0.0) -#define FREQ_A2_DUAL baseband_freq(54687.5, 2689.36, 274.1) -#define FREQ_A2_STEREO baseband_freq(54687.5, 2689.36, 117.5) - -/* The frequencies below are from the reference driver. They probably need - * further adjustments, because they are not tested at all. You may even need - * to play a bit with the registers of the chip to select the proper signal - * for the input of the audio rds fifo, and measure it's sampling rate to - * calculate the proper baseband frequencies... */ - -#define FREQ_A2M_CARRIER ((s32)(2.114516 * 32768.0)) -#define FREQ_A2M_DUAL ((s32)(2.754916 * 32768.0)) -#define FREQ_A2M_STEREO ((s32)(2.462326 * 32768.0)) - -#define FREQ_EIAJ_CARRIER ((s32)(1.963495 * 32768.0)) /* 5pi/8 */ -#define FREQ_EIAJ_DUAL ((s32)(2.562118 * 32768.0)) -#define FREQ_EIAJ_STEREO ((s32)(2.601053 * 32768.0)) - -#define FREQ_BTSC_DUAL ((s32)(1.963495 * 32768.0)) /* 5pi/8 */ -#define FREQ_BTSC_DUAL_REF ((s32)(1.374446 * 32768.0)) /* 7pi/16 */ - -#define FREQ_BTSC_SAP ((s32)(2.471532 * 32768.0)) -#define FREQ_BTSC_SAP_REF ((s32)(1.730072 * 32768.0)) - -/* The spectrum of the signal should be empty between these frequencies. */ -#define FREQ_NOISE_START ((s32)(0.100000 * 32768.0)) -#define FREQ_NOISE_END ((s32)(1.200000 * 32768.0)) - -static unsigned int dsp_debug; -module_param(dsp_debug, int, 0644); -MODULE_PARM_DESC(dsp_debug, "enable audio dsp debug messages"); - -#define dprintk(level, fmt, arg...) if (dsp_debug >= level) \ - printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) - -static s32 int_cos(u32 x) -{ - u32 t2, t4, t6, t8; - s32 ret; - u16 period = x / INT_PI; - if (period % 2) - return -int_cos(x - INT_PI); - x = x % INT_PI; - if (x > INT_PI/2) - return -int_cos(INT_PI/2 - (x % (INT_PI/2))); - /* Now x is between 0 and INT_PI/2. - * To calculate cos(x) we use it's Taylor polinom. */ - t2 = x*x/32768/2; - t4 = t2*x/32768*x/32768/3/4; - t6 = t4*x/32768*x/32768/5/6; - t8 = t6*x/32768*x/32768/7/8; - ret = 32768-t2+t4-t6+t8; - return ret; -} - -static u32 int_goertzel(s16 x[], u32 N, u32 freq) -{ - /* We use the Goertzel algorithm to determine the power of the - * given frequency in the signal */ - s32 s_prev = 0; - s32 s_prev2 = 0; - s32 coeff = 2*int_cos(freq); - u32 i; - - u64 tmp; - u32 divisor; - - for (i = 0; i < N; i++) { - s32 s = x[i] + ((s64)coeff*s_prev/32768) - s_prev2; - s_prev2 = s_prev; - s_prev = s; - } - - tmp = (s64)s_prev2 * s_prev2 + (s64)s_prev * s_prev - - (s64)coeff * s_prev2 * s_prev / 32768; - - /* XXX: N must be low enough so that N*N fits in s32. - * Else we need two divisions. */ - divisor = N * N; - do_div(tmp, divisor); - - return (u32) tmp; -} - -static u32 freq_magnitude(s16 x[], u32 N, u32 freq) -{ - u32 sum = int_goertzel(x, N, freq); - return (u32)int_sqrt(sum); -} - -static u32 noise_magnitude(s16 x[], u32 N, u32 freq_start, u32 freq_end) -{ - int i; - u32 sum = 0; - u32 freq_step; - int samples = 5; - - if (N > 192) { - /* The last 192 samples are enough for noise detection */ - x += (N-192); - N = 192; - } - - freq_step = (freq_end - freq_start) / (samples - 1); - - for (i = 0; i < samples; i++) { - sum += int_goertzel(x, N, freq_start); - freq_start += freq_step; - } - - return (u32)int_sqrt(sum / samples); -} - -static s32 detect_a2_a2m_eiaj(struct cx88_core *core, s16 x[], u32 N) -{ - s32 carrier, stereo, dual, noise; - s32 carrier_freq, stereo_freq, dual_freq; - s32 ret; - - switch (core->tvaudio) { - case WW_BG: - case WW_DK: - carrier_freq = FREQ_A2_CARRIER; - stereo_freq = FREQ_A2_STEREO; - dual_freq = FREQ_A2_DUAL; - break; - case WW_M: - carrier_freq = FREQ_A2M_CARRIER; - stereo_freq = FREQ_A2M_STEREO; - dual_freq = FREQ_A2M_DUAL; - break; - case WW_EIAJ: - carrier_freq = FREQ_EIAJ_CARRIER; - stereo_freq = FREQ_EIAJ_STEREO; - dual_freq = FREQ_EIAJ_DUAL; - break; - default: - printk(KERN_WARNING "%s/0: unsupported audio mode %d for %s\n", - core->name, core->tvaudio, __func__); - return UNSET; - } - - carrier = freq_magnitude(x, N, carrier_freq); - stereo = freq_magnitude(x, N, stereo_freq); - dual = freq_magnitude(x, N, dual_freq); - noise = noise_magnitude(x, N, FREQ_NOISE_START, FREQ_NOISE_END); - - dprintk(1, "detect a2/a2m/eiaj: carrier=%d, stereo=%d, dual=%d, " - "noise=%d\n", carrier, stereo, dual, noise); - - if (stereo > dual) - ret = V4L2_TUNER_SUB_STEREO; - else - ret = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; - - if (core->tvaudio == WW_EIAJ) { - /* EIAJ checks may need adjustments */ - if ((carrier > max(stereo, dual)*2) && - (carrier < max(stereo, dual)*6) && - (carrier > 20 && carrier < 200) && - (max(stereo, dual) > min(stereo, dual))) { - /* For EIAJ the carrier is always present, - so we probably don't need noise detection */ - return ret; - } - } else { - if ((carrier > max(stereo, dual)*2) && - (carrier < max(stereo, dual)*8) && - (carrier > 20 && carrier < 200) && - (noise < 10) && - (max(stereo, dual) > min(stereo, dual)*2)) { - return ret; - } - } - return V4L2_TUNER_SUB_MONO; -} - -static s32 detect_btsc(struct cx88_core *core, s16 x[], u32 N) -{ - s32 sap_ref = freq_magnitude(x, N, FREQ_BTSC_SAP_REF); - s32 sap = freq_magnitude(x, N, FREQ_BTSC_SAP); - s32 dual_ref = freq_magnitude(x, N, FREQ_BTSC_DUAL_REF); - s32 dual = freq_magnitude(x, N, FREQ_BTSC_DUAL); - dprintk(1, "detect btsc: dual_ref=%d, dual=%d, sap_ref=%d, sap=%d" - "\n", dual_ref, dual, sap_ref, sap); - /* FIXME: Currently not supported */ - return UNSET; -} - -static s16 *read_rds_samples(struct cx88_core *core, u32 *N) -{ - const struct sram_channel *srch = &cx88_sram_channels[SRAM_CH27]; - s16 *samples; - - unsigned int i; - unsigned int bpl = srch->fifo_size/AUD_RDS_LINES; - unsigned int spl = bpl/4; - unsigned int sample_count = spl*(AUD_RDS_LINES-1); - - u32 current_address = cx_read(srch->ptr1_reg); - u32 offset = (current_address - srch->fifo_start + bpl); - - dprintk(1, "read RDS samples: current_address=%08x (offset=%08x), " - "sample_count=%d, aud_intstat=%08x\n", current_address, - current_address - srch->fifo_start, sample_count, - cx_read(MO_AUD_INTSTAT)); - - samples = kmalloc(sizeof(s16)*sample_count, GFP_KERNEL); - if (!samples) - return NULL; - - *N = sample_count; - - for (i = 0; i < sample_count; i++) { - offset = offset % (AUD_RDS_LINES*bpl); - samples[i] = cx_read(srch->fifo_start + offset); - offset += 4; - } - - if (dsp_debug >= 2) { - dprintk(2, "RDS samples dump: "); - for (i = 0; i < sample_count; i++) - printk("%hd ", samples[i]); - printk(".\n"); - } - - return samples; -} - -s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core) -{ - s16 *samples; - u32 N = 0; - s32 ret = UNSET; - - /* If audio RDS fifo is disabled, we can't read the samples */ - if (!(cx_read(MO_AUD_DMACNTRL) & 0x04)) - return ret; - if (!(cx_read(AUD_CTL) & EN_FMRADIO_EN_RDS)) - return ret; - - /* Wait at least 500 ms after an audio standard change */ - if (time_before(jiffies, core->last_change + msecs_to_jiffies(500))) - return ret; - - samples = read_rds_samples(core, &N); - - if (!samples) - return ret; - - switch (core->tvaudio) { - case WW_BG: - case WW_DK: - case WW_EIAJ: - case WW_M: - ret = detect_a2_a2m_eiaj(core, samples, N); - break; - case WW_BTSC: - ret = detect_btsc(core, samples, N); - break; - case WW_NONE: - case WW_I: - case WW_L: - case WW_I2SPT: - case WW_FM: - case WW_I2SADC: - break; - } - - kfree(samples); - - if (UNSET != ret) - dprintk(1, "stereo/sap detection result:%s%s%s\n", - (ret & V4L2_TUNER_SUB_MONO) ? " mono" : "", - (ret & V4L2_TUNER_SUB_STEREO) ? " stereo" : "", - (ret & V4L2_TUNER_SUB_LANG2) ? " dual" : ""); - - return ret; -} -EXPORT_SYMBOL(cx88_dsp_detect_stereo_sap); - diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c deleted file mode 100644 index d803bba09525..000000000000 --- a/drivers/media/video/cx88/cx88-dvb.c +++ /dev/null @@ -1,1778 +0,0 @@ -/* - * - * device driver for Conexant 2388x based TV cards - * MPEG Transport Stream (DVB) routines - * - * (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> - * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/fs.h> -#include <linux/kthread.h> -#include <linux/file.h> -#include <linux/suspend.h> - -#include "cx88.h" -#include "dvb-pll.h" -#include <media/v4l2-common.h> - -#include "mt352.h" -#include "mt352_priv.h" -#include "cx88-vp3054-i2c.h" -#include "zl10353.h" -#include "cx22702.h" -#include "or51132.h" -#include "lgdt330x.h" -#include "s5h1409.h" -#include "xc4000.h" -#include "xc5000.h" -#include "nxt200x.h" -#include "cx24123.h" -#include "isl6421.h" -#include "tuner-simple.h" -#include "tda9887.h" -#include "s5h1411.h" -#include "stv0299.h" -#include "z0194a.h" -#include "stv0288.h" -#include "stb6000.h" -#include "cx24116.h" -#include "stv0900.h" -#include "stb6100.h" -#include "stb6100_proc.h" -#include "mb86a16.h" -#include "ds3000.h" - -MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); -MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); -MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(CX88_VERSION); - -static unsigned int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); - -static unsigned int dvb_buf_tscnt = 32; -module_param(dvb_buf_tscnt, int, 0644); -MODULE_PARM_DESC(dvb_buf_tscnt, "DVB Buffer TS count [dvb]"); - -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -#define dprintk(level,fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg) - -/* ------------------------------------------------------------------ */ - -static int dvb_buf_setup(struct videobuf_queue *q, - unsigned int *count, unsigned int *size) -{ - struct cx8802_dev *dev = q->priv_data; - - dev->ts_packet_size = 188 * 4; - dev->ts_packet_count = dvb_buf_tscnt; - - *size = dev->ts_packet_size * dev->ts_packet_count; - *count = dvb_buf_tscnt; - return 0; -} - -static int dvb_buf_prepare(struct videobuf_queue *q, - struct videobuf_buffer *vb, enum v4l2_field field) -{ - struct cx8802_dev *dev = q->priv_data; - return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field); -} - -static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct cx8802_dev *dev = q->priv_data; - cx8802_buf_queue(dev, (struct cx88_buffer*)vb); -} - -static void dvb_buf_release(struct videobuf_queue *q, - struct videobuf_buffer *vb) -{ - cx88_free_buffer(q, (struct cx88_buffer*)vb); -} - -static const struct videobuf_queue_ops dvb_qops = { - .buf_setup = dvb_buf_setup, - .buf_prepare = dvb_buf_prepare, - .buf_queue = dvb_buf_queue, - .buf_release = dvb_buf_release, -}; - -/* ------------------------------------------------------------------ */ - -static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) -{ - struct cx8802_dev *dev= fe->dvb->priv; - struct cx8802_driver *drv = NULL; - int ret = 0; - int fe_id; - - fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe); - if (!fe_id) { - printk(KERN_ERR "%s() No frontend found\n", __func__); - return -EINVAL; - } - - mutex_lock(&dev->core->lock); - drv = cx8802_get_driver(dev, CX88_MPEG_DVB); - if (drv) { - if (acquire){ - dev->frontends.active_fe_id = fe_id; - ret = drv->request_acquire(drv); - } else { - ret = drv->request_release(drv); - dev->frontends.active_fe_id = 0; - } - } - mutex_unlock(&dev->core->lock); - - return ret; -} - -static void cx88_dvb_gate_ctrl(struct cx88_core *core, int open) -{ - struct videobuf_dvb_frontends *f; - struct videobuf_dvb_frontend *fe; - - if (!core->dvbdev) - return; - - f = &core->dvbdev->frontends; - - if (!f) - return; - - if (f->gate <= 1) /* undefined or fe0 */ - fe = videobuf_dvb_get_frontend(f, 1); - else - fe = videobuf_dvb_get_frontend(f, f->gate); - - if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) - fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open); -} - -/* ------------------------------------------------------------------ */ - -static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) -{ - static const u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; - static const u8 reset [] = { RESET, 0x80 }; - static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; - static const u8 agc_cfg [] = { AGC_TARGET, 0x24, 0x20 }; - static const u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; - static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; - - mt352_write(fe, clock_config, sizeof(clock_config)); - udelay(200); - mt352_write(fe, reset, sizeof(reset)); - mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); - - mt352_write(fe, agc_cfg, sizeof(agc_cfg)); - mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); - mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); - return 0; -} - -static int dvico_dual_demod_init(struct dvb_frontend *fe) -{ - static const u8 clock_config [] = { CLOCK_CTL, 0x38, 0x38 }; - static const u8 reset [] = { RESET, 0x80 }; - static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; - static const u8 agc_cfg [] = { AGC_TARGET, 0x28, 0x20 }; - static const u8 gpp_ctl_cfg [] = { GPP_CTL, 0x33 }; - static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 }; - - mt352_write(fe, clock_config, sizeof(clock_config)); - udelay(200); - mt352_write(fe, reset, sizeof(reset)); - mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); - - mt352_write(fe, agc_cfg, sizeof(agc_cfg)); - mt352_write(fe, gpp_ctl_cfg, sizeof(gpp_ctl_cfg)); - mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); - - return 0; -} - -static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) -{ - static const u8 clock_config [] = { 0x89, 0x38, 0x39 }; - static const u8 reset [] = { 0x50, 0x80 }; - static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; - static const u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, - 0x00, 0xFF, 0x00, 0x40, 0x40 }; - static const u8 dntv_extra[] = { 0xB5, 0x7A }; - static const u8 capt_range_cfg[] = { 0x75, 0x32 }; - - mt352_write(fe, clock_config, sizeof(clock_config)); - udelay(2000); - mt352_write(fe, reset, sizeof(reset)); - mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); - - mt352_write(fe, agc_cfg, sizeof(agc_cfg)); - udelay(2000); - mt352_write(fe, dntv_extra, sizeof(dntv_extra)); - mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); - - return 0; -} - -static const struct mt352_config dvico_fusionhdtv = { - .demod_address = 0x0f, - .demod_init = dvico_fusionhdtv_demod_init, -}; - -static const struct mt352_config dntv_live_dvbt_config = { - .demod_address = 0x0f, - .demod_init = dntv_live_dvbt_demod_init, -}; - -static const struct mt352_config dvico_fusionhdtv_dual = { - .demod_address = 0x0f, - .demod_init = dvico_dual_demod_init, -}; - -static const struct zl10353_config cx88_terratec_cinergy_ht_pci_mkii_config = { - .demod_address = (0x1e >> 1), - .no_tuner = 1, - .if2 = 45600, -}; - -static struct mb86a16_config twinhan_vp1027 = { - .demod_address = 0x08, -}; - -#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) -static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe) -{ - static const u8 clock_config [] = { 0x89, 0x38, 0x38 }; - static const u8 reset [] = { 0x50, 0x80 }; - static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; - static const u8 agc_cfg [] = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF, - 0x00, 0xFF, 0x00, 0x40, 0x40 }; - static const u8 dntv_extra[] = { 0xB5, 0x7A }; - static const u8 capt_range_cfg[] = { 0x75, 0x32 }; - - mt352_write(fe, clock_config, sizeof(clock_config)); - udelay(2000); - mt352_write(fe, reset, sizeof(reset)); - mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); - - mt352_write(fe, agc_cfg, sizeof(agc_cfg)); - udelay(2000); - mt352_write(fe, dntv_extra, sizeof(dntv_extra)); - mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); - - return 0; -} - -static const struct mt352_config dntv_live_dvbt_pro_config = { - .demod_address = 0x0f, - .no_tuner = 1, - .demod_init = dntv_live_dvbt_pro_demod_init, -}; -#endif - -static const struct zl10353_config dvico_fusionhdtv_hybrid = { - .demod_address = 0x0f, - .no_tuner = 1, -}; - -static const struct zl10353_config dvico_fusionhdtv_xc3028 = { - .demod_address = 0x0f, - .if2 = 45600, - .no_tuner = 1, -}; - -static const struct mt352_config dvico_fusionhdtv_mt352_xc3028 = { - .demod_address = 0x0f, - .if2 = 4560, - .no_tuner = 1, - .demod_init = dvico_fusionhdtv_demod_init, -}; - -static const struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { - .demod_address = 0x0f, -}; - -static const struct cx22702_config connexant_refboard_config = { - .demod_address = 0x43, - .output_mode = CX22702_SERIAL_OUTPUT, -}; - -static const struct cx22702_config hauppauge_hvr_config = { - .demod_address = 0x63, - .output_mode = CX22702_SERIAL_OUTPUT, -}; - -static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured) -{ - struct cx8802_dev *dev= fe->dvb->priv; - dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; - return 0; -} - -static const struct or51132_config pchdtv_hd3000 = { - .demod_address = 0x15, - .set_ts_params = or51132_set_ts_param, -}; - -static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) -{ - struct cx8802_dev *dev= fe->dvb->priv; - struct cx88_core *core = dev->core; - - dprintk(1, "%s: index = %d\n", __func__, index); - if (index == 0) - cx_clear(MO_GP0_IO, 8); - else - cx_set(MO_GP0_IO, 8); - return 0; -} - -static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured) -{ - struct cx8802_dev *dev= fe->dvb->priv; - if (is_punctured) - dev->ts_gen_cntrl |= 0x04; - else - dev->ts_gen_cntrl &= ~0x04; - return 0; -} - -static struct lgdt330x_config fusionhdtv_3_gold = { - .demod_address = 0x0e, - .demod_chip = LGDT3302, - .serial_mpeg = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */ - .set_ts_params = lgdt330x_set_ts_param, -}; - -static const struct lgdt330x_config fusionhdtv_5_gold = { - .demod_address = 0x0e, - .demod_chip = LGDT3303, - .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ - .set_ts_params = lgdt330x_set_ts_param, -}; - -static const struct lgdt330x_config pchdtv_hd5500 = { - .demod_address = 0x59, - .demod_chip = LGDT3303, - .serial_mpeg = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */ - .set_ts_params = lgdt330x_set_ts_param, -}; - -static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured) -{ - struct cx8802_dev *dev= fe->dvb->priv; - dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; - return 0; -} - -static const struct nxt200x_config ati_hdtvwonder = { - .demod_address = 0x0a, - .set_ts_params = nxt200x_set_ts_param, -}; - -static int cx24123_set_ts_param(struct dvb_frontend* fe, - int is_punctured) -{ - struct cx8802_dev *dev= fe->dvb->priv; - dev->ts_gen_cntrl = 0x02; - return 0; -} - -static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, - fe_sec_voltage_t voltage) -{ - struct cx8802_dev *dev= fe->dvb->priv; - struct cx88_core *core = dev->core; - - if (voltage == SEC_VOLTAGE_OFF) - cx_write(MO_GP0_IO, 0x000006fb); - else - cx_write(MO_GP0_IO, 0x000006f9); - - if (core->prev_set_voltage) - return core->prev_set_voltage(fe, voltage); - return 0; -} - -static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe, - fe_sec_voltage_t voltage) -{ - struct cx8802_dev *dev= fe->dvb->priv; - struct cx88_core *core = dev->core; - - if (voltage == SEC_VOLTAGE_OFF) { - dprintk(1,"LNB Voltage OFF\n"); - cx_write(MO_GP0_IO, 0x0000efff); - } - - if (core->prev_set_voltage) - return core->prev_set_voltage(fe, voltage); - return 0; -} - -static int tevii_dvbs_set_voltage(struct dvb_frontend *fe, - fe_sec_voltage_t voltage) -{ - struct cx8802_dev *dev= fe->dvb->priv; - struct cx88_core *core = dev->core; - - cx_set(MO_GP0_IO, 0x6040); - switch (voltage) { - case SEC_VOLTAGE_13: - cx_clear(MO_GP0_IO, 0x20); - break; - case SEC_VOLTAGE_18: - cx_set(MO_GP0_IO, 0x20); - break; - case SEC_VOLTAGE_OFF: - cx_clear(MO_GP0_IO, 0x20); - break; - } - - if (core->prev_set_voltage) - return core->prev_set_voltage(fe, voltage); - return 0; -} - -static int vp1027_set_voltage(struct dvb_frontend *fe, - fe_sec_voltage_t voltage) -{ - struct cx8802_dev *dev = fe->dvb->priv; - struct cx88_core *core = dev->core; - - switch (voltage) { - case SEC_VOLTAGE_13: - dprintk(1, "LNB SEC Voltage=13\n"); - cx_write(MO_GP0_IO, 0x00001220); - break; - case SEC_VOLTAGE_18: - dprintk(1, "LNB SEC Voltage=18\n"); - cx_write(MO_GP0_IO, 0x00001222); - break; - case SEC_VOLTAGE_OFF: - dprintk(1, "LNB Voltage OFF\n"); - cx_write(MO_GP0_IO, 0x00001230); - break; - } - - if (core->prev_set_voltage) - return core->prev_set_voltage(fe, voltage); - return 0; -} - -static const struct cx24123_config geniatech_dvbs_config = { - .demod_address = 0x55, - .set_ts_params = cx24123_set_ts_param, -}; - -static const struct cx24123_config hauppauge_novas_config = { - .demod_address = 0x55, - .set_ts_params = cx24123_set_ts_param, -}; - -static const struct cx24123_config kworld_dvbs_100_config = { - .demod_address = 0x15, - .set_ts_params = cx24123_set_ts_param, - .lnb_polarity = 1, -}; - -static const struct s5h1409_config pinnacle_pctv_hd_800i_config = { - .demod_address = 0x32 >> 1, - .output_mode = S5H1409_PARALLEL_OUTPUT, - .gpio = S5H1409_GPIO_ON, - .qam_if = 44000, - .inversion = S5H1409_INVERSION_OFF, - .status_mode = S5H1409_DEMODLOCKING, - .mpeg_timing = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK, -}; - -static const struct s5h1409_config dvico_hdtv5_pci_nano_config = { - .demod_address = 0x32 >> 1, - .output_mode = S5H1409_SERIAL_OUTPUT, - .gpio = S5H1409_GPIO_OFF, - .inversion = S5H1409_INVERSION_OFF, - .status_mode = S5H1409_DEMODLOCKING, - .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, -}; - -static const struct s5h1409_config kworld_atsc_120_config = { - .demod_address = 0x32 >> 1, - .output_mode = S5H1409_SERIAL_OUTPUT, - .gpio = S5H1409_GPIO_OFF, - .inversion = S5H1409_INVERSION_OFF, - .status_mode = S5H1409_DEMODLOCKING, - .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, -}; - -static const struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { - .i2c_address = 0x64, - .if_khz = 5380, -}; - -static const struct zl10353_config cx88_pinnacle_hybrid_pctv = { - .demod_address = (0x1e >> 1), - .no_tuner = 1, - .if2 = 45600, -}; - -static const struct zl10353_config cx88_geniatech_x8000_mt = { - .demod_address = (0x1e >> 1), - .no_tuner = 1, - .disable_i2c_gate_ctrl = 1, -}; - -static const struct s5h1411_config dvico_fusionhdtv7_config = { - .output_mode = S5H1411_SERIAL_OUTPUT, - .gpio = S5H1411_GPIO_ON, - .mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, - .qam_if = S5H1411_IF_44000, - .vsb_if = S5H1411_IF_44000, - .inversion = S5H1411_INVERSION_OFF, - .status_mode = S5H1411_DEMODLOCKING -}; - -static const struct xc5000_config dvico_fusionhdtv7_tuner_config = { - .i2c_address = 0xc2 >> 1, - .if_khz = 5380, -}; - -static int attach_xc3028(u8 addr, struct cx8802_dev *dev) -{ - struct dvb_frontend *fe; - struct videobuf_dvb_frontend *fe0 = NULL; - struct xc2028_ctrl ctl; - struct xc2028_config cfg = { - .i2c_adap = &dev->core->i2c_adap, - .i2c_addr = addr, - .ctrl = &ctl, - }; - - /* Get the first frontend */ - fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); - if (!fe0) - return -EINVAL; - - if (!fe0->dvb.frontend) { - printk(KERN_ERR "%s/2: dvb frontend not attached. " - "Can't attach xc3028\n", - dev->core->name); - return -EINVAL; - } - - /* - * Some xc3028 devices may be hidden by an I2C gate. This is known - * to happen with some s5h1409-based devices. - * Now that I2C gate is open, sets up xc3028 configuration - */ - cx88_setup_xc3028(dev->core, &ctl); - - fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg); - if (!fe) { - printk(KERN_ERR "%s/2: xc3028 attach failed\n", - dev->core->name); - dvb_frontend_detach(fe0->dvb.frontend); - dvb_unregister_frontend(fe0->dvb.frontend); - fe0->dvb.frontend = NULL; - return -EINVAL; - } - - printk(KERN_INFO "%s/2: xc3028 attached\n", - dev->core->name); - - return 0; -} - -static int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg) -{ - struct dvb_frontend *fe; - struct videobuf_dvb_frontend *fe0 = NULL; - - /* Get the first frontend */ - fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); - if (!fe0) - return -EINVAL; - - if (!fe0->dvb.frontend) { - printk(KERN_ERR "%s/2: dvb frontend not attached. " - "Can't attach xc4000\n", - dev->core->name); - return -EINVAL; - } - - fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->core->i2c_adap, - cfg); - if (!fe) { - printk(KERN_ERR "%s/2: xc4000 attach failed\n", - dev->core->name); - dvb_frontend_detach(fe0->dvb.frontend); - dvb_unregister_frontend(fe0->dvb.frontend); - fe0->dvb.frontend = NULL; - return -EINVAL; - } - - printk(KERN_INFO "%s/2: xc4000 attached\n", dev->core->name); - - return 0; -} - -static int cx24116_set_ts_param(struct dvb_frontend *fe, - int is_punctured) -{ - struct cx8802_dev *dev = fe->dvb->priv; - dev->ts_gen_cntrl = 0x2; - - return 0; -} - -static int stv0900_set_ts_param(struct dvb_frontend *fe, - int is_punctured) -{ - struct cx8802_dev *dev = fe->dvb->priv; - dev->ts_gen_cntrl = 0; - - return 0; -} - -static int cx24116_reset_device(struct dvb_frontend *fe) -{ - struct cx8802_dev *dev = fe->dvb->priv; - struct cx88_core *core = dev->core; - - /* Reset the part */ - /* Put the cx24116 into reset */ - cx_write(MO_SRST_IO, 0); - msleep(10); - /* Take the cx24116 out of reset */ - cx_write(MO_SRST_IO, 1); - msleep(10); - - return 0; -} - -static const struct cx24116_config hauppauge_hvr4000_config = { - .demod_address = 0x05, - .set_ts_params = cx24116_set_ts_param, - .reset_device = cx24116_reset_device, -}; - -static const struct cx24116_config tevii_s460_config = { - .demod_address = 0x55, - .set_ts_params = cx24116_set_ts_param, - .reset_device = cx24116_reset_device, -}; - -static int ds3000_set_ts_param(struct dvb_frontend *fe, - int is_punctured) -{ - struct cx8802_dev *dev = fe->dvb->priv; - dev->ts_gen_cntrl = 4; - - return 0; -} - -static struct ds3000_config tevii_ds3000_config = { - .demod_address = 0x68, - .set_ts_params = ds3000_set_ts_param, -}; - -static const struct stv0900_config prof_7301_stv0900_config = { - .demod_address = 0x6a, -/* demod_mode = 0,*/ - .xtal = 27000000, - .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */ - .diseqc_mode = 2,/* 2/3 PWM */ - .tun1_maddress = 0,/* 0x60 */ - .tun1_adc = 0,/* 2 Vpp */ - .path1_mode = 3, - .set_ts_params = stv0900_set_ts_param, -}; - -static const struct stb6100_config prof_7301_stb6100_config = { - .tuner_address = 0x60, - .refclock = 27000000, -}; - -static const struct stv0299_config tevii_tuner_sharp_config = { - .demod_address = 0x68, - .inittab = sharp_z0194a_inittab, - .mclk = 88000000UL, - .invert = 1, - .skip_reinit = 0, - .lock_output = 1, - .volt13_op0_op1 = STV0299_VOLT13_OP1, - .min_delay_ms = 100, - .set_symbol_rate = sharp_z0194a_set_symbol_rate, - .set_ts_params = cx24116_set_ts_param, -}; - -static const struct stv0288_config tevii_tuner_earda_config = { - .demod_address = 0x68, - .min_delay_ms = 100, - .set_ts_params = cx24116_set_ts_param, -}; - -static int cx8802_alloc_frontends(struct cx8802_dev *dev) -{ - struct cx88_core *core = dev->core; - struct videobuf_dvb_frontend *fe = NULL; - int i; - - mutex_init(&dev->frontends.lock); - INIT_LIST_HEAD(&dev->frontends.felist); - - if (!core->board.num_frontends) - return -ENODEV; - - printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, - core->board.num_frontends); - for (i = 1; i <= core->board.num_frontends; i++) { - fe = videobuf_dvb_alloc_frontend(&dev->frontends, i); - if (!fe) { - printk(KERN_ERR "%s() failed to alloc\n", __func__); - videobuf_dvb_dealloc_frontends(&dev->frontends); - return -ENOMEM; - } - } - return 0; -} - - - -static const u8 samsung_smt_7020_inittab[] = { - 0x01, 0x15, - 0x02, 0x00, - 0x03, 0x00, - 0x04, 0x7D, - 0x05, 0x0F, - 0x06, 0x02, - 0x07, 0x00, - 0x08, 0x60, - - 0x0A, 0xC2, - 0x0B, 0x00, - 0x0C, 0x01, - 0x0D, 0x81, - 0x0E, 0x44, - 0x0F, 0x09, - 0x10, 0x3C, - 0x11, 0x84, - 0x12, 0xDA, - 0x13, 0x99, - 0x14, 0x8D, - 0x15, 0xCE, - 0x16, 0xE8, - 0x17, 0x43, - 0x18, 0x1C, - 0x19, 0x1B, - 0x1A, 0x1D, - - 0x1C, 0x12, - 0x1D, 0x00, - 0x1E, 0x00, - 0x1F, 0x00, - 0x20, 0x00, - 0x21, 0x00, - 0x22, 0x00, - 0x23, 0x00, - - 0x28, 0x02, - 0x29, 0x28, - 0x2A, 0x14, - 0x2B, 0x0F, - 0x2C, 0x09, - 0x2D, 0x05, - - 0x31, 0x1F, - 0x32, 0x19, - 0x33, 0xFC, - 0x34, 0x13, - 0xff, 0xff, -}; - - -static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - struct cx8802_dev *dev = fe->dvb->priv; - u8 buf[4]; - u32 div; - struct i2c_msg msg = { - .addr = 0x61, - .flags = 0, - .buf = buf, - .len = sizeof(buf) }; - - div = c->frequency / 125; - - buf[0] = (div >> 8) & 0x7f; - buf[1] = div & 0xff; - buf[2] = 0x84; /* 0xC4 */ - buf[3] = 0x00; - - if (c->frequency < 1500000) - buf[3] |= 0x10; - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - - if (i2c_transfer(&dev->core->i2c_adap, &msg, 1) != 1) - return -EIO; - - return 0; -} - -static int samsung_smt_7020_set_tone(struct dvb_frontend *fe, - fe_sec_tone_mode_t tone) -{ - struct cx8802_dev *dev = fe->dvb->priv; - struct cx88_core *core = dev->core; - - cx_set(MO_GP0_IO, 0x0800); - - switch (tone) { - case SEC_TONE_ON: - cx_set(MO_GP0_IO, 0x08); - break; - case SEC_TONE_OFF: - cx_clear(MO_GP0_IO, 0x08); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe, - fe_sec_voltage_t voltage) -{ - struct cx8802_dev *dev = fe->dvb->priv; - struct cx88_core *core = dev->core; - - u8 data; - struct i2c_msg msg = { - .addr = 8, - .flags = 0, - .buf = &data, - .len = sizeof(data) }; - - cx_set(MO_GP0_IO, 0x8000); - - switch (voltage) { - case SEC_VOLTAGE_OFF: - break; - case SEC_VOLTAGE_13: - data = ISL6421_EN1 | ISL6421_LLC1; - cx_clear(MO_GP0_IO, 0x80); - break; - case SEC_VOLTAGE_18: - data = ISL6421_EN1 | ISL6421_LLC1 | ISL6421_VSEL1; - cx_clear(MO_GP0_IO, 0x80); - break; - default: - return -EINVAL; - }; - - return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO; -} - -static int samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend *fe, - u32 srate, u32 ratio) -{ - u8 aclk = 0; - u8 bclk = 0; - - if (srate < 1500000) { - aclk = 0xb7; - bclk = 0x47; - } else if (srate < 3000000) { - aclk = 0xb7; - bclk = 0x4b; - } else if (srate < 7000000) { - aclk = 0xb7; - bclk = 0x4f; - } else if (srate < 14000000) { - aclk = 0xb7; - bclk = 0x53; - } else if (srate < 30000000) { - aclk = 0xb6; - bclk = 0x53; - } else if (srate < 45000000) { - aclk = 0xb4; - bclk = 0x51; - } - - stv0299_writereg(fe, 0x13, aclk); - stv0299_writereg(fe, 0x14, bclk); - stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg(fe, 0x21, ratio & 0xf0); - - return 0; -} - - -static const struct stv0299_config samsung_stv0299_config = { - .demod_address = 0x68, - .inittab = samsung_smt_7020_inittab, - .mclk = 88000000UL, - .invert = 0, - .skip_reinit = 0, - .lock_output = STV0299_LOCKOUTPUT_LK, - .volt13_op0_op1 = STV0299_VOLT13_OP1, - .min_delay_ms = 100, - .set_symbol_rate = samsung_smt_7020_stv0299_set_symbol_rate, -}; - -static int dvb_register(struct cx8802_dev *dev) -{ - struct cx88_core *core = dev->core; - struct videobuf_dvb_frontend *fe0, *fe1 = NULL; - int mfe_shared = 0; /* bus not shared by default */ - int res = -EINVAL; - - if (0 != core->i2c_rc) { - printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name); - goto frontend_detach; - } - - /* Get the first frontend */ - fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); - if (!fe0) - goto frontend_detach; - - /* multi-frontend gate control is undefined or defaults to fe0 */ - dev->frontends.gate = 0; - - /* Sets the gate control callback to be used by i2c command calls */ - core->gate_ctrl = cx88_dvb_gate_ctrl; - - /* init frontend(s) */ - switch (core->boardnr) { - case CX88_BOARD_HAUPPAUGE_DVB_T1: - fe0->dvb.frontend = dvb_attach(cx22702_attach, - &connexant_refboard_config, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, - 0x61, &core->i2c_adap, - DVB_PLL_THOMSON_DTT759X)) - goto frontend_detach; - } - break; - case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: - case CX88_BOARD_CONEXANT_DVB_T1: - case CX88_BOARD_KWORLD_DVB_T_CX22702: - case CX88_BOARD_WINFAST_DTV1000: - fe0->dvb.frontend = dvb_attach(cx22702_attach, - &connexant_refboard_config, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, - 0x60, &core->i2c_adap, - DVB_PLL_THOMSON_DTT7579)) - goto frontend_detach; - } - break; - case CX88_BOARD_WINFAST_DTV2000H: - case CX88_BOARD_HAUPPAUGE_HVR1100: - case CX88_BOARD_HAUPPAUGE_HVR1100LP: - case CX88_BOARD_HAUPPAUGE_HVR1300: - fe0->dvb.frontend = dvb_attach(cx22702_attach, - &hauppauge_hvr_config, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, - &core->i2c_adap, 0x61, - TUNER_PHILIPS_FMD1216ME_MK3)) - goto frontend_detach; - } - break; - case CX88_BOARD_WINFAST_DTV2000H_J: - fe0->dvb.frontend = dvb_attach(cx22702_attach, - &hauppauge_hvr_config, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, - &core->i2c_adap, 0x61, - TUNER_PHILIPS_FMD1216MEX_MK3)) - goto frontend_detach; - } - break; - case CX88_BOARD_HAUPPAUGE_HVR3000: - /* MFE frontend 1 */ - mfe_shared = 1; - dev->frontends.gate = 2; - /* DVB-S init */ - fe0->dvb.frontend = dvb_attach(cx24123_attach, - &hauppauge_novas_config, - &dev->core->i2c_adap); - if (fe0->dvb.frontend) { - if (!dvb_attach(isl6421_attach, - fe0->dvb.frontend, - &dev->core->i2c_adap, - 0x08, ISL6421_DCL, 0x00)) - goto frontend_detach; - } - /* MFE frontend 2 */ - fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); - if (!fe1) - goto frontend_detach; - /* DVB-T init */ - fe1->dvb.frontend = dvb_attach(cx22702_attach, - &hauppauge_hvr_config, - &dev->core->i2c_adap); - if (fe1->dvb.frontend) { - fe1->dvb.frontend->id = 1; - if (!dvb_attach(simple_tuner_attach, - fe1->dvb.frontend, - &dev->core->i2c_adap, - 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) - goto frontend_detach; - } - break; - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: - fe0->dvb.frontend = dvb_attach(mt352_attach, - &dvico_fusionhdtv, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, - 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) - goto frontend_detach; - break; - } - /* ZL10353 replaces MT352 on later cards */ - fe0->dvb.frontend = dvb_attach(zl10353_attach, - &dvico_fusionhdtv_plus_v1_1, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, - 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) - goto frontend_detach; - } - break; - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: - /* The tin box says DEE1601, but it seems to be DTT7579 - * compatible, with a slightly different MT352 AGC gain. */ - fe0->dvb.frontend = dvb_attach(mt352_attach, - &dvico_fusionhdtv_dual, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, - 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) - goto frontend_detach; - break; - } - /* ZL10353 replaces MT352 on later cards */ - fe0->dvb.frontend = dvb_attach(zl10353_attach, - &dvico_fusionhdtv_plus_v1_1, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, - 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) - goto frontend_detach; - } - break; - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: - fe0->dvb.frontend = dvb_attach(mt352_attach, - &dvico_fusionhdtv, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, - 0x61, NULL, DVB_PLL_LG_Z201)) - goto frontend_detach; - } - break; - case CX88_BOARD_KWORLD_DVB_T: - case CX88_BOARD_DNTV_LIVE_DVB_T: - case CX88_BOARD_ADSTECH_DVB_T_PCI: - fe0->dvb.frontend = dvb_attach(mt352_attach, - &dntv_live_dvbt_config, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, - 0x61, NULL, DVB_PLL_UNKNOWN_1)) - goto frontend_detach; - } - break; - case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: -#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) - /* MT352 is on a secondary I2C bus made from some GPIO lines */ - fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, - &dev->vp3054->adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, - &core->i2c_adap, 0x61, - TUNER_PHILIPS_FMD1216ME_MK3)) - goto frontend_detach; - } -#else - printk(KERN_ERR "%s/2: built without vp3054 support\n", - core->name); -#endif - break; - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: - fe0->dvb.frontend = dvb_attach(zl10353_attach, - &dvico_fusionhdtv_hybrid, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, - &core->i2c_adap, 0x61, - TUNER_THOMSON_FE6600)) - goto frontend_detach; - } - break; - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: - fe0->dvb.frontend = dvb_attach(zl10353_attach, - &dvico_fusionhdtv_xc3028, - &core->i2c_adap); - if (fe0->dvb.frontend == NULL) - fe0->dvb.frontend = dvb_attach(mt352_attach, - &dvico_fusionhdtv_mt352_xc3028, - &core->i2c_adap); - /* - * On this board, the demod provides the I2C bus pullup. - * We must not permit gate_ctrl to be performed, or - * the xc3028 cannot communicate on the bus. - */ - if (fe0->dvb.frontend) - fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; - if (attach_xc3028(0x61, dev) < 0) - goto frontend_detach; - break; - case CX88_BOARD_PCHDTV_HD3000: - fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, - &core->i2c_adap, 0x61, - TUNER_THOMSON_DTT761X)) - goto frontend_detach; - } - break; - case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: - dev->ts_gen_cntrl = 0x08; - - /* Do a hardware reset of chip before using it. */ - cx_clear(MO_GP0_IO, 1); - mdelay(100); - cx_set(MO_GP0_IO, 1); - mdelay(200); - - /* Select RF connector callback */ - fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; - fe0->dvb.frontend = dvb_attach(lgdt330x_attach, - &fusionhdtv_3_gold, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, - &core->i2c_adap, 0x61, - TUNER_MICROTUNE_4042FI5)) - goto frontend_detach; - } - break; - case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: - dev->ts_gen_cntrl = 0x08; - - /* Do a hardware reset of chip before using it. */ - cx_clear(MO_GP0_IO, 1); - mdelay(100); - cx_set(MO_GP0_IO, 9); - mdelay(200); - fe0->dvb.frontend = dvb_attach(lgdt330x_attach, - &fusionhdtv_3_gold, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, - &core->i2c_adap, 0x61, - TUNER_THOMSON_DTT761X)) - goto frontend_detach; - } - break; - case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: - dev->ts_gen_cntrl = 0x08; - - /* Do a hardware reset of chip before using it. */ - cx_clear(MO_GP0_IO, 1); - mdelay(100); - cx_set(MO_GP0_IO, 1); - mdelay(200); - fe0->dvb.frontend = dvb_attach(lgdt330x_attach, - &fusionhdtv_5_gold, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, - &core->i2c_adap, 0x61, - TUNER_LG_TDVS_H06XF)) - goto frontend_detach; - if (!dvb_attach(tda9887_attach, fe0->dvb.frontend, - &core->i2c_adap, 0x43)) - goto frontend_detach; - } - break; - case CX88_BOARD_PCHDTV_HD5500: - dev->ts_gen_cntrl = 0x08; - - /* Do a hardware reset of chip before using it. */ - cx_clear(MO_GP0_IO, 1); - mdelay(100); - cx_set(MO_GP0_IO, 1); - mdelay(200); - fe0->dvb.frontend = dvb_attach(lgdt330x_attach, - &pchdtv_hd5500, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, - &core->i2c_adap, 0x61, - TUNER_LG_TDVS_H06XF)) - goto frontend_detach; - if (!dvb_attach(tda9887_attach, fe0->dvb.frontend, - &core->i2c_adap, 0x43)) - goto frontend_detach; - } - break; - case CX88_BOARD_ATI_HDTVWONDER: - fe0->dvb.frontend = dvb_attach(nxt200x_attach, - &ati_hdtvwonder, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, - &core->i2c_adap, 0x61, - TUNER_PHILIPS_TUV1236D)) - goto frontend_detach; - } - break; - case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: - case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: - fe0->dvb.frontend = dvb_attach(cx24123_attach, - &hauppauge_novas_config, - &core->i2c_adap); - if (fe0->dvb.frontend) { - if (!dvb_attach(isl6421_attach, fe0->dvb.frontend, - &core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) - goto frontend_detach; - } - break; - case CX88_BOARD_KWORLD_DVBS_100: - fe0->dvb.frontend = dvb_attach(cx24123_attach, - &kworld_dvbs_100_config, - &core->i2c_adap); - if (fe0->dvb.frontend) { - core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; - fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; - } - break; - case CX88_BOARD_GENIATECH_DVBS: - fe0->dvb.frontend = dvb_attach(cx24123_attach, - &geniatech_dvbs_config, - &core->i2c_adap); - if (fe0->dvb.frontend) { - core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; - fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; - } - break; - case CX88_BOARD_PINNACLE_PCTV_HD_800i: - fe0->dvb.frontend = dvb_attach(s5h1409_attach, - &pinnacle_pctv_hd_800i_config, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(xc5000_attach, fe0->dvb.frontend, - &core->i2c_adap, - &pinnacle_pctv_hd_800i_tuner_config)) - goto frontend_detach; - } - break; - case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: - fe0->dvb.frontend = dvb_attach(s5h1409_attach, - &dvico_hdtv5_pci_nano_config, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - struct dvb_frontend *fe; - struct xc2028_config cfg = { - .i2c_adap = &core->i2c_adap, - .i2c_addr = 0x61, - }; - static struct xc2028_ctrl ctl = { - .fname = XC2028_DEFAULT_FIRMWARE, - .max_len = 64, - .scode_table = XC3028_FE_OREN538, - }; - - fe = dvb_attach(xc2028_attach, - fe0->dvb.frontend, &cfg); - if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) - fe->ops.tuner_ops.set_config(fe, &ctl); - } - break; - case CX88_BOARD_PINNACLE_HYBRID_PCTV: - case CX88_BOARD_WINFAST_DTV1800H: - fe0->dvb.frontend = dvb_attach(zl10353_attach, - &cx88_pinnacle_hybrid_pctv, - &core->i2c_adap); - if (fe0->dvb.frontend) { - fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; - if (attach_xc3028(0x61, dev) < 0) - goto frontend_detach; - } - break; - case CX88_BOARD_WINFAST_DTV1800H_XC4000: - case CX88_BOARD_WINFAST_DTV2000H_PLUS: - fe0->dvb.frontend = dvb_attach(zl10353_attach, - &cx88_pinnacle_hybrid_pctv, - &core->i2c_adap); - if (fe0->dvb.frontend) { - struct xc4000_config cfg = { - .i2c_address = 0x61, - .default_pm = 0, - .dvb_amplitude = 134, - .set_smoothedcvbs = 1, - .if_khz = 4560 - }; - fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; - if (attach_xc4000(dev, &cfg) < 0) - goto frontend_detach; - } - break; - case CX88_BOARD_GENIATECH_X8000_MT: - dev->ts_gen_cntrl = 0x00; - - fe0->dvb.frontend = dvb_attach(zl10353_attach, - &cx88_geniatech_x8000_mt, - &core->i2c_adap); - if (attach_xc3028(0x61, dev) < 0) - goto frontend_detach; - break; - case CX88_BOARD_KWORLD_ATSC_120: - fe0->dvb.frontend = dvb_attach(s5h1409_attach, - &kworld_atsc_120_config, - &core->i2c_adap); - if (attach_xc3028(0x61, dev) < 0) - goto frontend_detach; - break; - case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: - fe0->dvb.frontend = dvb_attach(s5h1411_attach, - &dvico_fusionhdtv7_config, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(xc5000_attach, fe0->dvb.frontend, - &core->i2c_adap, - &dvico_fusionhdtv7_tuner_config)) - goto frontend_detach; - } - break; - case CX88_BOARD_HAUPPAUGE_HVR4000: - /* MFE frontend 1 */ - mfe_shared = 1; - dev->frontends.gate = 2; - /* DVB-S/S2 Init */ - fe0->dvb.frontend = dvb_attach(cx24116_attach, - &hauppauge_hvr4000_config, - &dev->core->i2c_adap); - if (fe0->dvb.frontend) { - if (!dvb_attach(isl6421_attach, - fe0->dvb.frontend, - &dev->core->i2c_adap, - 0x08, ISL6421_DCL, 0x00)) - goto frontend_detach; - } - /* MFE frontend 2 */ - fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); - if (!fe1) - goto frontend_detach; - /* DVB-T Init */ - fe1->dvb.frontend = dvb_attach(cx22702_attach, - &hauppauge_hvr_config, - &dev->core->i2c_adap); - if (fe1->dvb.frontend) { - fe1->dvb.frontend->id = 1; - if (!dvb_attach(simple_tuner_attach, - fe1->dvb.frontend, - &dev->core->i2c_adap, - 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) - goto frontend_detach; - } - break; - case CX88_BOARD_HAUPPAUGE_HVR4000LITE: - fe0->dvb.frontend = dvb_attach(cx24116_attach, - &hauppauge_hvr4000_config, - &dev->core->i2c_adap); - if (fe0->dvb.frontend) { - if (!dvb_attach(isl6421_attach, - fe0->dvb.frontend, - &dev->core->i2c_adap, - 0x08, ISL6421_DCL, 0x00)) - goto frontend_detach; - } - break; - case CX88_BOARD_PROF_6200: - case CX88_BOARD_TBS_8910: - case CX88_BOARD_TEVII_S420: - fe0->dvb.frontend = dvb_attach(stv0299_attach, - &tevii_tuner_sharp_config, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, - &core->i2c_adap, DVB_PLL_OPERA1)) - goto frontend_detach; - core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; - fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; - - } else { - fe0->dvb.frontend = dvb_attach(stv0288_attach, - &tevii_tuner_earda_config, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61, - &core->i2c_adap)) - goto frontend_detach; - core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; - fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; - } - } - break; - case CX88_BOARD_TEVII_S460: - fe0->dvb.frontend = dvb_attach(cx24116_attach, - &tevii_s460_config, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) - fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; - break; - case CX88_BOARD_TEVII_S464: - fe0->dvb.frontend = dvb_attach(ds3000_attach, - &tevii_ds3000_config, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) - fe0->dvb.frontend->ops.set_voltage = - tevii_dvbs_set_voltage; - break; - case CX88_BOARD_OMICOM_SS4_PCI: - case CX88_BOARD_TBS_8920: - case CX88_BOARD_PROF_7300: - case CX88_BOARD_SATTRADE_ST4200: - fe0->dvb.frontend = dvb_attach(cx24116_attach, - &hauppauge_hvr4000_config, - &core->i2c_adap); - if (fe0->dvb.frontend != NULL) - fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; - break; - case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII: - fe0->dvb.frontend = dvb_attach(zl10353_attach, - &cx88_terratec_cinergy_ht_pci_mkii_config, - &core->i2c_adap); - if (fe0->dvb.frontend) { - fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; - if (attach_xc3028(0x61, dev) < 0) - goto frontend_detach; - } - break; - case CX88_BOARD_PROF_7301:{ - struct dvb_tuner_ops *tuner_ops = NULL; - - fe0->dvb.frontend = dvb_attach(stv0900_attach, - &prof_7301_stv0900_config, - &core->i2c_adap, 0); - if (fe0->dvb.frontend != NULL) { - if (!dvb_attach(stb6100_attach, fe0->dvb.frontend, - &prof_7301_stb6100_config, - &core->i2c_adap)) - goto frontend_detach; - - tuner_ops = &fe0->dvb.frontend->ops.tuner_ops; - tuner_ops->set_frequency = stb6100_set_freq; - tuner_ops->get_frequency = stb6100_get_freq; - tuner_ops->set_bandwidth = stb6100_set_bandw; - tuner_ops->get_bandwidth = stb6100_get_bandw; - - core->prev_set_voltage = - fe0->dvb.frontend->ops.set_voltage; - fe0->dvb.frontend->ops.set_voltage = - tevii_dvbs_set_voltage; - } - break; - } - case CX88_BOARD_SAMSUNG_SMT_7020: - dev->ts_gen_cntrl = 0x08; - - cx_set(MO_GP0_IO, 0x0101); - - cx_clear(MO_GP0_IO, 0x01); - mdelay(100); - cx_set(MO_GP0_IO, 0x01); - mdelay(200); - - fe0->dvb.frontend = dvb_attach(stv0299_attach, - &samsung_stv0299_config, - &dev->core->i2c_adap); - if (fe0->dvb.frontend) { - fe0->dvb.frontend->ops.tuner_ops.set_params = - samsung_smt_7020_tuner_set_params; - fe0->dvb.frontend->tuner_priv = - &dev->core->i2c_adap; - fe0->dvb.frontend->ops.set_voltage = - samsung_smt_7020_set_voltage; - fe0->dvb.frontend->ops.set_tone = - samsung_smt_7020_set_tone; - } - - break; - case CX88_BOARD_TWINHAN_VP1027_DVBS: - dev->ts_gen_cntrl = 0x00; - fe0->dvb.frontend = dvb_attach(mb86a16_attach, - &twinhan_vp1027, - &core->i2c_adap); - if (fe0->dvb.frontend) { - core->prev_set_voltage = - fe0->dvb.frontend->ops.set_voltage; - fe0->dvb.frontend->ops.set_voltage = - vp1027_set_voltage; - } - break; - - default: - printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", - core->name); - break; - } - - if ( (NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend) ) { - printk(KERN_ERR - "%s/2: frontend initialization failed\n", - core->name); - goto frontend_detach; - } - /* define general-purpose callback pointer */ - fe0->dvb.frontend->callback = cx88_tuner_callback; - - /* Ensure all frontends negotiate bus access */ - fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; - if (fe1) - fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; - - /* Put the analog decoder in standby to keep it quiet */ - call_all(core, core, s_power, 0); - - /* register everything */ - res = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, - &dev->pci->dev, adapter_nr, mfe_shared); - if (res) - goto frontend_detach; - return res; - -frontend_detach: - core->gate_ctrl = NULL; - videobuf_dvb_dealloc_frontends(&dev->frontends); - return res; -} - -/* ----------------------------------------------------------- */ - -/* CX8802 MPEG -> mini driver - We have been given the hardware */ -static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - int err = 0; - dprintk( 1, "%s\n", __func__); - - switch (core->boardnr) { - case CX88_BOARD_HAUPPAUGE_HVR1300: - /* We arrive here with either the cx23416 or the cx22702 - * on the bus. Take the bus from the cx23416 and enable the - * cx22702 demod - */ - /* Toggle reset on cx22702 leaving i2c active */ - cx_set(MO_GP0_IO, 0x00000080); - udelay(1000); - cx_clear(MO_GP0_IO, 0x00000080); - udelay(50); - cx_set(MO_GP0_IO, 0x00000080); - udelay(1000); - /* enable the cx22702 pins */ - cx_clear(MO_GP0_IO, 0x00000004); - udelay(1000); - break; - - case CX88_BOARD_HAUPPAUGE_HVR3000: - case CX88_BOARD_HAUPPAUGE_HVR4000: - /* Toggle reset on cx22702 leaving i2c active */ - cx_set(MO_GP0_IO, 0x00000080); - udelay(1000); - cx_clear(MO_GP0_IO, 0x00000080); - udelay(50); - cx_set(MO_GP0_IO, 0x00000080); - udelay(1000); - switch (core->dvbdev->frontends.active_fe_id) { - case 1: /* DVB-S/S2 Enabled */ - /* tri-state the cx22702 pins */ - cx_set(MO_GP0_IO, 0x00000004); - /* Take the cx24116/cx24123 out of reset */ - cx_write(MO_SRST_IO, 1); - core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */ - break; - case 2: /* DVB-T Enabled */ - /* Put the cx24116/cx24123 into reset */ - cx_write(MO_SRST_IO, 0); - /* enable the cx22702 pins */ - cx_clear(MO_GP0_IO, 0x00000004); - core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */ - break; - } - udelay(1000); - break; - - case CX88_BOARD_WINFAST_DTV2000H_PLUS: - /* set RF input to AIR for DVB-T (GPIO 16) */ - cx_write(MO_GP2_IO, 0x0101); - break; - - default: - err = -ENODEV; - } - return err; -} - -/* CX8802 MPEG -> mini driver - We no longer have the hardware */ -static int cx8802_dvb_advise_release(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - int err = 0; - dprintk( 1, "%s\n", __func__); - - switch (core->boardnr) { - case CX88_BOARD_HAUPPAUGE_HVR1300: - /* Do Nothing, leave the cx22702 on the bus. */ - break; - case CX88_BOARD_HAUPPAUGE_HVR3000: - case CX88_BOARD_HAUPPAUGE_HVR4000: - break; - default: - err = -ENODEV; - } - return err; -} - -static int cx8802_dvb_probe(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - struct cx8802_dev *dev = drv->core->dvbdev; - int err; - struct videobuf_dvb_frontend *fe; - int i; - - dprintk( 1, "%s\n", __func__); - dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", - core->boardnr, - core->name, - core->pci_bus, - core->pci_slot); - - err = -ENODEV; - if (!(core->board.mpeg & CX88_MPEG_DVB)) - goto fail_core; - - /* If vp3054 isn't enabled, a stub will just return 0 */ - err = vp3054_i2c_probe(dev); - if (0 != err) - goto fail_core; - - /* dvb stuff */ - printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); - dev->ts_gen_cntrl = 0x0c; - - err = cx8802_alloc_frontends(dev); - if (err) - goto fail_core; - - err = -ENODEV; - for (i = 1; i <= core->board.num_frontends; i++) { - fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i); - if (fe == NULL) { - printk(KERN_ERR "%s() failed to get frontend(%d)\n", - __func__, i); - goto fail_probe; - } - videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_TOP, - sizeof(struct cx88_buffer), - dev, NULL); - /* init struct videobuf_dvb */ - fe->dvb.name = dev->core->name; - } - - err = dvb_register(dev); - if (err) - /* frontends/adapter de-allocated in dvb_register */ - printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n", - core->name, err); - return err; -fail_probe: - videobuf_dvb_dealloc_frontends(&core->dvbdev->frontends); -fail_core: - return err; -} - -static int cx8802_dvb_remove(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - struct cx8802_dev *dev = drv->core->dvbdev; - - dprintk( 1, "%s\n", __func__); - - videobuf_dvb_unregister_bus(&dev->frontends); - - vp3054_i2c_remove(dev); - - core->gate_ctrl = NULL; - - return 0; -} - -static struct cx8802_driver cx8802_dvb_driver = { - .type_id = CX88_MPEG_DVB, - .hw_access = CX8802_DRVCTL_SHARED, - .probe = cx8802_dvb_probe, - .remove = cx8802_dvb_remove, - .advise_acquire = cx8802_dvb_advise_acquire, - .advise_release = cx8802_dvb_advise_release, -}; - -static int __init dvb_init(void) -{ - printk(KERN_INFO "cx88/2: cx2388x dvb driver version %s loaded\n", - CX88_VERSION); - return cx8802_register_driver(&cx8802_dvb_driver); -} - -static void __exit dvb_fini(void) -{ - cx8802_unregister_driver(&cx8802_dvb_driver); -} - -module_init(dvb_init); -module_exit(dvb_fini); diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c deleted file mode 100644 index de0f1af74e41..000000000000 --- a/drivers/media/video/cx88/cx88-i2c.c +++ /dev/null @@ -1,184 +0,0 @@ - -/* - - cx88-i2c.c -- all the i2c code is here - - Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) - (c) 2002 Yurij Sysoev <yurij@naturesoft.net> - (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org> - - (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org> - - Multituner support and i2c address binding - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include <linux/module.h> -#include <linux/init.h> - -#include <asm/io.h> - -#include "cx88.h" -#include <media/v4l2-common.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"); - -static unsigned int i2c_udelay = 5; -module_param(i2c_udelay, int, 0644); -MODULE_PARM_DESC(i2c_udelay,"i2c delay at insmod time, in usecs " - "(should be 5 or higher). Lower value means higher bus speed."); - -#define dprintk(level,fmt, arg...) if (i2c_debug >= level) \ - printk(KERN_DEBUG "%s: " fmt, core->name , ## arg) - -/* ----------------------------------------------------------------------- */ - -static void cx8800_bit_setscl(void *data, int state) -{ - struct cx88_core *core = data; - - if (state) - core->i2c_state |= 0x02; - else - core->i2c_state &= ~0x02; - cx_write(MO_I2C, core->i2c_state); - cx_read(MO_I2C); -} - -static void cx8800_bit_setsda(void *data, int state) -{ - struct cx88_core *core = data; - - if (state) - core->i2c_state |= 0x01; - else - core->i2c_state &= ~0x01; - cx_write(MO_I2C, core->i2c_state); - cx_read(MO_I2C); -} - -static int cx8800_bit_getscl(void *data) -{ - struct cx88_core *core = data; - u32 state; - - state = cx_read(MO_I2C); - return state & 0x02 ? 1 : 0; -} - -static int cx8800_bit_getsda(void *data) -{ - struct cx88_core *core = data; - u32 state; - - state = cx_read(MO_I2C); - return state & 0x01; -} - -/* ----------------------------------------------------------------------- */ - -static const struct i2c_algo_bit_data cx8800_i2c_algo_template = { - .setsda = cx8800_bit_setsda, - .setscl = cx8800_bit_setscl, - .getsda = cx8800_bit_getsda, - .getscl = cx8800_bit_getscl, - .udelay = 16, - .timeout = 200, -}; - -/* ----------------------------------------------------------------------- */ - -static const char * const i2c_devs[128] = { - [ 0x1c >> 1 ] = "lgdt330x", - [ 0x86 >> 1 ] = "tda9887/cx22702", - [ 0xa0 >> 1 ] = "eeprom", - [ 0xc0 >> 1 ] = "tuner (analog)", - [ 0xc2 >> 1 ] = "tuner (analog/dvb)", - [ 0xc8 >> 1 ] = "xc5000", -}; - -static void do_i2c_scan(const char *name, struct i2c_client *c) -{ - unsigned char buf; - int i,rc; - - for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { - c->addr = i; - rc = i2c_master_recv(c,&buf,0); - if (rc < 0) - continue; - printk("%s: i2c scan: found device @ 0x%x [%s]\n", - name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); - } -} - -/* init + register i2c adapter */ -int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) -{ - /* Prevents usage of invalid delay values */ - if (i2c_udelay<5) - i2c_udelay=5; - - memcpy(&core->i2c_algo, &cx8800_i2c_algo_template, - sizeof(core->i2c_algo)); - - - core->i2c_adap.dev.parent = &pci->dev; - strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name)); - core->i2c_adap.owner = THIS_MODULE; - core->i2c_algo.udelay = i2c_udelay; - core->i2c_algo.data = core; - i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev); - core->i2c_adap.algo_data = &core->i2c_algo; - core->i2c_client.adapter = &core->i2c_adap; - strlcpy(core->i2c_client.name, "cx88xx internal", I2C_NAME_SIZE); - - cx8800_bit_setscl(core,1); - cx8800_bit_setsda(core,1); - - core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap); - if (0 == core->i2c_rc) { - static u8 tuner_data[] = - { 0x0b, 0xdc, 0x86, 0x52 }; - static struct i2c_msg tuner_msg = - { .flags = 0, .addr = 0xc2 >> 1, .buf = tuner_data, .len = 4 }; - - dprintk(1, "i2c register ok\n"); - switch( core->boardnr ) { - case CX88_BOARD_HAUPPAUGE_HVR1300: - case CX88_BOARD_HAUPPAUGE_HVR3000: - case CX88_BOARD_HAUPPAUGE_HVR4000: - printk("%s: i2c init: enabling analog demod on HVR1300/3000/4000 tuner\n", - core->name); - i2c_transfer(core->i2c_client.adapter, &tuner_msg, 1); - break; - default: - break; - } - if (i2c_scan) - do_i2c_scan(core->name,&core->i2c_client); - } else - printk("%s: i2c register FAILED\n", core->name); - - return core->i2c_rc; -} diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c deleted file mode 100644 index ebf448c48ca3..000000000000 --- a/drivers/media/video/cx88/cx88-input.c +++ /dev/null @@ -1,635 +0,0 @@ -/* - * - * Device driver for GPIO attached remote control interfaces - * on Conexant 2388x based TV/DVB cards. - * - * Copyright (c) 2003 Pavel Machek - * Copyright (c) 2004 Gerd Knorr - * Copyright (c) 2004, 2005 Chris Pascoe - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/init.h> -#include <linux/hrtimer.h> -#include <linux/pci.h> -#include <linux/slab.h> -#include <linux/module.h> - -#include "cx88.h" -#include <media/rc-core.h> - -#define MODULE_NAME "cx88xx" - -/* ---------------------------------------------------------------------- */ - -struct cx88_IR { - struct cx88_core *core; - struct rc_dev *dev; - - int users; - - char name[32]; - char phys[32]; - - /* sample from gpio pin 16 */ - u32 sampling; - - /* poll external decoder */ - int polling; - struct hrtimer timer; - u32 gpio_addr; - u32 last_gpio; - u32 mask_keycode; - u32 mask_keydown; - u32 mask_keyup; -}; - -static unsigned ir_samplerate = 4; -module_param(ir_samplerate, uint, 0444); -MODULE_PARM_DESC(ir_samplerate, "IR samplerate in kHz, 1 - 20, default 4"); - -static int ir_debug; -module_param(ir_debug, int, 0644); /* debug level [IR] */ -MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); - -#define ir_dprintk(fmt, arg...) if (ir_debug) \ - printk(KERN_DEBUG "%s IR: " fmt , ir->core->name , ##arg) - -#define dprintk(fmt, arg...) if (ir_debug) \ - printk(KERN_DEBUG "cx88 IR: " fmt , ##arg) - -/* ---------------------------------------------------------------------- */ - -static void cx88_ir_handle_key(struct cx88_IR *ir) -{ - struct cx88_core *core = ir->core; - u32 gpio, data, auxgpio; - - /* read gpio value */ - gpio = cx_read(ir->gpio_addr); - switch (core->boardnr) { - case CX88_BOARD_NPGTECH_REALTV_TOP10FM: - /* This board apparently uses a combination of 2 GPIO - to represent the keys. Additionally, the second GPIO - can be used for parity. - - Example: - - for key "5" - gpio = 0x758, auxgpio = 0xe5 or 0xf5 - for key "Power" - gpio = 0x758, auxgpio = 0xed or 0xfd - */ - - auxgpio = cx_read(MO_GP1_IO); - /* Take out the parity part */ - gpio=(gpio & 0x7fd) + (auxgpio & 0xef); - break; - case CX88_BOARD_WINFAST_DTV1000: - case CX88_BOARD_WINFAST_DTV1800H: - case CX88_BOARD_WINFAST_DTV1800H_XC4000: - case CX88_BOARD_WINFAST_DTV2000H_PLUS: - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36: - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43: - gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900); - auxgpio = gpio; - break; - default: - auxgpio = gpio; - } - if (ir->polling) { - if (ir->last_gpio == auxgpio) - return; - ir->last_gpio = auxgpio; - } - - /* extract data */ - data = ir_extract_bits(gpio, ir->mask_keycode); - ir_dprintk("irq gpio=0x%x code=%d | %s%s%s\n", - gpio, data, - ir->polling ? "poll" : "irq", - (gpio & ir->mask_keydown) ? " down" : "", - (gpio & ir->mask_keyup) ? " up" : ""); - - if (ir->core->boardnr == CX88_BOARD_NORWOOD_MICRO) { - u32 gpio_key = cx_read(MO_GP0_IO); - - data = (data << 4) | ((gpio_key & 0xf0) >> 4); - - rc_keydown(ir->dev, data, 0); - - } else if (ir->mask_keydown) { - /* bit set on keydown */ - if (gpio & ir->mask_keydown) - rc_keydown_notimeout(ir->dev, data, 0); - else - rc_keyup(ir->dev); - - } else if (ir->mask_keyup) { - /* bit cleared on keydown */ - if (0 == (gpio & ir->mask_keyup)) - rc_keydown_notimeout(ir->dev, data, 0); - else - rc_keyup(ir->dev); - - } else { - /* can't distinguish keydown/up :-/ */ - rc_keydown_notimeout(ir->dev, data, 0); - rc_keyup(ir->dev); - } -} - -static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer) -{ - unsigned long missed; - struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer); - - cx88_ir_handle_key(ir); - missed = hrtimer_forward_now(&ir->timer, - ktime_set(0, ir->polling * 1000000)); - if (missed > 1) - ir_dprintk("Missed ticks %ld\n", missed - 1); - - return HRTIMER_RESTART; -} - -static int __cx88_ir_start(void *priv) -{ - struct cx88_core *core = priv; - struct cx88_IR *ir; - - if (!core || !core->ir) - return -EINVAL; - - ir = core->ir; - - if (ir->polling) { - hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - ir->timer.function = cx88_ir_work; - hrtimer_start(&ir->timer, - ktime_set(0, ir->polling * 1000000), - HRTIMER_MODE_REL); - } - if (ir->sampling) { - core->pci_irqmask |= PCI_INT_IR_SMPINT; - cx_write(MO_DDS_IO, 0x33F286 * ir_samplerate); /* samplerate */ - cx_write(MO_DDSCFG_IO, 0x5); /* enable */ - } - return 0; -} - -static void __cx88_ir_stop(void *priv) -{ - struct cx88_core *core = priv; - struct cx88_IR *ir; - - if (!core || !core->ir) - return; - - ir = core->ir; - if (ir->sampling) { - cx_write(MO_DDSCFG_IO, 0x0); - core->pci_irqmask &= ~PCI_INT_IR_SMPINT; - } - - if (ir->polling) - hrtimer_cancel(&ir->timer); -} - -int cx88_ir_start(struct cx88_core *core) -{ - if (core->ir->users) - return __cx88_ir_start(core); - - return 0; -} - -void cx88_ir_stop(struct cx88_core *core) -{ - if (core->ir->users) - __cx88_ir_stop(core); -} - -static int cx88_ir_open(struct rc_dev *rc) -{ - struct cx88_core *core = rc->priv; - - core->ir->users++; - return __cx88_ir_start(core); -} - -static void cx88_ir_close(struct rc_dev *rc) -{ - struct cx88_core *core = rc->priv; - - core->ir->users--; - if (!core->ir->users) - __cx88_ir_stop(core); -} - -/* ---------------------------------------------------------------------- */ - -int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) -{ - struct cx88_IR *ir; - struct rc_dev *dev; - char *ir_codes = NULL; - u64 rc_type = RC_TYPE_OTHER; - int err = -ENOMEM; - u32 hardware_mask = 0; /* For devices with a hardware mask, when - * used with a full-code IR table - */ - - ir = kzalloc(sizeof(*ir), GFP_KERNEL); - dev = rc_allocate_device(); - if (!ir || !dev) - goto err_out_free; - - ir->dev = dev; - - /* detect & configure */ - switch (core->boardnr) { - case CX88_BOARD_DNTV_LIVE_DVB_T: - case CX88_BOARD_KWORLD_DVB_T: - case CX88_BOARD_KWORLD_DVB_T_CX22702: - ir_codes = RC_MAP_DNTV_LIVE_DVB_T; - ir->gpio_addr = MO_GP1_IO; - ir->mask_keycode = 0x1f; - ir->mask_keyup = 0x60; - ir->polling = 50; /* ms */ - break; - case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: - ir_codes = RC_MAP_CINERGY_1400; - ir->sampling = 0xeb04; /* address */ - break; - case CX88_BOARD_HAUPPAUGE: - case CX88_BOARD_HAUPPAUGE_DVB_T1: - case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: - case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: - case CX88_BOARD_HAUPPAUGE_HVR1100: - case CX88_BOARD_HAUPPAUGE_HVR3000: - case CX88_BOARD_HAUPPAUGE_HVR4000: - case CX88_BOARD_HAUPPAUGE_HVR4000LITE: - case CX88_BOARD_PCHDTV_HD3000: - case CX88_BOARD_PCHDTV_HD5500: - case CX88_BOARD_HAUPPAUGE_IRONLY: - ir_codes = RC_MAP_HAUPPAUGE; - ir->sampling = 1; - break; - case CX88_BOARD_WINFAST_DTV2000H: - case CX88_BOARD_WINFAST_DTV2000H_J: - case CX88_BOARD_WINFAST_DTV1800H: - case CX88_BOARD_WINFAST_DTV1800H_XC4000: - case CX88_BOARD_WINFAST_DTV2000H_PLUS: - ir_codes = RC_MAP_WINFAST; - ir->gpio_addr = MO_GP0_IO; - ir->mask_keycode = 0x8f8; - ir->mask_keyup = 0x100; - ir->polling = 50; /* ms */ - break; - case CX88_BOARD_WINFAST2000XP_EXPERT: - case CX88_BOARD_WINFAST_DTV1000: - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36: - case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43: - ir_codes = RC_MAP_WINFAST; - ir->gpio_addr = MO_GP0_IO; - ir->mask_keycode = 0x8f8; - ir->mask_keyup = 0x100; - ir->polling = 1; /* ms */ - break; - case CX88_BOARD_IODATA_GVBCTV7E: - ir_codes = RC_MAP_IODATA_BCTV7E; - ir->gpio_addr = MO_GP0_IO; - ir->mask_keycode = 0xfd; - ir->mask_keydown = 0x02; - ir->polling = 5; /* ms */ - break; - case CX88_BOARD_PROLINK_PLAYTVPVR: - case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO: - /* - * It seems that this hardware is paired with NEC extended - * address 0x866b. So, unfortunately, its usage with other - * IR's with different address won't work. Still, there are - * other IR's from the same manufacturer that works, like the - * 002-T mini RC, provided with newer PV hardware - */ - ir_codes = RC_MAP_PIXELVIEW_MK12; - ir->gpio_addr = MO_GP1_IO; - ir->mask_keyup = 0x80; - ir->polling = 10; /* ms */ - hardware_mask = 0x3f; /* Hardware returns only 6 bits from command part */ - break; - case CX88_BOARD_PROLINK_PV_8000GT: - case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME: - ir_codes = RC_MAP_PIXELVIEW_NEW; - ir->gpio_addr = MO_GP1_IO; - ir->mask_keycode = 0x3f; - ir->mask_keyup = 0x80; - ir->polling = 1; /* ms */ - break; - case CX88_BOARD_KWORLD_LTV883: - ir_codes = RC_MAP_PIXELVIEW; - ir->gpio_addr = MO_GP1_IO; - ir->mask_keycode = 0x1f; - ir->mask_keyup = 0x60; - ir->polling = 1; /* ms */ - break; - case CX88_BOARD_ADSTECH_DVB_T_PCI: - ir_codes = RC_MAP_ADSTECH_DVB_T_PCI; - ir->gpio_addr = MO_GP1_IO; - ir->mask_keycode = 0xbf; - ir->mask_keyup = 0x40; - ir->polling = 50; /* ms */ - break; - case CX88_BOARD_MSI_TVANYWHERE_MASTER: - ir_codes = RC_MAP_MSI_TVANYWHERE; - ir->gpio_addr = MO_GP1_IO; - ir->mask_keycode = 0x1f; - ir->mask_keyup = 0x40; - ir->polling = 1; /* ms */ - break; - case CX88_BOARD_AVERTV_303: - case CX88_BOARD_AVERTV_STUDIO_303: - ir_codes = RC_MAP_AVERTV_303; - ir->gpio_addr = MO_GP2_IO; - ir->mask_keycode = 0xfb; - ir->mask_keydown = 0x02; - ir->polling = 50; /* ms */ - break; - case CX88_BOARD_OMICOM_SS4_PCI: - case CX88_BOARD_SATTRADE_ST4200: - case CX88_BOARD_TBS_8920: - case CX88_BOARD_TBS_8910: - case CX88_BOARD_PROF_7300: - case CX88_BOARD_PROF_7301: - case CX88_BOARD_PROF_6200: - ir_codes = RC_MAP_TBS_NEC; - ir->sampling = 0xff00; /* address */ - break; - case CX88_BOARD_TEVII_S464: - case CX88_BOARD_TEVII_S460: - case CX88_BOARD_TEVII_S420: - ir_codes = RC_MAP_TEVII_NEC; - ir->sampling = 0xff00; /* address */ - break; - case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: - ir_codes = RC_MAP_DNTV_LIVE_DVBT_PRO; - ir->sampling = 0xff00; /* address */ - break; - case CX88_BOARD_NORWOOD_MICRO: - ir_codes = RC_MAP_NORWOOD; - ir->gpio_addr = MO_GP1_IO; - ir->mask_keycode = 0x0e; - ir->mask_keyup = 0x80; - ir->polling = 50; /* ms */ - break; - case CX88_BOARD_NPGTECH_REALTV_TOP10FM: - ir_codes = RC_MAP_NPGTECH; - ir->gpio_addr = MO_GP0_IO; - ir->mask_keycode = 0xfa; - ir->polling = 50; /* ms */ - break; - case CX88_BOARD_PINNACLE_PCTV_HD_800i: - ir_codes = RC_MAP_PINNACLE_PCTV_HD; - ir->sampling = 1; - break; - case CX88_BOARD_POWERCOLOR_REAL_ANGEL: - ir_codes = RC_MAP_POWERCOLOR_REAL_ANGEL; - ir->gpio_addr = MO_GP2_IO; - ir->mask_keycode = 0x7e; - ir->polling = 100; /* ms */ - break; - case CX88_BOARD_TWINHAN_VP1027_DVBS: - ir_codes = RC_MAP_TWINHAN_VP1027_DVBS; - rc_type = RC_TYPE_NEC; - ir->sampling = 0xff00; /* address */ - break; - } - - if (!ir_codes) { - err = -ENODEV; - goto err_out_free; - } - - /* - * The usage of mask_keycode were very convenient, due to several - * reasons. Among others, the scancode tables were using the scancode - * as the index elements. So, the less bits it was used, the smaller - * the table were stored. After the input changes, the better is to use - * the full scancodes, since it allows replacing the IR remote by - * another one. Unfortunately, there are still some hardware, like - * Pixelview Ultra Pro, where only part of the scancode is sent via - * GPIO. So, there's no way to get the full scancode. Due to that, - * hardware_mask were introduced here: it represents those hardware - * that has such limits. - */ - if (hardware_mask && !ir->mask_keycode) - ir->mask_keycode = hardware_mask; - - /* init input device */ - snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); - snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); - - dev->input_name = ir->name; - dev->input_phys = ir->phys; - dev->input_id.bustype = BUS_PCI; - dev->input_id.version = 1; - if (pci->subsystem_vendor) { - dev->input_id.vendor = pci->subsystem_vendor; - dev->input_id.product = pci->subsystem_device; - } else { - dev->input_id.vendor = pci->vendor; - dev->input_id.product = pci->device; - } - dev->dev.parent = &pci->dev; - dev->map_name = ir_codes; - dev->driver_name = MODULE_NAME; - dev->priv = core; - dev->open = cx88_ir_open; - dev->close = cx88_ir_close; - dev->scanmask = hardware_mask; - - if (ir->sampling) { - dev->driver_type = RC_DRIVER_IR_RAW; - dev->timeout = 10 * 1000 * 1000; /* 10 ms */ - } else { - dev->driver_type = RC_DRIVER_SCANCODE; - dev->allowed_protos = rc_type; - } - - ir->core = core; - core->ir = ir; - - /* all done */ - err = rc_register_device(dev); - if (err) - goto err_out_free; - - return 0; - -err_out_free: - rc_free_device(dev); - core->ir = NULL; - kfree(ir); - return err; -} - -int cx88_ir_fini(struct cx88_core *core) -{ - struct cx88_IR *ir = core->ir; - - /* skip detach on non attached boards */ - if (NULL == ir) - return 0; - - cx88_ir_stop(core); - rc_unregister_device(ir->dev); - kfree(ir); - - /* done */ - core->ir = NULL; - return 0; -} - -/* ---------------------------------------------------------------------- */ - -void cx88_ir_irq(struct cx88_core *core) -{ - struct cx88_IR *ir = core->ir; - u32 samples; - unsigned todo, bits; - struct ir_raw_event ev; - - if (!ir || !ir->sampling) - return; - - /* - * Samples are stored in a 32 bit register, oldest sample in - * the msb. A set bit represents space and an unset bit - * represents a pulse. - */ - samples = cx_read(MO_SAMPLE_IO); - - if (samples == 0xff && ir->dev->idle) - return; - - init_ir_raw_event(&ev); - for (todo = 32; todo > 0; todo -= bits) { - ev.pulse = samples & 0x80000000 ? false : true; - bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples)); - ev.duration = (bits * (NSEC_PER_SEC / 1000)) / ir_samplerate; - ir_raw_event_store_with_filter(ir->dev, &ev); - samples <<= bits; - } - ir_raw_event_handle(ir->dev); -} - -static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) -{ - int flags, code; - - /* poll IR chip */ - flags = i2c_smbus_read_byte_data(ir->c, 0x10); - if (flags < 0) { - dprintk("read error\n"); - return 0; - } - /* key pressed ? */ - if (0 == (flags & 0x80)) - return 0; - - /* read actual key code */ - code = i2c_smbus_read_byte_data(ir->c, 0x00); - if (code < 0) { - dprintk("read error\n"); - return 0; - } - - dprintk("IR Key/Flags: (0x%02x/0x%02x)\n", - code & 0xff, flags & 0xff); - - *ir_key = code & 0xff; - *ir_raw = code; - return 1; -} - -void cx88_i2c_init_ir(struct cx88_core *core) -{ - struct i2c_board_info info; - const unsigned short default_addr_list[] = { - 0x18, 0x6b, 0x71, - I2C_CLIENT_END - }; - const unsigned short pvr2000_addr_list[] = { - 0x18, 0x1a, - I2C_CLIENT_END - }; - const unsigned short *addr_list = default_addr_list; - const unsigned short *addrp; - /* Instantiate the IR receiver device, if present */ - if (0 != core->i2c_rc) - return; - - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - - switch (core->boardnr) { - case CX88_BOARD_LEADTEK_PVR2000: - addr_list = pvr2000_addr_list; - core->init_data.name = "cx88 Leadtek PVR 2000 remote"; - core->init_data.type = RC_TYPE_UNKNOWN; - core->init_data.get_key = get_key_pvr2000; - core->init_data.ir_codes = RC_MAP_EMPTY; - break; - } - - /* - * We can't call i2c_new_probed_device() because it uses - * quick writes for probing and at least some RC receiver - * devices only reply to reads. - * Also, Hauppauge XVR needs to be specified, as address 0x71 - * conflicts with another remote type used with saa7134 - */ - for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) { - info.platform_data = NULL; - memset(&core->init_data, 0, sizeof(core->init_data)); - - if (*addrp == 0x71) { - /* Hauppauge XVR */ - core->init_data.name = "cx88 Hauppauge XVR remote"; - core->init_data.ir_codes = RC_MAP_HAUPPAUGE; - core->init_data.type = RC_TYPE_RC5; - core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - - info.platform_data = &core->init_data; - } - if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0, - I2C_SMBUS_READ, 0, - I2C_SMBUS_QUICK, NULL) >= 0) { - info.addr = *addrp; - i2c_new_device(&core->i2c_adap, &info); - break; - } - } -} - -/* ---------------------------------------------------------------------- */ - -MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe"); -MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls"); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c deleted file mode 100644 index cd5386ee210c..000000000000 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ /dev/null @@ -1,929 +0,0 @@ -/* - * - * Support for the mpeg transport stream transfers - * PCI function #2 of the cx2388x. - * - * (c) 2004 Jelle Foks <jelle@foks.us> - * (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au> - * (c) 2004 Gerd Knorr <kraxel@bytesex.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/dma-mapping.h> -#include <linux/interrupt.h> -#include <asm/delay.h> - -#include "cx88.h" - -/* ------------------------------------------------------------------ */ - -MODULE_DESCRIPTION("mpeg driver for cx2388x based TV cards"); -MODULE_AUTHOR("Jelle Foks <jelle@foks.us>"); -MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); -MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(CX88_VERSION); - -static unsigned int debug; -module_param(debug,int,0644); -MODULE_PARM_DESC(debug,"enable debug messages [mpeg]"); - -#define dprintk(level,fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg) - -#define mpeg_dbg(level,fmt, arg...) if (debug >= level) \ - printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg) - -#if defined(CONFIG_MODULES) && defined(MODULE) -static void request_module_async(struct work_struct *work) -{ - struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk); - - if (dev->core->board.mpeg & CX88_MPEG_DVB) - request_module("cx88-dvb"); - if (dev->core->board.mpeg & CX88_MPEG_BLACKBIRD) - request_module("cx88-blackbird"); -} - -static void request_modules(struct cx8802_dev *dev) -{ - INIT_WORK(&dev->request_module_wk, request_module_async); - schedule_work(&dev->request_module_wk); -} - -static void flush_request_modules(struct cx8802_dev *dev) -{ - flush_work_sync(&dev->request_module_wk); -} -#else -#define request_modules(dev) -#define flush_request_modules(dev) -#endif /* CONFIG_MODULES */ - - -static LIST_HEAD(cx8802_devlist); -static DEFINE_MUTEX(cx8802_mutex); -/* ------------------------------------------------------------------ */ - -static int cx8802_start_dma(struct cx8802_dev *dev, - struct cx88_dmaqueue *q, - struct cx88_buffer *buf) -{ - struct cx88_core *core = dev->core; - - dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n", - buf->vb.width, buf->vb.height, buf->vb.field); - - /* setup fifo + format */ - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], - dev->ts_packet_size, buf->risc.dma); - - /* write TS length to chip */ - cx_write(MO_TS_LNGTH, buf->vb.width); - - /* FIXME: this needs a review. - * also: move to cx88-blackbird + cx88-dvb source files? */ - - dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id); - - if ( (core->active_type_id == CX88_MPEG_DVB) && - (core->board.mpeg & CX88_MPEG_DVB) ) { - - dprintk( 1, "cx8802_start_dma doing .dvb\n"); - /* negedge driven & software reset */ - cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl); - udelay(100); - cx_write(MO_PINMUX_IO, 0x00); - cx_write(TS_HW_SOP_CNTRL, 0x47<<16|188<<4|0x01); - switch (core->boardnr) { - case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: - case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: - case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: - case CX88_BOARD_PCHDTV_HD5500: - cx_write(TS_SOP_STAT, 1<<13); - break; - case CX88_BOARD_SAMSUNG_SMT_7020: - cx_write(TS_SOP_STAT, 0x00); - break; - case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: - case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: - cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ - udelay(100); - break; - case CX88_BOARD_HAUPPAUGE_HVR1300: - /* Enable MPEG parallel IO and video signal pins */ - cx_write(MO_PINMUX_IO, 0x88); - cx_write(TS_SOP_STAT, 0); - cx_write(TS_VALERR_CNTRL, 0); - break; - case CX88_BOARD_PINNACLE_PCTV_HD_800i: - /* Enable MPEG parallel IO and video signal pins */ - cx_write(MO_PINMUX_IO, 0x88); - cx_write(TS_HW_SOP_CNTRL, (0x47 << 16) | (188 << 4)); - dev->ts_gen_cntrl = 5; - cx_write(TS_SOP_STAT, 0); - cx_write(TS_VALERR_CNTRL, 0); - udelay(100); - break; - default: - cx_write(TS_SOP_STAT, 0x00); - break; - } - cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl); - udelay(100); - } else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) && - (core->board.mpeg & CX88_MPEG_BLACKBIRD) ) { - dprintk( 1, "cx8802_start_dma doing .blackbird\n"); - cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */ - - cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */ - udelay(100); - - cx_write(TS_HW_SOP_CNTRL, 0x408); /* mpeg start byte */ - cx_write(TS_VALERR_CNTRL, 0x2000); - - cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */ - udelay(100); - } else { - printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __func__, - core->board.mpeg ); - return -EINVAL; - } - - /* reset counter */ - cx_write(MO_TS_GPCNTRL, GP_COUNT_CONTROL_RESET); - q->count = 1; - - /* enable irqs */ - dprintk( 1, "setting the interrupt mask\n" ); - cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_TSINT); - cx_set(MO_TS_INTMSK, 0x1f0011); - - /* start dma */ - cx_set(MO_DEV_CNTRL2, (1<<5)); - cx_set(MO_TS_DMACNTRL, 0x11); - return 0; -} - -static int cx8802_stop_dma(struct cx8802_dev *dev) -{ - struct cx88_core *core = dev->core; - dprintk( 1, "cx8802_stop_dma\n" ); - - /* stop dma */ - cx_clear(MO_TS_DMACNTRL, 0x11); - - /* disable irqs */ - cx_clear(MO_PCI_INTMSK, PCI_INT_TSINT); - cx_clear(MO_TS_INTMSK, 0x1f0011); - - /* Reset the controller */ - cx_write(TS_GEN_CNTRL, 0xcd); - return 0; -} - -static int cx8802_restart_queue(struct cx8802_dev *dev, - struct cx88_dmaqueue *q) -{ - struct cx88_buffer *buf; - - dprintk( 1, "cx8802_restart_queue\n" ); - if (list_empty(&q->active)) - { - struct cx88_buffer *prev; - prev = NULL; - - dprintk(1, "cx8802_restart_queue: queue is empty\n" ); - - for (;;) { - if (list_empty(&q->queued)) - return 0; - buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); - if (NULL == prev) { - list_del(&buf->vb.queue); - list_add_tail(&buf->vb.queue,&q->active); - cx8802_start_dma(dev, q, buf); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(1,"[%p/%d] restart_queue - first active\n", - buf,buf->vb.i); - - } else if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_del(&buf->vb.queue); - list_add_tail(&buf->vb.queue,&q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - dprintk(1,"[%p/%d] restart_queue - move to active\n", - buf,buf->vb.i); - } else { - return 0; - } - prev = buf; - } - return 0; - } - - buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); - dprintk(2,"restart_queue [%p/%d]: restart dma\n", - buf, buf->vb.i); - cx8802_start_dma(dev, q, buf); - list_for_each_entry(buf, &q->active, vb.queue) - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - return 0; -} - -/* ------------------------------------------------------------------ */ - -int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev, - struct cx88_buffer *buf, enum v4l2_field field) -{ - int size = dev->ts_packet_size * dev->ts_packet_count; - struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); - int rc; - - dprintk(1, "%s: %p\n", __func__, buf); - if (0 != buf->vb.baddr && buf->vb.bsize < size) - return -EINVAL; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - buf->vb.width = dev->ts_packet_size; - buf->vb.height = dev->ts_packet_count; - buf->vb.size = size; - buf->vb.field = field /*V4L2_FIELD_TOP*/; - - if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) - goto fail; - cx88_risc_databuffer(dev->pci, &buf->risc, - dma->sglist, - buf->vb.width, buf->vb.height, 0); - } - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - - fail: - cx88_free_buffer(q,buf); - return rc; -} - -void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) -{ - struct cx88_buffer *prev; - struct cx88_dmaqueue *cx88q = &dev->mpegq; - - dprintk( 1, "cx8802_buf_queue\n" ); - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma); - - if (list_empty(&cx88q->active)) { - dprintk( 1, "queue is empty - first active\n" ); - list_add_tail(&buf->vb.queue,&cx88q->active); - cx8802_start_dma(dev, cx88q, buf); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = cx88q->count++; - mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(1,"[%p/%d] %s - first active\n", - buf, buf->vb.i, __func__); - - } else { - dprintk( 1, "queue is not empty - append to active\n" ); - prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue); - list_add_tail(&buf->vb.queue,&cx88q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = cx88q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - dprintk( 1, "[%p/%d] %s - append to active\n", - buf, buf->vb.i, __func__); - } -} - -/* ----------------------------------------------------------- */ - -static void do_cancel_buffers(struct cx8802_dev *dev, const char *reason, int restart) -{ - struct cx88_dmaqueue *q = &dev->mpegq; - struct cx88_buffer *buf; - unsigned long flags; - - spin_lock_irqsave(&dev->slock,flags); - while (!list_empty(&q->active)) { - buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); - list_del(&buf->vb.queue); - buf->vb.state = VIDEOBUF_ERROR; - wake_up(&buf->vb.done); - dprintk(1,"[%p/%d] %s - dma=0x%08lx\n", - buf, buf->vb.i, reason, (unsigned long)buf->risc.dma); - } - if (restart) - { - dprintk(1, "restarting queue\n" ); - cx8802_restart_queue(dev,q); - } - spin_unlock_irqrestore(&dev->slock,flags); -} - -void cx8802_cancel_buffers(struct cx8802_dev *dev) -{ - struct cx88_dmaqueue *q = &dev->mpegq; - - dprintk( 1, "cx8802_cancel_buffers" ); - del_timer_sync(&q->timeout); - cx8802_stop_dma(dev); - do_cancel_buffers(dev,"cancel",0); -} - -static void cx8802_timeout(unsigned long data) -{ - struct cx8802_dev *dev = (struct cx8802_dev*)data; - - dprintk(1, "%s\n",__func__); - - if (debug) - cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]); - cx8802_stop_dma(dev); - do_cancel_buffers(dev,"timeout",1); -} - -static const char * cx88_mpeg_irqs[32] = { - "ts_risci1", NULL, NULL, NULL, - "ts_risci2", NULL, NULL, NULL, - "ts_oflow", NULL, NULL, NULL, - "ts_sync", NULL, NULL, NULL, - "opc_err", "par_err", "rip_err", "pci_abort", - "ts_err?", -}; - -static void cx8802_mpeg_irq(struct cx8802_dev *dev) -{ - struct cx88_core *core = dev->core; - u32 status, mask, count; - - dprintk( 1, "cx8802_mpeg_irq\n" ); - status = cx_read(MO_TS_INTSTAT); - mask = cx_read(MO_TS_INTMSK); - if (0 == (status & mask)) - return; - - cx_write(MO_TS_INTSTAT, status); - - if (debug || (status & mask & ~0xff)) - cx88_print_irqbits(core->name, "irq mpeg ", - cx88_mpeg_irqs, ARRAY_SIZE(cx88_mpeg_irqs), - status, mask); - - /* risc op code error */ - if (status & (1 << 16)) { - printk(KERN_WARNING "%s: mpeg risc op code error\n",core->name); - cx_clear(MO_TS_DMACNTRL, 0x11); - cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]); - } - - /* risc1 y */ - if (status & 0x01) { - dprintk( 1, "wake up\n" ); - spin_lock(&dev->slock); - count = cx_read(MO_TS_GPCNT); - cx88_wakeup(dev->core, &dev->mpegq, count); - spin_unlock(&dev->slock); - } - - /* risc2 y */ - if (status & 0x10) { - spin_lock(&dev->slock); - cx8802_restart_queue(dev,&dev->mpegq); - spin_unlock(&dev->slock); - } - - /* other general errors */ - if (status & 0x1f0100) { - dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 ); - spin_lock(&dev->slock); - cx8802_stop_dma(dev); - cx8802_restart_queue(dev,&dev->mpegq); - spin_unlock(&dev->slock); - } -} - -#define MAX_IRQ_LOOP 10 - -static irqreturn_t cx8802_irq(int irq, void *dev_id) -{ - struct cx8802_dev *dev = dev_id; - struct cx88_core *core = dev->core; - u32 status; - int loop, handled = 0; - - for (loop = 0; loop < MAX_IRQ_LOOP; loop++) { - status = cx_read(MO_PCI_INTSTAT) & - (core->pci_irqmask | PCI_INT_TSINT); - if (0 == status) - goto out; - dprintk( 1, "cx8802_irq\n" ); - dprintk( 1, " loop: %d/%d\n", loop, MAX_IRQ_LOOP ); - dprintk( 1, " status: %d\n", status ); - handled = 1; - cx_write(MO_PCI_INTSTAT, status); - - if (status & core->pci_irqmask) - cx88_core_irq(core,status); - if (status & PCI_INT_TSINT) - cx8802_mpeg_irq(dev); - }; - if (MAX_IRQ_LOOP == loop) { - dprintk( 0, "clearing mask\n" ); - printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n", - core->name); - cx_write(MO_PCI_INTMSK,0); - } - - out: - return IRQ_RETVAL(handled); -} - -static int cx8802_init_common(struct cx8802_dev *dev) -{ - struct cx88_core *core = dev->core; - int err; - - /* pci init */ - if (pci_enable_device(dev->pci)) - return -EIO; - pci_set_master(dev->pci); - if (!pci_dma_supported(dev->pci,DMA_BIT_MASK(32))) { - printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name); - return -EIO; - } - - dev->pci_rev = dev->pci->revision; - pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER, &dev->pci_lat); - printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, " - "latency: %d, mmio: 0x%llx\n", dev->core->name, - pci_name(dev->pci), dev->pci_rev, dev->pci->irq, - dev->pci_lat,(unsigned long long)pci_resource_start(dev->pci,0)); - - /* initialize driver struct */ - spin_lock_init(&dev->slock); - - /* init dma queue */ - INIT_LIST_HEAD(&dev->mpegq.active); - INIT_LIST_HEAD(&dev->mpegq.queued); - dev->mpegq.timeout.function = cx8802_timeout; - dev->mpegq.timeout.data = (unsigned long)dev; - init_timer(&dev->mpegq.timeout); - cx88_risc_stopper(dev->pci,&dev->mpegq.stopper, - MO_TS_DMACNTRL,0x11,0x00); - - /* get irq */ - err = request_irq(dev->pci->irq, cx8802_irq, - IRQF_SHARED | IRQF_DISABLED, dev->core->name, dev); - if (err < 0) { - printk(KERN_ERR "%s: can't get IRQ %d\n", - dev->core->name, dev->pci->irq); - return err; - } - cx_set(MO_PCI_INTMSK, core->pci_irqmask); - - /* everything worked */ - pci_set_drvdata(dev->pci,dev); - return 0; -} - -static void cx8802_fini_common(struct cx8802_dev *dev) -{ - dprintk( 2, "cx8802_fini_common\n" ); - cx8802_stop_dma(dev); - pci_disable_device(dev->pci); - - /* unregister stuff */ - free_irq(dev->pci->irq, dev); - pci_set_drvdata(dev->pci, NULL); - - /* free memory */ - btcx_riscmem_free(dev->pci,&dev->mpegq.stopper); -} - -/* ----------------------------------------------------------- */ - -static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state) -{ - struct cx8802_dev *dev = pci_get_drvdata(pci_dev); - struct cx88_core *core = dev->core; - - /* stop mpeg dma */ - spin_lock(&dev->slock); - if (!list_empty(&dev->mpegq.active)) { - dprintk( 2, "suspend\n" ); - printk("%s: suspend mpeg\n", core->name); - cx8802_stop_dma(dev); - del_timer(&dev->mpegq.timeout); - } - spin_unlock(&dev->slock); - - /* FIXME -- shutdown device */ - cx88_shutdown(dev->core); - - pci_save_state(pci_dev); - if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) { - pci_disable_device(pci_dev); - dev->state.disabled = 1; - } - return 0; -} - -static int cx8802_resume_common(struct pci_dev *pci_dev) -{ - struct cx8802_dev *dev = pci_get_drvdata(pci_dev); - struct cx88_core *core = dev->core; - int err; - - if (dev->state.disabled) { - err=pci_enable_device(pci_dev); - if (err) { - printk(KERN_ERR "%s: can't enable device\n", - dev->core->name); - return err; - } - dev->state.disabled = 0; - } - err=pci_set_power_state(pci_dev, PCI_D0); - if (err) { - printk(KERN_ERR "%s: can't enable device\n", - dev->core->name); - pci_disable_device(pci_dev); - dev->state.disabled = 1; - - return err; - } - pci_restore_state(pci_dev); - - /* FIXME: re-initialize hardware */ - cx88_reset(dev->core); - - /* restart video+vbi capture */ - spin_lock(&dev->slock); - if (!list_empty(&dev->mpegq.active)) { - printk("%s: resume mpeg\n", core->name); - cx8802_restart_queue(dev,&dev->mpegq); - } - spin_unlock(&dev->slock); - - return 0; -} - -struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype) -{ - struct cx8802_driver *d; - - list_for_each_entry(d, &dev->drvlist, drvlist) - if (d->type_id == btype) - return d; - - return NULL; -} - -/* Driver asked for hardware access. */ -static int cx8802_request_acquire(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - unsigned int i; - - /* Fail a request for hardware if the device is busy. */ - if (core->active_type_id != CX88_BOARD_NONE && - core->active_type_id != drv->type_id) - return -EBUSY; - - if (drv->type_id == CX88_MPEG_DVB) { - /* When switching to DVB, always set the input to the tuner */ - core->last_analog_input = core->input; - core->input = 0; - for (i = 0; - i < (sizeof(core->board.input) / sizeof(struct cx88_input)); - i++) { - if (core->board.input[i].type == CX88_VMUX_DVB) { - core->input = i; - break; - } - } - } - - if (drv->advise_acquire) - { - core->active_ref++; - if (core->active_type_id == CX88_BOARD_NONE) { - core->active_type_id = drv->type_id; - drv->advise_acquire(drv); - } - - mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); - } - - return 0; -} - -/* Driver asked to release hardware. */ -static int cx8802_request_release(struct cx8802_driver *drv) -{ - struct cx88_core *core = drv->core; - - if (drv->advise_release && --core->active_ref == 0) - { - if (drv->type_id == CX88_MPEG_DVB) { - /* If the DVB driver is releasing, reset the input - state to the last configured analog input */ - core->input = core->last_analog_input; - } - - drv->advise_release(drv); - core->active_type_id = CX88_BOARD_NONE; - mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); - } - - return 0; -} - -static int cx8802_check_driver(struct cx8802_driver *drv) -{ - if (drv == NULL) - return -ENODEV; - - if ((drv->type_id != CX88_MPEG_DVB) && - (drv->type_id != CX88_MPEG_BLACKBIRD)) - return -EINVAL; - - if ((drv->hw_access != CX8802_DRVCTL_SHARED) && - (drv->hw_access != CX8802_DRVCTL_EXCLUSIVE)) - return -EINVAL; - - if ((drv->probe == NULL) || - (drv->remove == NULL) || - (drv->advise_acquire == NULL) || - (drv->advise_release == NULL)) - return -EINVAL; - - return 0; -} - -int cx8802_register_driver(struct cx8802_driver *drv) -{ - struct cx8802_dev *dev; - struct cx8802_driver *driver; - int err, i = 0; - - printk(KERN_INFO - "cx88/2: registering cx8802 driver, type: %s access: %s\n", - drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", - drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); - - if ((err = cx8802_check_driver(drv)) != 0) { - printk(KERN_ERR "cx88/2: cx8802_driver is invalid\n"); - return err; - } - - mutex_lock(&cx8802_mutex); - - list_for_each_entry(dev, &cx8802_devlist, devlist) { - printk(KERN_INFO - "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", - dev->core->name, dev->pci->subsystem_vendor, - dev->pci->subsystem_device, dev->core->board.name, - dev->core->boardnr); - - /* Bring up a new struct for each driver instance */ - driver = kzalloc(sizeof(*drv),GFP_KERNEL); - if (driver == NULL) { - err = -ENOMEM; - goto out; - } - - /* Snapshot of the driver registration data */ - drv->core = dev->core; - drv->suspend = cx8802_suspend_common; - drv->resume = cx8802_resume_common; - drv->request_acquire = cx8802_request_acquire; - drv->request_release = cx8802_request_release; - memcpy(driver, drv, sizeof(*driver)); - - mutex_lock(&drv->core->lock); - err = drv->probe(driver); - if (err == 0) { - i++; - list_add_tail(&driver->drvlist, &dev->drvlist); - } else { - printk(KERN_ERR - "%s/2: cx8802 probe failed, err = %d\n", - dev->core->name, err); - } - mutex_unlock(&drv->core->lock); - } - - err = i ? 0 : -ENODEV; -out: - mutex_unlock(&cx8802_mutex); - return err; -} - -int cx8802_unregister_driver(struct cx8802_driver *drv) -{ - struct cx8802_dev *dev; - struct cx8802_driver *d, *dtmp; - int err = 0; - - printk(KERN_INFO - "cx88/2: unregistering cx8802 driver, type: %s access: %s\n", - drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", - drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); - - mutex_lock(&cx8802_mutex); - - list_for_each_entry(dev, &cx8802_devlist, devlist) { - printk(KERN_INFO - "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", - dev->core->name, dev->pci->subsystem_vendor, - dev->pci->subsystem_device, dev->core->board.name, - dev->core->boardnr); - - mutex_lock(&dev->core->lock); - - list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) { - /* only unregister the correct driver type */ - if (d->type_id != drv->type_id) - continue; - - err = d->remove(d); - if (err == 0) { - list_del(&d->drvlist); - kfree(d); - } else - printk(KERN_ERR "%s/2: cx8802 driver remove " - "failed (%d)\n", dev->core->name, err); - } - - mutex_unlock(&dev->core->lock); - } - - mutex_unlock(&cx8802_mutex); - - return err; -} - -/* ----------------------------------------------------------- */ -static int __devinit cx8802_probe(struct pci_dev *pci_dev, - const struct pci_device_id *pci_id) -{ - struct cx8802_dev *dev; - struct cx88_core *core; - int err; - - /* general setup */ - core = cx88_core_get(pci_dev); - if (NULL == core) - return -EINVAL; - - printk("%s/2: cx2388x 8802 Driver Manager\n", core->name); - - err = -ENODEV; - if (!core->board.mpeg) - goto fail_core; - - err = -ENOMEM; - dev = kzalloc(sizeof(*dev),GFP_KERNEL); - if (NULL == dev) - goto fail_core; - dev->pci = pci_dev; - dev->core = core; - - /* Maintain a reference so cx88-video can query the 8802 device. */ - core->dvbdev = dev; - - err = cx8802_init_common(dev); - if (err != 0) - goto fail_free; - - INIT_LIST_HEAD(&dev->drvlist); - mutex_lock(&cx8802_mutex); - list_add_tail(&dev->devlist,&cx8802_devlist); - mutex_unlock(&cx8802_mutex); - - /* now autoload cx88-dvb or cx88-blackbird */ - request_modules(dev); - return 0; - - fail_free: - kfree(dev); - fail_core: - core->dvbdev = NULL; - cx88_core_put(core,pci_dev); - return err; -} - -static void __devexit cx8802_remove(struct pci_dev *pci_dev) -{ - struct cx8802_dev *dev; - - dev = pci_get_drvdata(pci_dev); - - dprintk( 1, "%s\n", __func__); - - flush_request_modules(dev); - - mutex_lock(&dev->core->lock); - - if (!list_empty(&dev->drvlist)) { - struct cx8802_driver *drv, *tmp; - int err; - - printk(KERN_WARNING "%s/2: Trying to remove cx8802 driver " - "while cx8802 sub-drivers still loaded?!\n", - dev->core->name); - - list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) { - err = drv->remove(drv); - if (err == 0) { - list_del(&drv->drvlist); - } else - printk(KERN_ERR "%s/2: cx8802 driver remove " - "failed (%d)\n", dev->core->name, err); - kfree(drv); - } - } - - mutex_unlock(&dev->core->lock); - - /* Destroy any 8802 reference. */ - dev->core->dvbdev = NULL; - - /* common */ - cx8802_fini_common(dev); - cx88_core_put(dev->core,dev->pci); - kfree(dev); -} - -static const struct pci_device_id cx8802_pci_tbl[] = { - { - .vendor = 0x14f1, - .device = 0x8802, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - },{ - /* --- end of list --- */ - } -}; -MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); - -static struct pci_driver cx8802_pci_driver = { - .name = "cx88-mpeg driver manager", - .id_table = cx8802_pci_tbl, - .probe = cx8802_probe, - .remove = __devexit_p(cx8802_remove), -}; - -static int __init cx8802_init(void) -{ - printk(KERN_INFO "cx88/2: cx2388x MPEG-TS Driver Manager version %s loaded\n", - CX88_VERSION); - return pci_register_driver(&cx8802_pci_driver); -} - -static void __exit cx8802_fini(void) -{ - pci_unregister_driver(&cx8802_pci_driver); -} - -module_init(cx8802_init); -module_exit(cx8802_fini); -EXPORT_SYMBOL(cx8802_buf_prepare); -EXPORT_SYMBOL(cx8802_buf_queue); -EXPORT_SYMBOL(cx8802_cancel_buffers); - -EXPORT_SYMBOL(cx8802_register_driver); -EXPORT_SYMBOL(cx8802_unregister_driver); -EXPORT_SYMBOL(cx8802_get_driver); -/* ----------------------------------------------------------- */ -/* - * Local variables: - * c-basic-offset: 8 - * End: - * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off - */ diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h deleted file mode 100644 index 2ec52d1cdea0..000000000000 --- a/drivers/media/video/cx88/cx88-reg.h +++ /dev/null @@ -1,836 +0,0 @@ -/* - - cx88x-hw.h - CX2388x register offsets - - Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - 2001 Michael Eskin - 2002 Yurij Sysoev <yurij@naturesoft.net> - 2003 Gerd Knorr <kraxel@bytesex.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _CX88_REG_H_ -#define _CX88_REG_H_ - -/* ---------------------------------------------------------------------- */ -/* PCI IDs and config space */ - -#ifndef PCI_VENDOR_ID_CONEXANT -# define PCI_VENDOR_ID_CONEXANT 0x14F1 -#endif -#ifndef PCI_DEVICE_ID_CX2300_VID -# define PCI_DEVICE_ID_CX2300_VID 0x8800 -#endif - -#define CX88X_DEVCTRL 0x40 -#define CX88X_EN_TBFX 0x02 -#define CX88X_EN_VSFX 0x04 - -/* ---------------------------------------------------------------------- */ -/* PCI controller registers */ - -/* Command and Status Register */ -#define F0_CMD_STAT_MM 0x2f0004 -#define F1_CMD_STAT_MM 0x2f0104 -#define F2_CMD_STAT_MM 0x2f0204 -#define F3_CMD_STAT_MM 0x2f0304 -#define F4_CMD_STAT_MM 0x2f0404 - -/* Device Control #1 */ -#define F0_DEV_CNTRL1_MM 0x2f0040 -#define F1_DEV_CNTRL1_MM 0x2f0140 -#define F2_DEV_CNTRL1_MM 0x2f0240 -#define F3_DEV_CNTRL1_MM 0x2f0340 -#define F4_DEV_CNTRL1_MM 0x2f0440 - -/* Device Control #1 */ -#define F0_BAR0_MM 0x2f0010 -#define F1_BAR0_MM 0x2f0110 -#define F2_BAR0_MM 0x2f0210 -#define F3_BAR0_MM 0x2f0310 -#define F4_BAR0_MM 0x2f0410 - -/* ---------------------------------------------------------------------- */ -/* DMA Controller registers */ - -#define MO_PDMA_STHRSH 0x200000 // Source threshold -#define MO_PDMA_STADRS 0x200004 // Source target address -#define MO_PDMA_SIADRS 0x200008 // Source internal address -#define MO_PDMA_SCNTRL 0x20000C // Source control -#define MO_PDMA_DTHRSH 0x200010 // Destination threshold -#define MO_PDMA_DTADRS 0x200014 // Destination target address -#define MO_PDMA_DIADRS 0x200018 // Destination internal address -#define MO_PDMA_DCNTRL 0x20001C // Destination control -#define MO_LD_SSID 0x200030 // Load subsystem ID -#define MO_DEV_CNTRL2 0x200034 // Device control -#define MO_PCI_INTMSK 0x200040 // PCI interrupt mask -#define MO_PCI_INTSTAT 0x200044 // PCI interrupt status -#define MO_PCI_INTMSTAT 0x200048 // PCI interrupt masked status -#define MO_VID_INTMSK 0x200050 // Video interrupt mask -#define MO_VID_INTSTAT 0x200054 // Video interrupt status -#define MO_VID_INTMSTAT 0x200058 // Video interrupt masked status -#define MO_VID_INTSSTAT 0x20005C // Video interrupt set status -#define MO_AUD_INTMSK 0x200060 // Audio interrupt mask -#define MO_AUD_INTSTAT 0x200064 // Audio interrupt status -#define MO_AUD_INTMSTAT 0x200068 // Audio interrupt masked status -#define MO_AUD_INTSSTAT 0x20006C // Audio interrupt set status -#define MO_TS_INTMSK 0x200070 // Transport stream interrupt mask -#define MO_TS_INTSTAT 0x200074 // Transport stream interrupt status -#define MO_TS_INTMSTAT 0x200078 // Transport stream interrupt mask status -#define MO_TS_INTSSTAT 0x20007C // Transport stream interrupt set status -#define MO_VIP_INTMSK 0x200080 // VIP interrupt mask -#define MO_VIP_INTSTAT 0x200084 // VIP interrupt status -#define MO_VIP_INTMSTAT 0x200088 // VIP interrupt masked status -#define MO_VIP_INTSSTAT 0x20008C // VIP interrupt set status -#define MO_GPHST_INTMSK 0x200090 // Host interrupt mask -#define MO_GPHST_INTSTAT 0x200094 // Host interrupt status -#define MO_GPHST_INTMSTAT 0x200098 // Host interrupt masked status -#define MO_GPHST_INTSSTAT 0x20009C // Host interrupt set status - -// DMA Channels 1-6 belong to SPIPE -#define MO_DMA7_PTR1 0x300018 // {24}RW* DMA Current Ptr : Ch#7 -#define MO_DMA8_PTR1 0x30001C // {24}RW* DMA Current Ptr : Ch#8 - -// DMA Channels 9-20 belong to SPIPE -#define MO_DMA21_PTR1 0x300080 // {24}R0* DMA Current Ptr : Ch#21 -#define MO_DMA22_PTR1 0x300084 // {24}R0* DMA Current Ptr : Ch#22 -#define MO_DMA23_PTR1 0x300088 // {24}R0* DMA Current Ptr : Ch#23 -#define MO_DMA24_PTR1 0x30008C // {24}R0* DMA Current Ptr : Ch#24 -#define MO_DMA25_PTR1 0x300090 // {24}R0* DMA Current Ptr : Ch#25 -#define MO_DMA26_PTR1 0x300094 // {24}R0* DMA Current Ptr : Ch#26 -#define MO_DMA27_PTR1 0x300098 // {24}R0* DMA Current Ptr : Ch#27 -#define MO_DMA28_PTR1 0x30009C // {24}R0* DMA Current Ptr : Ch#28 -#define MO_DMA29_PTR1 0x3000A0 // {24}R0* DMA Current Ptr : Ch#29 -#define MO_DMA30_PTR1 0x3000A4 // {24}R0* DMA Current Ptr : Ch#30 -#define MO_DMA31_PTR1 0x3000A8 // {24}R0* DMA Current Ptr : Ch#31 -#define MO_DMA32_PTR1 0x3000AC // {24}R0* DMA Current Ptr : Ch#32 - -#define MO_DMA21_PTR2 0x3000C0 // {24}RW* DMA Tab Ptr : Ch#21 -#define MO_DMA22_PTR2 0x3000C4 // {24}RW* DMA Tab Ptr : Ch#22 -#define MO_DMA23_PTR2 0x3000C8 // {24}RW* DMA Tab Ptr : Ch#23 -#define MO_DMA24_PTR2 0x3000CC // {24}RW* DMA Tab Ptr : Ch#24 -#define MO_DMA25_PTR2 0x3000D0 // {24}RW* DMA Tab Ptr : Ch#25 -#define MO_DMA26_PTR2 0x3000D4 // {24}RW* DMA Tab Ptr : Ch#26 -#define MO_DMA27_PTR2 0x3000D8 // {24}RW* DMA Tab Ptr : Ch#27 -#define MO_DMA28_PTR2 0x3000DC // {24}RW* DMA Tab Ptr : Ch#28 -#define MO_DMA29_PTR2 0x3000E0 // {24}RW* DMA Tab Ptr : Ch#29 -#define MO_DMA30_PTR2 0x3000E4 // {24}RW* DMA Tab Ptr : Ch#30 -#define MO_DMA31_PTR2 0x3000E8 // {24}RW* DMA Tab Ptr : Ch#31 -#define MO_DMA32_PTR2 0x3000EC // {24}RW* DMA Tab Ptr : Ch#32 - -#define MO_DMA21_CNT1 0x300100 // {11}RW* DMA Buffer Size : Ch#21 -#define MO_DMA22_CNT1 0x300104 // {11}RW* DMA Buffer Size : Ch#22 -#define MO_DMA23_CNT1 0x300108 // {11}RW* DMA Buffer Size : Ch#23 -#define MO_DMA24_CNT1 0x30010C // {11}RW* DMA Buffer Size : Ch#24 -#define MO_DMA25_CNT1 0x300110 // {11}RW* DMA Buffer Size : Ch#25 -#define MO_DMA26_CNT1 0x300114 // {11}RW* DMA Buffer Size : Ch#26 -#define MO_DMA27_CNT1 0x300118 // {11}RW* DMA Buffer Size : Ch#27 -#define MO_DMA28_CNT1 0x30011C // {11}RW* DMA Buffer Size : Ch#28 -#define MO_DMA29_CNT1 0x300120 // {11}RW* DMA Buffer Size : Ch#29 -#define MO_DMA30_CNT1 0x300124 // {11}RW* DMA Buffer Size : Ch#30 -#define MO_DMA31_CNT1 0x300128 // {11}RW* DMA Buffer Size : Ch#31 -#define MO_DMA32_CNT1 0x30012C // {11}RW* DMA Buffer Size : Ch#32 - -#define MO_DMA21_CNT2 0x300140 // {11}RW* DMA Table Size : Ch#21 -#define MO_DMA22_CNT2 0x300144 // {11}RW* DMA Table Size : Ch#22 -#define MO_DMA23_CNT2 0x300148 // {11}RW* DMA Table Size : Ch#23 -#define MO_DMA24_CNT2 0x30014C // {11}RW* DMA Table Size : Ch#24 -#define MO_DMA25_CNT2 0x300150 // {11}RW* DMA Table Size : Ch#25 -#define MO_DMA26_CNT2 0x300154 // {11}RW* DMA Table Size : Ch#26 -#define MO_DMA27_CNT2 0x300158 // {11}RW* DMA Table Size : Ch#27 -#define MO_DMA28_CNT2 0x30015C // {11}RW* DMA Table Size : Ch#28 -#define MO_DMA29_CNT2 0x300160 // {11}RW* DMA Table Size : Ch#29 -#define MO_DMA30_CNT2 0x300164 // {11}RW* DMA Table Size : Ch#30 -#define MO_DMA31_CNT2 0x300168 // {11}RW* DMA Table Size : Ch#31 -#define MO_DMA32_CNT2 0x30016C // {11}RW* DMA Table Size : Ch#32 - - -/* ---------------------------------------------------------------------- */ -/* Video registers */ - -#define MO_VIDY_DMA 0x310000 // {64}RWp Video Y -#define MO_VIDU_DMA 0x310008 // {64}RWp Video U -#define MO_VIDV_DMA 0x310010 // {64}RWp Video V -#define MO_VBI_DMA 0x310018 // {64}RWp VBI (Vertical blanking interval) - -#define MO_DEVICE_STATUS 0x310100 -#define MO_INPUT_FORMAT 0x310104 -#define MO_AGC_BURST 0x31010c -#define MO_CONTR_BRIGHT 0x310110 -#define MO_UV_SATURATION 0x310114 -#define MO_HUE 0x310118 -#define MO_HTOTAL 0x310120 -#define MO_HDELAY_EVEN 0x310124 -#define MO_HDELAY_ODD 0x310128 -#define MO_VDELAY_ODD 0x31012c -#define MO_VDELAY_EVEN 0x310130 -#define MO_HACTIVE_EVEN 0x31013c -#define MO_HACTIVE_ODD 0x310140 -#define MO_VACTIVE_EVEN 0x310144 -#define MO_VACTIVE_ODD 0x310148 -#define MO_HSCALE_EVEN 0x31014c -#define MO_HSCALE_ODD 0x310150 -#define MO_VSCALE_EVEN 0x310154 -#define MO_FILTER_EVEN 0x31015c -#define MO_VSCALE_ODD 0x310158 -#define MO_FILTER_ODD 0x310160 -#define MO_OUTPUT_FORMAT 0x310164 - -#define MO_PLL_REG 0x310168 // PLL register -#define MO_PLL_ADJ_CTRL 0x31016c // PLL adjust control register -#define MO_SCONV_REG 0x310170 // sample rate conversion register -#define MO_SCONV_FIFO 0x310174 // sample rate conversion fifo -#define MO_SUB_STEP 0x310178 // subcarrier step size -#define MO_SUB_STEP_DR 0x31017c // subcarrier step size for DR line - -#define MO_CAPTURE_CTRL 0x310180 // capture control -#define MO_COLOR_CTRL 0x310184 -#define MO_VBI_PACKET 0x310188 // vbi packet size / delay -#define MO_FIELD_COUNT 0x310190 // field counter -#define MO_VIP_CONFIG 0x310194 -#define MO_VBOS_CONTROL 0x3101a8 - -#define MO_AGC_BACK_VBI 0x310200 -#define MO_AGC_SYNC_TIP1 0x310208 - -#define MO_VIDY_GPCNT 0x31C020 // {16}RO Video Y general purpose counter -#define MO_VIDU_GPCNT 0x31C024 // {16}RO Video U general purpose counter -#define MO_VIDV_GPCNT 0x31C028 // {16}RO Video V general purpose counter -#define MO_VBI_GPCNT 0x31C02C // {16}RO VBI general purpose counter -#define MO_VIDY_GPCNTRL 0x31C030 // {2}WO Video Y general purpose control -#define MO_VIDU_GPCNTRL 0x31C034 // {2}WO Video U general purpose control -#define MO_VIDV_GPCNTRL 0x31C038 // {2}WO Video V general purpose control -#define MO_VBI_GPCNTRL 0x31C03C // {2}WO VBI general purpose counter -#define MO_VID_DMACNTRL 0x31C040 // {8}RW Video DMA control -#define MO_VID_XFR_STAT 0x31C044 // {1}RO Video transfer status - - -/* ---------------------------------------------------------------------- */ -/* audio registers */ - -#define MO_AUDD_DMA 0x320000 // {64}RWp Audio downstream -#define MO_AUDU_DMA 0x320008 // {64}RWp Audio upstream -#define MO_AUDR_DMA 0x320010 // {64}RWp Audio RDS (downstream) -#define MO_AUDD_GPCNT 0x32C020 // {16}RO Audio down general purpose counter -#define MO_AUDU_GPCNT 0x32C024 // {16}RO Audio up general purpose counter -#define MO_AUDR_GPCNT 0x32C028 // {16}RO Audio RDS general purpose counter -#define MO_AUDD_GPCNTRL 0x32C030 // {2}WO Audio down general purpose control -#define MO_AUDU_GPCNTRL 0x32C034 // {2}WO Audio up general purpose control -#define MO_AUDR_GPCNTRL 0x32C038 // {2}WO Audio RDS general purpose control -#define MO_AUD_DMACNTRL 0x32C040 // {6}RW Audio DMA control -#define MO_AUD_XFR_STAT 0x32C044 // {1}RO Audio transfer status -#define MO_AUDD_LNGTH 0x32C048 // {12}RW Audio down line length -#define MO_AUDR_LNGTH 0x32C04C // {12}RW Audio RDS line length - -#define AUD_INIT 0x320100 -#define AUD_INIT_LD 0x320104 -#define AUD_SOFT_RESET 0x320108 -#define AUD_I2SINPUTCNTL 0x320120 -#define AUD_BAUDRATE 0x320124 -#define AUD_I2SOUTPUTCNTL 0x320128 -#define AAGC_HYST 0x320134 -#define AAGC_GAIN 0x320138 -#define AAGC_DEF 0x32013c -#define AUD_IIR1_0_SEL 0x320150 -#define AUD_IIR1_0_SHIFT 0x320154 -#define AUD_IIR1_1_SEL 0x320158 -#define AUD_IIR1_1_SHIFT 0x32015c -#define AUD_IIR1_2_SEL 0x320160 -#define AUD_IIR1_2_SHIFT 0x320164 -#define AUD_IIR1_3_SEL 0x320168 -#define AUD_IIR1_3_SHIFT 0x32016c -#define AUD_IIR1_4_SEL 0x320170 -#define AUD_IIR1_4_SHIFT 0x32017c -#define AUD_IIR1_5_SEL 0x320180 -#define AUD_IIR1_5_SHIFT 0x320184 -#define AUD_IIR2_0_SEL 0x320190 -#define AUD_IIR2_0_SHIFT 0x320194 -#define AUD_IIR2_1_SEL 0x320198 -#define AUD_IIR2_1_SHIFT 0x32019c -#define AUD_IIR2_2_SEL 0x3201a0 -#define AUD_IIR2_2_SHIFT 0x3201a4 -#define AUD_IIR2_3_SEL 0x3201a8 -#define AUD_IIR2_3_SHIFT 0x3201ac -#define AUD_IIR3_0_SEL 0x3201c0 -#define AUD_IIR3_0_SHIFT 0x3201c4 -#define AUD_IIR3_1_SEL 0x3201c8 -#define AUD_IIR3_1_SHIFT 0x3201cc -#define AUD_IIR3_2_SEL 0x3201d0 -#define AUD_IIR3_2_SHIFT 0x3201d4 -#define AUD_IIR4_0_SEL 0x3201e0 -#define AUD_IIR4_0_SHIFT 0x3201e4 -#define AUD_IIR4_1_SEL 0x3201e8 -#define AUD_IIR4_1_SHIFT 0x3201ec -#define AUD_IIR4_2_SEL 0x3201f0 -#define AUD_IIR4_2_SHIFT 0x3201f4 -#define AUD_IIR4_0_CA0 0x320200 -#define AUD_IIR4_0_CA1 0x320204 -#define AUD_IIR4_0_CA2 0x320208 -#define AUD_IIR4_0_CB0 0x32020c -#define AUD_IIR4_0_CB1 0x320210 -#define AUD_IIR4_1_CA0 0x320214 -#define AUD_IIR4_1_CA1 0x320218 -#define AUD_IIR4_1_CA2 0x32021c -#define AUD_IIR4_1_CB0 0x320220 -#define AUD_IIR4_1_CB1 0x320224 -#define AUD_IIR4_2_CA0 0x320228 -#define AUD_IIR4_2_CA1 0x32022c -#define AUD_IIR4_2_CA2 0x320230 -#define AUD_IIR4_2_CB0 0x320234 -#define AUD_IIR4_2_CB1 0x320238 -#define AUD_HP_MD_IIR4_1 0x320250 -#define AUD_HP_PROG_IIR4_1 0x320254 -#define AUD_FM_MODE_ENABLE 0x320258 -#define AUD_POLY0_DDS_CONSTANT 0x320270 -#define AUD_DN0_FREQ 0x320274 -#define AUD_DN1_FREQ 0x320278 -#define AUD_DN1_FREQ_SHIFT 0x32027c -#define AUD_DN1_AFC 0x320280 -#define AUD_DN1_SRC_SEL 0x320284 -#define AUD_DN1_SHFT 0x320288 -#define AUD_DN2_FREQ 0x32028c -#define AUD_DN2_FREQ_SHIFT 0x320290 -#define AUD_DN2_AFC 0x320294 -#define AUD_DN2_SRC_SEL 0x320298 -#define AUD_DN2_SHFT 0x32029c -#define AUD_CRDC0_SRC_SEL 0x320300 -#define AUD_CRDC0_SHIFT 0x320304 -#define AUD_CORDIC_SHIFT_0 0x320308 -#define AUD_CRDC1_SRC_SEL 0x32030c -#define AUD_CRDC1_SHIFT 0x320310 -#define AUD_CORDIC_SHIFT_1 0x320314 -#define AUD_DCOC_0_SRC 0x320320 -#define AUD_DCOC0_SHIFT 0x320324 -#define AUD_DCOC_0_SHIFT_IN0 0x320328 -#define AUD_DCOC_0_SHIFT_IN1 0x32032c -#define AUD_DCOC_1_SRC 0x320330 -#define AUD_DCOC1_SHIFT 0x320334 -#define AUD_DCOC_1_SHIFT_IN0 0x320338 -#define AUD_DCOC_1_SHIFT_IN1 0x32033c -#define AUD_DCOC_2_SRC 0x320340 -#define AUD_DCOC2_SHIFT 0x320344 -#define AUD_DCOC_2_SHIFT_IN0 0x320348 -#define AUD_DCOC_2_SHIFT_IN1 0x32034c -#define AUD_DCOC_PASS_IN 0x320350 -#define AUD_PDET_SRC 0x320370 -#define AUD_PDET_SHIFT 0x320374 -#define AUD_PILOT_BQD_1_K0 0x320380 -#define AUD_PILOT_BQD_1_K1 0x320384 -#define AUD_PILOT_BQD_1_K2 0x320388 -#define AUD_PILOT_BQD_1_K3 0x32038c -#define AUD_PILOT_BQD_1_K4 0x320390 -#define AUD_PILOT_BQD_2_K0 0x320394 -#define AUD_PILOT_BQD_2_K1 0x320398 -#define AUD_PILOT_BQD_2_K2 0x32039c -#define AUD_PILOT_BQD_2_K3 0x3203a0 -#define AUD_PILOT_BQD_2_K4 0x3203a4 -#define AUD_THR_FR 0x3203c0 -#define AUD_X_PROG 0x3203c4 -#define AUD_Y_PROG 0x3203c8 -#define AUD_HARMONIC_MULT 0x3203cc -#define AUD_C1_UP_THR 0x3203d0 -#define AUD_C1_LO_THR 0x3203d4 -#define AUD_C2_UP_THR 0x3203d8 -#define AUD_C2_LO_THR 0x3203dc -#define AUD_PLL_EN 0x320400 -#define AUD_PLL_SRC 0x320404 -#define AUD_PLL_SHIFT 0x320408 -#define AUD_PLL_IF_SEL 0x32040c -#define AUD_PLL_IF_SHIFT 0x320410 -#define AUD_BIQUAD_PLL_K0 0x320414 -#define AUD_BIQUAD_PLL_K1 0x320418 -#define AUD_BIQUAD_PLL_K2 0x32041c -#define AUD_BIQUAD_PLL_K3 0x320420 -#define AUD_BIQUAD_PLL_K4 0x320424 -#define AUD_DEEMPH0_SRC_SEL 0x320440 -#define AUD_DEEMPH0_SHIFT 0x320444 -#define AUD_DEEMPH0_G0 0x320448 -#define AUD_DEEMPH0_A0 0x32044c -#define AUD_DEEMPH0_B0 0x320450 -#define AUD_DEEMPH0_A1 0x320454 -#define AUD_DEEMPH0_B1 0x320458 -#define AUD_DEEMPH1_SRC_SEL 0x32045c -#define AUD_DEEMPH1_SHIFT 0x320460 -#define AUD_DEEMPH1_G0 0x320464 -#define AUD_DEEMPH1_A0 0x320468 -#define AUD_DEEMPH1_B0 0x32046c -#define AUD_DEEMPH1_A1 0x320470 -#define AUD_DEEMPH1_B1 0x320474 -#define AUD_OUT0_SEL 0x320490 -#define AUD_OUT0_SHIFT 0x320494 -#define AUD_OUT1_SEL 0x320498 -#define AUD_OUT1_SHIFT 0x32049c -#define AUD_RDSI_SEL 0x3204a0 -#define AUD_RDSI_SHIFT 0x3204a4 -#define AUD_RDSQ_SEL 0x3204a8 -#define AUD_RDSQ_SHIFT 0x3204ac -#define AUD_DBX_IN_GAIN 0x320500 -#define AUD_DBX_WBE_GAIN 0x320504 -#define AUD_DBX_SE_GAIN 0x320508 -#define AUD_DBX_RMS_WBE 0x32050c -#define AUD_DBX_RMS_SE 0x320510 -#define AUD_DBX_SE_BYPASS 0x320514 -#define AUD_FAWDETCTL 0x320530 -#define AUD_FAWDETWINCTL 0x320534 -#define AUD_DEEMPHGAIN_R 0x320538 -#define AUD_DEEMPHNUMER1_R 0x32053c -#define AUD_DEEMPHNUMER2_R 0x320540 -#define AUD_DEEMPHDENOM1_R 0x320544 -#define AUD_DEEMPHDENOM2_R 0x320548 -#define AUD_ERRLOGPERIOD_R 0x32054c -#define AUD_ERRINTRPTTHSHLD1_R 0x320550 -#define AUD_ERRINTRPTTHSHLD2_R 0x320554 -#define AUD_ERRINTRPTTHSHLD3_R 0x320558 -#define AUD_NICAM_STATUS1 0x32055c -#define AUD_NICAM_STATUS2 0x320560 -#define AUD_ERRLOG1 0x320564 -#define AUD_ERRLOG2 0x320568 -#define AUD_ERRLOG3 0x32056c -#define AUD_DAC_BYPASS_L 0x320580 -#define AUD_DAC_BYPASS_R 0x320584 -#define AUD_DAC_BYPASS_CTL 0x320588 -#define AUD_CTL 0x32058c -#define AUD_STATUS 0x320590 -#define AUD_VOL_CTL 0x320594 -#define AUD_BAL_CTL 0x320598 -#define AUD_START_TIMER 0x3205b0 -#define AUD_MODE_CHG_TIMER 0x3205b4 -#define AUD_POLYPH80SCALEFAC 0x3205b8 -#define AUD_DMD_RA_DDS 0x3205bc -#define AUD_I2S_RA_DDS 0x3205c0 -#define AUD_RATE_THRES_DMD 0x3205d0 -#define AUD_RATE_THRES_I2S 0x3205d4 -#define AUD_RATE_ADJ1 0x3205d8 -#define AUD_RATE_ADJ2 0x3205dc -#define AUD_RATE_ADJ3 0x3205e0 -#define AUD_RATE_ADJ4 0x3205e4 -#define AUD_RATE_ADJ5 0x3205e8 -#define AUD_APB_IN_RATE_ADJ 0x3205ec -#define AUD_I2SCNTL 0x3205ec -#define AUD_PHASE_FIX_CTL 0x3205f0 -#define AUD_PLL_PRESCALE 0x320600 -#define AUD_PLL_DDS 0x320604 -#define AUD_PLL_INT 0x320608 -#define AUD_PLL_FRAC 0x32060c -#define AUD_PLL_JTAG 0x320620 -#define AUD_PLL_SPMP 0x320624 -#define AUD_AFE_12DB_EN 0x320628 - -// Audio QAM Register Addresses -#define AUD_PDF_DDS_CNST_BYTE2 0x320d01 -#define AUD_PDF_DDS_CNST_BYTE1 0x320d02 -#define AUD_PDF_DDS_CNST_BYTE0 0x320d03 -#define AUD_PHACC_FREQ_8MSB 0x320d2a -#define AUD_PHACC_FREQ_8LSB 0x320d2b -#define AUD_QAM_MODE 0x320d04 - - -/* ---------------------------------------------------------------------- */ -/* transport stream registers */ - -#define MO_TS_DMA 0x330000 // {64}RWp Transport stream downstream -#define MO_TS_GPCNT 0x33C020 // {16}RO TS general purpose counter -#define MO_TS_GPCNTRL 0x33C030 // {2}WO TS general purpose control -#define MO_TS_DMACNTRL 0x33C040 // {6}RW TS DMA control -#define MO_TS_XFR_STAT 0x33C044 // {1}RO TS transfer status -#define MO_TS_LNGTH 0x33C048 // {12}RW TS line length - -#define TS_HW_SOP_CNTRL 0x33C04C -#define TS_GEN_CNTRL 0x33C050 -#define TS_BD_PKT_STAT 0x33C054 -#define TS_SOP_STAT 0x33C058 -#define TS_FIFO_OVFL_STAT 0x33C05C -#define TS_VALERR_CNTRL 0x33C060 - - -/* ---------------------------------------------------------------------- */ -/* VIP registers */ - -#define MO_VIPD_DMA 0x340000 // {64}RWp VIP downstream -#define MO_VIPU_DMA 0x340008 // {64}RWp VIP upstream -#define MO_VIPD_GPCNT 0x34C020 // {16}RO VIP down general purpose counter -#define MO_VIPU_GPCNT 0x34C024 // {16}RO VIP up general purpose counter -#define MO_VIPD_GPCNTRL 0x34C030 // {2}WO VIP down general purpose control -#define MO_VIPU_GPCNTRL 0x34C034 // {2}WO VIP up general purpose control -#define MO_VIP_DMACNTRL 0x34C040 // {6}RW VIP DMA control -#define MO_VIP_XFR_STAT 0x34C044 // {1}RO VIP transfer status -#define MO_VIP_CFG 0x340048 // VIP configuration -#define MO_VIPU_CNTRL 0x34004C // VIP upstream control #1 -#define MO_VIPD_CNTRL 0x340050 // VIP downstream control #2 -#define MO_VIPD_LNGTH 0x340054 // VIP downstream line length -#define MO_VIP_BRSTLN 0x340058 // VIP burst length -#define MO_VIP_INTCNTRL 0x34C05C // VIP Interrupt Control -#define MO_VIP_XFTERM 0x340060 // VIP transfer terminate - - -/* ---------------------------------------------------------------------- */ -/* misc registers */ - -#define MO_M2M_DMA 0x350000 // {64}RWp Mem2Mem DMA Bfr -#define MO_GP0_IO 0x350010 // {32}RW* GPIOoutput enablesdata I/O -#define MO_GP1_IO 0x350014 // {32}RW* GPIOoutput enablesdata I/O -#define MO_GP2_IO 0x350018 // {32}RW* GPIOoutput enablesdata I/O -#define MO_GP3_IO 0x35001C // {32}RW* GPIO Mode/Ctrloutput enables -#define MO_GPIO 0x350020 // {32}RW* GPIO I2C Ctrldata I/O -#define MO_GPOE 0x350024 // {32}RW GPIO I2C Ctrloutput enables -#define MO_GP_ISM 0x350028 // {16}WO GPIO Intr Sens/Pol - -#define MO_PLL_B 0x35C008 // {32}RW* PLL Control for ASB bus clks -#define MO_M2M_CNT 0x35C024 // {32}RW Mem2Mem DMA Cnt -#define MO_M2M_XSUM 0x35C028 // {32}RO M2M XOR-Checksum -#define MO_CRC 0x35C02C // {16}RW CRC16 init/result -#define MO_CRC_D 0x35C030 // {32}WO CRC16 new data in -#define MO_TM_CNT_LDW 0x35C034 // {32}RO Timer : Counter low dword -#define MO_TM_CNT_UW 0x35C038 // {16}RO Timer : Counter high word -#define MO_TM_LMT_LDW 0x35C03C // {32}RW Timer : Limit low dword -#define MO_TM_LMT_UW 0x35C040 // {32}RW Timer : Limit high word -#define MO_PINMUX_IO 0x35C044 // {8}RW Pin Mux Control -#define MO_TSTSEL_IO 0x35C048 // {2}RW Pin Mux Control -#define MO_AFECFG_IO 0x35C04C // AFE configuration reg -#define MO_DDS_IO 0x35C050 // DDS Increment reg -#define MO_DDSCFG_IO 0x35C054 // DDS Configuration reg -#define MO_SAMPLE_IO 0x35C058 // IRIn sample reg -#define MO_SRST_IO 0x35C05C // Output system reset reg - -#define MO_INT1_MSK 0x35C060 // DMA RISC interrupt mask -#define MO_INT1_STAT 0x35C064 // DMA RISC interrupt status -#define MO_INT1_MSTAT 0x35C068 // DMA RISC interrupt masked status - - -/* ---------------------------------------------------------------------- */ -/* i2c bus registers */ - -#define MO_I2C 0x368000 // I2C data/control -#define MO_I2C_DIV (0xf<<4) -#define MO_I2C_SYNC (1<<3) -#define MO_I2C_W3B (1<<2) -#define MO_I2C_SCL (1<<1) -#define MO_I2C_SDA (1<<0) - - -/* ---------------------------------------------------------------------- */ -/* general purpose host registers */ -/* FIXME: tyops? s/0x35/0x38/ ?? */ - -#define MO_GPHSTD_DMA 0x350000 // {64}RWp Host downstream -#define MO_GPHSTU_DMA 0x350008 // {64}RWp Host upstream -#define MO_GPHSTU_CNTRL 0x380048 // Host upstream control #1 -#define MO_GPHSTD_CNTRL 0x38004C // Host downstream control #2 -#define MO_GPHSTD_LNGTH 0x380050 // Host downstream line length -#define MO_GPHST_WSC 0x380054 // Host wait state control -#define MO_GPHST_XFR 0x380058 // Host transfer control -#define MO_GPHST_WDTH 0x38005C // Host interface width -#define MO_GPHST_HDSHK 0x380060 // Host peripheral handshake -#define MO_GPHST_MUX16 0x380064 // Host muxed 16-bit transfer parameters -#define MO_GPHST_MODE 0x380068 // Host mode select - -#define MO_GPHSTD_GPCNT 0x35C020 // Host down general purpose counter -#define MO_GPHSTU_GPCNT 0x35C024 // Host up general purpose counter -#define MO_GPHSTD_GPCNTRL 0x38C030 // Host down general purpose control -#define MO_GPHSTU_GPCNTRL 0x38C034 // Host up general purpose control -#define MO_GPHST_DMACNTRL 0x38C040 // Host DMA control -#define MO_GPHST_XFR_STAT 0x38C044 // Host transfer status -#define MO_GPHST_SOFT_RST 0x38C06C // Host software reset - - -/* ---------------------------------------------------------------------- */ -/* RISC instructions */ - -#define RISC_SYNC 0x80000000 -#define RISC_SYNC_ODD 0x80000000 -#define RISC_SYNC_EVEN 0x80000200 -#define RISC_RESYNC 0x80008000 -#define RISC_RESYNC_ODD 0x80008000 -#define RISC_RESYNC_EVEN 0x80008200 -#define RISC_WRITE 0x10000000 -#define RISC_WRITEC 0x50000000 -#define RISC_READ 0x90000000 -#define RISC_READC 0xA0000000 -#define RISC_JUMP 0x70000000 -#define RISC_SKIP 0x20000000 -#define RISC_WRITERM 0xB0000000 -#define RISC_WRITECM 0xC0000000 -#define RISC_WRITECR 0xD0000000 -#define RISC_IMM 0x00000001 - -#define RISC_SOL 0x08000000 -#define RISC_EOL 0x04000000 - -#define RISC_IRQ2 0x02000000 -#define RISC_IRQ1 0x01000000 - -#define RISC_CNT_NONE 0x00000000 -#define RISC_CNT_INC 0x00010000 -#define RISC_CNT_RSVR 0x00020000 -#define RISC_CNT_RESET 0x00030000 -#define RISC_JMP_SRP 0x01 - - -/* ---------------------------------------------------------------------- */ -/* various constants */ - -// DMA -/* Interrupt mask/status */ -#define PCI_INT_VIDINT (1 << 0) -#define PCI_INT_AUDINT (1 << 1) -#define PCI_INT_TSINT (1 << 2) -#define PCI_INT_VIPINT (1 << 3) -#define PCI_INT_HSTINT (1 << 4) -#define PCI_INT_TM1INT (1 << 5) -#define PCI_INT_SRCDMAINT (1 << 6) -#define PCI_INT_DSTDMAINT (1 << 7) -#define PCI_INT_RISC_RD_BERRINT (1 << 10) -#define PCI_INT_RISC_WR_BERRINT (1 << 11) -#define PCI_INT_BRDG_BERRINT (1 << 12) -#define PCI_INT_SRC_DMA_BERRINT (1 << 13) -#define PCI_INT_DST_DMA_BERRINT (1 << 14) -#define PCI_INT_IPB_DMA_BERRINT (1 << 15) -#define PCI_INT_I2CDONE (1 << 16) -#define PCI_INT_I2CRACK (1 << 17) -#define PCI_INT_IR_SMPINT (1 << 18) -#define PCI_INT_GPIO_INT0 (1 << 19) -#define PCI_INT_GPIO_INT1 (1 << 20) - -#define SEL_BTSC 0x01 -#define SEL_EIAJ 0x02 -#define SEL_A2 0x04 -#define SEL_SAP 0x08 -#define SEL_NICAM 0x10 -#define SEL_FMRADIO 0x20 - -// AUD_CTL -#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 EN_BTSC_FORCE_MONO 0 -#define EN_BTSC_FORCE_STEREO 1 -#define EN_BTSC_FORCE_SAP 2 -#define EN_BTSC_AUTO_STEREO 3 -#define EN_BTSC_AUTO_SAP 4 - -#define EN_A2_FORCE_MONO1 8 -#define EN_A2_FORCE_MONO2 9 -#define EN_A2_FORCE_STEREO 10 -#define EN_A2_AUTO_MONO2 11 -#define EN_A2_AUTO_STEREO 12 - -#define EN_EIAJ_FORCE_MONO1 16 -#define EN_EIAJ_FORCE_MONO2 17 -#define EN_EIAJ_FORCE_STEREO 18 -#define EN_EIAJ_AUTO_MONO2 19 -#define EN_EIAJ_AUTO_STEREO 20 - -#define EN_NICAM_FORCE_MONO1 32 -#define EN_NICAM_FORCE_MONO2 33 -#define EN_NICAM_FORCE_STEREO 34 -#define EN_NICAM_AUTO_MONO2 35 -#define EN_NICAM_AUTO_STEREO 36 - -#define EN_FMRADIO_FORCE_MONO 24 -#define EN_FMRADIO_FORCE_STEREO 25 -#define EN_FMRADIO_AUTO_STEREO 26 - -#define EN_NICAM_AUTO_FALLBACK 0x00000040 -#define EN_FMRADIO_EN_RDS 0x00000200 -#define EN_NICAM_TRY_AGAIN_BIT 0x00000400 -#define EN_DAC_ENABLE 0x00001000 -#define EN_I2SOUT_ENABLE 0x00002000 -#define EN_I2SIN_STR2DAC 0x00004000 -#define EN_I2SIN_ENABLE 0x00008000 - -#define EN_DMTRX_SUMDIFF (0 << 7) -#define EN_DMTRX_SUMR (1 << 7) -#define EN_DMTRX_LR (2 << 7) -#define EN_DMTRX_MONO (3 << 7) -#define EN_DMTRX_BYPASS (1 << 11) - -// Video -#define VID_CAPTURE_CONTROL 0x310180 - -#define CX23880_CAP_CTL_CAPTURE_VBI_ODD (1<<3) -#define CX23880_CAP_CTL_CAPTURE_VBI_EVEN (1<<2) -#define CX23880_CAP_CTL_CAPTURE_ODD (1<<1) -#define CX23880_CAP_CTL_CAPTURE_EVEN (1<<0) - -#define VideoInputMux0 0x0 -#define VideoInputMux1 0x1 -#define VideoInputMux2 0x2 -#define VideoInputMux3 0x3 -#define VideoInputTuner 0x0 -#define VideoInputComposite 0x1 -#define VideoInputSVideo 0x2 -#define VideoInputOther 0x3 - -#define Xtal0 0x1 -#define Xtal1 0x2 -#define XtalAuto 0x3 - -#define VideoFormatAuto 0x0 -#define VideoFormatNTSC 0x1 -#define VideoFormatNTSCJapan 0x2 -#define VideoFormatNTSC443 0x3 -#define VideoFormatPAL 0x4 -#define VideoFormatPALB 0x4 -#define VideoFormatPALD 0x4 -#define VideoFormatPALG 0x4 -#define VideoFormatPALH 0x4 -#define VideoFormatPALI 0x4 -#define VideoFormatPALBDGHI 0x4 -#define VideoFormatPALM 0x5 -#define VideoFormatPALN 0x6 -#define VideoFormatPALNC 0x7 -#define VideoFormatPAL60 0x8 -#define VideoFormatSECAM 0x9 - -#define VideoFormatAuto27MHz 0x10 -#define VideoFormatNTSC27MHz 0x11 -#define VideoFormatNTSCJapan27MHz 0x12 -#define VideoFormatNTSC44327MHz 0x13 -#define VideoFormatPAL27MHz 0x14 -#define VideoFormatPALB27MHz 0x14 -#define VideoFormatPALD27MHz 0x14 -#define VideoFormatPALG27MHz 0x14 -#define VideoFormatPALH27MHz 0x14 -#define VideoFormatPALI27MHz 0x14 -#define VideoFormatPALBDGHI27MHz 0x14 -#define VideoFormatPALM27MHz 0x15 -#define VideoFormatPALN27MHz 0x16 -#define VideoFormatPALNC27MHz 0x17 -#define VideoFormatPAL6027MHz 0x18 -#define VideoFormatSECAM27MHz 0x19 - -#define NominalUSECAM 0x87 -#define NominalVSECAM 0x85 -#define NominalUNTSC 0xFE -#define NominalVNTSC 0xB4 - -#define NominalContrast 0xD8 - -#define HFilterAutoFormat 0x0 -#define HFilterCIF 0x1 -#define HFilterQCIF 0x2 -#define HFilterICON 0x3 - -#define VFilter2TapInterpolate 0 -#define VFilter3TapInterpolate 1 -#define VFilter4TapInterpolate 2 -#define VFilter5TapInterpolate 3 -#define VFilter2TapNoInterpolate 4 -#define VFilter3TapNoInterpolate 5 -#define VFilter4TapNoInterpolate 6 -#define VFilter5TapNoInterpolate 7 - -#define ColorFormatRGB32 0x0000 -#define ColorFormatRGB24 0x0011 -#define ColorFormatRGB16 0x0022 -#define ColorFormatRGB15 0x0033 -#define ColorFormatYUY2 0x0044 -#define ColorFormatBTYUV 0x0055 -#define ColorFormatY8 0x0066 -#define ColorFormatRGB8 0x0077 -#define ColorFormatPL422 0x0088 -#define ColorFormatPL411 0x0099 -#define ColorFormatYUV12 0x00AA -#define ColorFormatYUV9 0x00BB -#define ColorFormatRAW 0x00EE -#define ColorFormatBSWAP 0x0300 -#define ColorFormatWSWAP 0x0c00 -#define ColorFormatEvenMask 0x050f -#define ColorFormatOddMask 0x0af0 -#define ColorFormatGamma 0x1000 - -#define Interlaced 0x1 -#define NonInterlaced 0x0 - -#define FieldEven 0x1 -#define FieldOdd 0x0 - -#define TGReadWriteMode 0x0 -#define TGEnableMode 0x1 - -#define DV_CbAlign 0x0 -#define DV_Y0Align 0x1 -#define DV_CrAlign 0x2 -#define DV_Y1Align 0x3 - -#define DVF_Analog 0x0 -#define DVF_CCIR656 0x1 -#define DVF_ByteStream 0x2 -#define DVF_ExtVSYNC 0x4 -#define DVF_ExtField 0x5 - -#define CHANNEL_VID_Y 0x1 -#define CHANNEL_VID_U 0x2 -#define CHANNEL_VID_V 0x3 -#define CHANNEL_VID_VBI 0x4 -#define CHANNEL_AUD_DN 0x5 -#define CHANNEL_AUD_UP 0x6 -#define CHANNEL_AUD_RDS_DN 0x7 -#define CHANNEL_MPEG_DN 0x8 -#define CHANNEL_VIP_DN 0x9 -#define CHANNEL_VIP_UP 0xA -#define CHANNEL_HOST_DN 0xB -#define CHANNEL_HOST_UP 0xC -#define CHANNEL_FIRST 0x1 -#define CHANNEL_LAST 0xC - -#define GP_COUNT_CONTROL_NONE 0x0 -#define GP_COUNT_CONTROL_INC 0x1 -#define GP_COUNT_CONTROL_RESERVED 0x2 -#define GP_COUNT_CONTROL_RESET 0x3 - -#define PLL_PRESCALE_BY_2 2 -#define PLL_PRESCALE_BY_3 3 -#define PLL_PRESCALE_BY_4 4 -#define PLL_PRESCALE_BY_5 5 - -#define HLNotchFilter4xFsc 0 -#define HLNotchFilterSquare 1 -#define HLNotchFilter135NTSC 2 -#define HLNotchFilter135PAL 3 - -#define NTSC_8x_SUB_CARRIER 28.63636E6 -#define PAL_8x_SUB_CARRIER 35.46895E6 - -// Default analog settings -#define DEFAULT_HUE_NTSC 0x00 -#define DEFAULT_BRIGHTNESS_NTSC 0x00 -#define DEFAULT_CONTRAST_NTSC 0x39 -#define DEFAULT_SAT_U_NTSC 0x7F -#define DEFAULT_SAT_V_NTSC 0x5A - -typedef enum -{ - SOURCE_TUNER = 0, - SOURCE_COMPOSITE, - SOURCE_SVIDEO, - SOURCE_OTHER1, - SOURCE_OTHER2, - SOURCE_COMPVIASVIDEO, - SOURCE_CCIR656 -} VIDEOSOURCETYPE; - -#endif /* _CX88_REG_H_ */ diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c deleted file mode 100644 index 770ec05b5e9b..000000000000 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ /dev/null @@ -1,1059 +0,0 @@ -/* - - cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver - - (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version] - (c) 2002 Yurij Sysoev <yurij@naturesoft.net> - (c) 2003 Gerd Knorr <kraxel@bytesex.org> - - ----------------------------------------------------------------------- - - Lot of voodoo here. Even the data sheet doesn't help to - understand what is going on here, the documentation for the audio - part of the cx2388x chip is *very* bad. - - Some of this comes from party done linux driver sources I got from - [undocumented]. - - Some comes from the dscaler sources, one of the dscaler driver guy works - for Conexant ... - - ----------------------------------------------------------------------- - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/freezer.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/poll.h> -#include <linux/signal.h> -#include <linux/ioport.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/vmalloc.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/kthread.h> - -#include "cx88.h" - -static unsigned int audio_debug; -module_param(audio_debug, int, 0644); -MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]"); - -static unsigned int always_analog; -module_param(always_analog,int,0644); -MODULE_PARM_DESC(always_analog,"force analog audio out"); - -static unsigned int radio_deemphasis; -module_param(radio_deemphasis,int,0644); -MODULE_PARM_DESC(radio_deemphasis, "Radio deemphasis time constant, " - "0=None, 1=50us (elsewhere), 2=75us (USA)"); - -#define dprintk(fmt, arg...) if (audio_debug) \ - printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) - -/* ----------------------------------------------------------- */ - -static const char * const aud_ctl_names[64] = { - [EN_BTSC_FORCE_MONO] = "BTSC_FORCE_MONO", - [EN_BTSC_FORCE_STEREO] = "BTSC_FORCE_STEREO", - [EN_BTSC_FORCE_SAP] = "BTSC_FORCE_SAP", - [EN_BTSC_AUTO_STEREO] = "BTSC_AUTO_STEREO", - [EN_BTSC_AUTO_SAP] = "BTSC_AUTO_SAP", - [EN_A2_FORCE_MONO1] = "A2_FORCE_MONO1", - [EN_A2_FORCE_MONO2] = "A2_FORCE_MONO2", - [EN_A2_FORCE_STEREO] = "A2_FORCE_STEREO", - [EN_A2_AUTO_MONO2] = "A2_AUTO_MONO2", - [EN_A2_AUTO_STEREO] = "A2_AUTO_STEREO", - [EN_EIAJ_FORCE_MONO1] = "EIAJ_FORCE_MONO1", - [EN_EIAJ_FORCE_MONO2] = "EIAJ_FORCE_MONO2", - [EN_EIAJ_FORCE_STEREO] = "EIAJ_FORCE_STEREO", - [EN_EIAJ_AUTO_MONO2] = "EIAJ_AUTO_MONO2", - [EN_EIAJ_AUTO_STEREO] = "EIAJ_AUTO_STEREO", - [EN_NICAM_FORCE_MONO1] = "NICAM_FORCE_MONO1", - [EN_NICAM_FORCE_MONO2] = "NICAM_FORCE_MONO2", - [EN_NICAM_FORCE_STEREO] = "NICAM_FORCE_STEREO", - [EN_NICAM_AUTO_MONO2] = "NICAM_AUTO_MONO2", - [EN_NICAM_AUTO_STEREO] = "NICAM_AUTO_STEREO", - [EN_FMRADIO_FORCE_MONO] = "FMRADIO_FORCE_MONO", - [EN_FMRADIO_FORCE_STEREO] = "FMRADIO_FORCE_STEREO", - [EN_FMRADIO_AUTO_STEREO] = "FMRADIO_AUTO_STEREO", -}; - -struct rlist { - u32 reg; - u32 val; -}; - -static void set_audio_registers(struct cx88_core *core, const struct rlist *l) -{ - int i; - - for (i = 0; l[i].reg; i++) { - switch (l[i].reg) { - case AUD_PDF_DDS_CNST_BYTE2: - case AUD_PDF_DDS_CNST_BYTE1: - case AUD_PDF_DDS_CNST_BYTE0: - case AUD_QAM_MODE: - case AUD_PHACC_FREQ_8MSB: - case AUD_PHACC_FREQ_8LSB: - cx_writeb(l[i].reg, l[i].val); - break; - default: - cx_write(l[i].reg, l[i].val); - break; - } - } -} - -static void set_audio_start(struct cx88_core *core, u32 mode) -{ - /* mute */ - cx_write(AUD_VOL_CTL, (1 << 6)); - - /* start programming */ - cx_write(AUD_INIT, mode); - cx_write(AUD_INIT_LD, 0x0001); - cx_write(AUD_SOFT_RESET, 0x0001); -} - -static void set_audio_finish(struct cx88_core *core, u32 ctl) -{ - u32 volume; - - /* restart dma; This avoids buzz in NICAM and is good in others */ - cx88_stop_audio_dma(core); - cx_write(AUD_RATE_THRES_DMD, 0x000000C0); - cx88_start_audio_dma(core); - - if (core->board.mpeg & CX88_MPEG_BLACKBIRD) { - cx_write(AUD_I2SINPUTCNTL, 4); - cx_write(AUD_BAUDRATE, 1); - /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */ - cx_set(AUD_CTL, EN_I2SOUT_ENABLE); - cx_write(AUD_I2SOUTPUTCNTL, 1); - cx_write(AUD_I2SCNTL, 0); - /* cx_write(AUD_APB_IN_RATE_ADJ, 0); */ - } - if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) { - ctl |= EN_DAC_ENABLE; - cx_write(AUD_CTL, ctl); - } - - /* finish programming */ - cx_write(AUD_SOFT_RESET, 0x0000); - - /* unmute */ - volume = cx_sread(SHADOW_AUD_VOL_CTL); - cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume); - - core->last_change = jiffies; -} - -/* ----------------------------------------------------------- */ - -static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap, - u32 mode) -{ - static const struct rlist btsc[] = { - {AUD_AFE_12DB_EN, 0x00000001}, - {AUD_OUT1_SEL, 0x00000013}, - {AUD_OUT1_SHIFT, 0x00000000}, - {AUD_POLY0_DDS_CONSTANT, 0x0012010c}, - {AUD_DMD_RA_DDS, 0x00c3e7aa}, - {AUD_DBX_IN_GAIN, 0x00004734}, - {AUD_DBX_WBE_GAIN, 0x00004640}, - {AUD_DBX_SE_GAIN, 0x00008d31}, - {AUD_DCOC_0_SRC, 0x0000001a}, - {AUD_IIR1_4_SEL, 0x00000021}, - {AUD_DCOC_PASS_IN, 0x00000003}, - {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, - {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, - {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, - {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, - {AUD_DN0_FREQ, 0x0000283b}, - {AUD_DN2_SRC_SEL, 0x00000008}, - {AUD_DN2_FREQ, 0x00003000}, - {AUD_DN2_AFC, 0x00000002}, - {AUD_DN2_SHFT, 0x00000000}, - {AUD_IIR2_2_SEL, 0x00000020}, - {AUD_IIR2_2_SHIFT, 0x00000000}, - {AUD_IIR2_3_SEL, 0x0000001f}, - {AUD_IIR2_3_SHIFT, 0x00000000}, - {AUD_CRDC1_SRC_SEL, 0x000003ce}, - {AUD_CRDC1_SHIFT, 0x00000000}, - {AUD_CORDIC_SHIFT_1, 0x00000007}, - {AUD_DCOC_1_SRC, 0x0000001b}, - {AUD_DCOC1_SHIFT, 0x00000000}, - {AUD_RDSI_SEL, 0x00000008}, - {AUD_RDSQ_SEL, 0x00000008}, - {AUD_RDSI_SHIFT, 0x00000000}, - {AUD_RDSQ_SHIFT, 0x00000000}, - {AUD_POLYPH80SCALEFAC, 0x00000003}, - { /* end of list */ }, - }; - static const struct rlist btsc_sap[] = { - {AUD_AFE_12DB_EN, 0x00000001}, - {AUD_DBX_IN_GAIN, 0x00007200}, - {AUD_DBX_WBE_GAIN, 0x00006200}, - {AUD_DBX_SE_GAIN, 0x00006200}, - {AUD_IIR1_1_SEL, 0x00000000}, - {AUD_IIR1_3_SEL, 0x00000001}, - {AUD_DN1_SRC_SEL, 0x00000007}, - {AUD_IIR1_4_SHIFT, 0x00000006}, - {AUD_IIR2_1_SHIFT, 0x00000000}, - {AUD_IIR2_2_SHIFT, 0x00000000}, - {AUD_IIR3_0_SHIFT, 0x00000000}, - {AUD_IIR3_1_SHIFT, 0x00000000}, - {AUD_IIR3_0_SEL, 0x0000000d}, - {AUD_IIR3_1_SEL, 0x0000000e}, - {AUD_DEEMPH1_SRC_SEL, 0x00000014}, - {AUD_DEEMPH1_SHIFT, 0x00000000}, - {AUD_DEEMPH1_G0, 0x00004000}, - {AUD_DEEMPH1_A0, 0x00000000}, - {AUD_DEEMPH1_B0, 0x00000000}, - {AUD_DEEMPH1_A1, 0x00000000}, - {AUD_DEEMPH1_B1, 0x00000000}, - {AUD_OUT0_SEL, 0x0000003f}, - {AUD_OUT1_SEL, 0x0000003f}, - {AUD_DN1_AFC, 0x00000002}, - {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, - {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, - {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, - {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, - {AUD_IIR1_0_SEL, 0x0000001d}, - {AUD_IIR1_2_SEL, 0x0000001e}, - {AUD_IIR2_1_SEL, 0x00000002}, - {AUD_IIR2_2_SEL, 0x00000004}, - {AUD_IIR3_2_SEL, 0x0000000f}, - {AUD_DCOC2_SHIFT, 0x00000001}, - {AUD_IIR3_2_SHIFT, 0x00000001}, - {AUD_DEEMPH0_SRC_SEL, 0x00000014}, - {AUD_CORDIC_SHIFT_1, 0x00000006}, - {AUD_POLY0_DDS_CONSTANT, 0x000e4db2}, - {AUD_DMD_RA_DDS, 0x00f696e6}, - {AUD_IIR2_3_SEL, 0x00000025}, - {AUD_IIR1_4_SEL, 0x00000021}, - {AUD_DN1_FREQ, 0x0000c965}, - {AUD_DCOC_PASS_IN, 0x00000003}, - {AUD_DCOC_0_SRC, 0x0000001a}, - {AUD_DCOC_1_SRC, 0x0000001b}, - {AUD_DCOC1_SHIFT, 0x00000000}, - {AUD_RDSI_SEL, 0x00000009}, - {AUD_RDSQ_SEL, 0x00000009}, - {AUD_RDSI_SHIFT, 0x00000000}, - {AUD_RDSQ_SHIFT, 0x00000000}, - {AUD_POLYPH80SCALEFAC, 0x00000003}, - { /* end of list */ }, - }; - - mode |= EN_FMRADIO_EN_RDS; - - if (sap) { - dprintk("%s SAP (status: unknown)\n", __func__); - set_audio_start(core, SEL_SAP); - set_audio_registers(core, btsc_sap); - set_audio_finish(core, mode); - } else { - dprintk("%s (status: known-good)\n", __func__); - set_audio_start(core, SEL_BTSC); - set_audio_registers(core, btsc); - set_audio_finish(core, mode); - } -} - -static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode) -{ - static const struct rlist nicam_l[] = { - {AUD_AFE_12DB_EN, 0x00000001}, - {AUD_RATE_ADJ1, 0x00000060}, - {AUD_RATE_ADJ2, 0x000000F9}, - {AUD_RATE_ADJ3, 0x000001CC}, - {AUD_RATE_ADJ4, 0x000002B3}, - {AUD_RATE_ADJ5, 0x00000726}, - {AUD_DEEMPHDENOM1_R, 0x0000F3D0}, - {AUD_DEEMPHDENOM2_R, 0x00000000}, - {AUD_ERRLOGPERIOD_R, 0x00000064}, - {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF}, - {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F}, - {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F}, - {AUD_POLYPH80SCALEFAC, 0x00000003}, - {AUD_DMD_RA_DDS, 0x00C00000}, - {AUD_PLL_INT, 0x0000001E}, - {AUD_PLL_DDS, 0x00000000}, - {AUD_PLL_FRAC, 0x0000E542}, - {AUD_START_TIMER, 0x00000000}, - {AUD_DEEMPHNUMER1_R, 0x000353DE}, - {AUD_DEEMPHNUMER2_R, 0x000001B1}, - {AUD_PDF_DDS_CNST_BYTE2, 0x06}, - {AUD_PDF_DDS_CNST_BYTE1, 0x82}, - {AUD_PDF_DDS_CNST_BYTE0, 0x12}, - {AUD_QAM_MODE, 0x05}, - {AUD_PHACC_FREQ_8MSB, 0x34}, - {AUD_PHACC_FREQ_8LSB, 0x4C}, - {AUD_DEEMPHGAIN_R, 0x00006680}, - {AUD_RATE_THRES_DMD, 0x000000C0}, - { /* end of list */ }, - }; - - static const struct rlist nicam_bgdki_common[] = { - {AUD_AFE_12DB_EN, 0x00000001}, - {AUD_RATE_ADJ1, 0x00000010}, - {AUD_RATE_ADJ2, 0x00000040}, - {AUD_RATE_ADJ3, 0x00000100}, - {AUD_RATE_ADJ4, 0x00000400}, - {AUD_RATE_ADJ5, 0x00001000}, - {AUD_ERRLOGPERIOD_R, 0x00000fff}, - {AUD_ERRINTRPTTHSHLD1_R, 0x000003ff}, - {AUD_ERRINTRPTTHSHLD2_R, 0x000000ff}, - {AUD_ERRINTRPTTHSHLD3_R, 0x0000003f}, - {AUD_POLYPH80SCALEFAC, 0x00000003}, - {AUD_DEEMPHGAIN_R, 0x000023c2}, - {AUD_DEEMPHNUMER1_R, 0x0002a7bc}, - {AUD_DEEMPHNUMER2_R, 0x0003023e}, - {AUD_DEEMPHDENOM1_R, 0x0000f3d0}, - {AUD_DEEMPHDENOM2_R, 0x00000000}, - {AUD_PDF_DDS_CNST_BYTE2, 0x06}, - {AUD_PDF_DDS_CNST_BYTE1, 0x82}, - {AUD_QAM_MODE, 0x05}, - { /* end of list */ }, - }; - - static const struct rlist nicam_i[] = { - {AUD_PDF_DDS_CNST_BYTE0, 0x12}, - {AUD_PHACC_FREQ_8MSB, 0x3a}, - {AUD_PHACC_FREQ_8LSB, 0x93}, - { /* end of list */ }, - }; - - static const struct rlist nicam_default[] = { - {AUD_PDF_DDS_CNST_BYTE0, 0x16}, - {AUD_PHACC_FREQ_8MSB, 0x34}, - {AUD_PHACC_FREQ_8LSB, 0x4c}, - { /* end of list */ }, - }; - - set_audio_start(core,SEL_NICAM); - switch (core->tvaudio) { - case WW_L: - dprintk("%s SECAM-L NICAM (status: devel)\n", __func__); - set_audio_registers(core, nicam_l); - break; - case WW_I: - dprintk("%s PAL-I NICAM (status: known-good)\n", __func__); - set_audio_registers(core, nicam_bgdki_common); - set_audio_registers(core, nicam_i); - break; - case WW_NONE: - case WW_BTSC: - case WW_BG: - case WW_DK: - case WW_EIAJ: - case WW_I2SPT: - case WW_FM: - case WW_I2SADC: - case WW_M: - dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__); - set_audio_registers(core, nicam_bgdki_common); - set_audio_registers(core, nicam_default); - break; - }; - - mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS; - set_audio_finish(core, mode); -} - -static void set_audio_standard_A2(struct cx88_core *core, u32 mode) -{ - static const struct rlist a2_bgdk_common[] = { - {AUD_ERRLOGPERIOD_R, 0x00000064}, - {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff}, - {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f}, - {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f}, - {AUD_PDF_DDS_CNST_BYTE2, 0x06}, - {AUD_PDF_DDS_CNST_BYTE1, 0x82}, - {AUD_PDF_DDS_CNST_BYTE0, 0x12}, - {AUD_QAM_MODE, 0x05}, - {AUD_PHACC_FREQ_8MSB, 0x34}, - {AUD_PHACC_FREQ_8LSB, 0x4c}, - {AUD_RATE_ADJ1, 0x00000100}, - {AUD_RATE_ADJ2, 0x00000200}, - {AUD_RATE_ADJ3, 0x00000300}, - {AUD_RATE_ADJ4, 0x00000400}, - {AUD_RATE_ADJ5, 0x00000500}, - {AUD_THR_FR, 0x00000000}, - {AAGC_HYST, 0x0000001a}, - {AUD_PILOT_BQD_1_K0, 0x0000755b}, - {AUD_PILOT_BQD_1_K1, 0x00551340}, - {AUD_PILOT_BQD_1_K2, 0x006d30be}, - {AUD_PILOT_BQD_1_K3, 0xffd394af}, - {AUD_PILOT_BQD_1_K4, 0x00400000}, - {AUD_PILOT_BQD_2_K0, 0x00040000}, - {AUD_PILOT_BQD_2_K1, 0x002a4841}, - {AUD_PILOT_BQD_2_K2, 0x00400000}, - {AUD_PILOT_BQD_2_K3, 0x00000000}, - {AUD_PILOT_BQD_2_K4, 0x00000000}, - {AUD_MODE_CHG_TIMER, 0x00000040}, - {AUD_AFE_12DB_EN, 0x00000001}, - {AUD_CORDIC_SHIFT_0, 0x00000007}, - {AUD_CORDIC_SHIFT_1, 0x00000007}, - {AUD_DEEMPH0_G0, 0x00000380}, - {AUD_DEEMPH1_G0, 0x00000380}, - {AUD_DCOC_0_SRC, 0x0000001a}, - {AUD_DCOC0_SHIFT, 0x00000000}, - {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, - {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, - {AUD_DCOC_PASS_IN, 0x00000003}, - {AUD_IIR3_0_SEL, 0x00000021}, - {AUD_DN2_AFC, 0x00000002}, - {AUD_DCOC_1_SRC, 0x0000001b}, - {AUD_DCOC1_SHIFT, 0x00000000}, - {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, - {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, - {AUD_IIR3_1_SEL, 0x00000023}, - {AUD_RDSI_SEL, 0x00000017}, - {AUD_RDSI_SHIFT, 0x00000000}, - {AUD_RDSQ_SEL, 0x00000017}, - {AUD_RDSQ_SHIFT, 0x00000000}, - {AUD_PLL_INT, 0x0000001e}, - {AUD_PLL_DDS, 0x00000000}, - {AUD_PLL_FRAC, 0x0000e542}, - {AUD_POLYPH80SCALEFAC, 0x00000001}, - {AUD_START_TIMER, 0x00000000}, - { /* end of list */ }, - }; - - static const struct rlist a2_bg[] = { - {AUD_DMD_RA_DDS, 0x002a4f2f}, - {AUD_C1_UP_THR, 0x00007000}, - {AUD_C1_LO_THR, 0x00005400}, - {AUD_C2_UP_THR, 0x00005400}, - {AUD_C2_LO_THR, 0x00003000}, - { /* end of list */ }, - }; - - static const struct rlist a2_dk[] = { - {AUD_DMD_RA_DDS, 0x002a4f2f}, - {AUD_C1_UP_THR, 0x00007000}, - {AUD_C1_LO_THR, 0x00005400}, - {AUD_C2_UP_THR, 0x00005400}, - {AUD_C2_LO_THR, 0x00003000}, - {AUD_DN0_FREQ, 0x00003a1c}, - {AUD_DN2_FREQ, 0x0000d2e0}, - { /* end of list */ }, - }; - - static const struct rlist a1_i[] = { - {AUD_ERRLOGPERIOD_R, 0x00000064}, - {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff}, - {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f}, - {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f}, - {AUD_PDF_DDS_CNST_BYTE2, 0x06}, - {AUD_PDF_DDS_CNST_BYTE1, 0x82}, - {AUD_PDF_DDS_CNST_BYTE0, 0x12}, - {AUD_QAM_MODE, 0x05}, - {AUD_PHACC_FREQ_8MSB, 0x3a}, - {AUD_PHACC_FREQ_8LSB, 0x93}, - {AUD_DMD_RA_DDS, 0x002a4f2f}, - {AUD_PLL_INT, 0x0000001e}, - {AUD_PLL_DDS, 0x00000004}, - {AUD_PLL_FRAC, 0x0000e542}, - {AUD_RATE_ADJ1, 0x00000100}, - {AUD_RATE_ADJ2, 0x00000200}, - {AUD_RATE_ADJ3, 0x00000300}, - {AUD_RATE_ADJ4, 0x00000400}, - {AUD_RATE_ADJ5, 0x00000500}, - {AUD_THR_FR, 0x00000000}, - {AUD_PILOT_BQD_1_K0, 0x0000755b}, - {AUD_PILOT_BQD_1_K1, 0x00551340}, - {AUD_PILOT_BQD_1_K2, 0x006d30be}, - {AUD_PILOT_BQD_1_K3, 0xffd394af}, - {AUD_PILOT_BQD_1_K4, 0x00400000}, - {AUD_PILOT_BQD_2_K0, 0x00040000}, - {AUD_PILOT_BQD_2_K1, 0x002a4841}, - {AUD_PILOT_BQD_2_K2, 0x00400000}, - {AUD_PILOT_BQD_2_K3, 0x00000000}, - {AUD_PILOT_BQD_2_K4, 0x00000000}, - {AUD_MODE_CHG_TIMER, 0x00000060}, - {AUD_AFE_12DB_EN, 0x00000001}, - {AAGC_HYST, 0x0000000a}, - {AUD_CORDIC_SHIFT_0, 0x00000007}, - {AUD_CORDIC_SHIFT_1, 0x00000007}, - {AUD_C1_UP_THR, 0x00007000}, - {AUD_C1_LO_THR, 0x00005400}, - {AUD_C2_UP_THR, 0x00005400}, - {AUD_C2_LO_THR, 0x00003000}, - {AUD_DCOC_0_SRC, 0x0000001a}, - {AUD_DCOC0_SHIFT, 0x00000000}, - {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, - {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, - {AUD_DCOC_PASS_IN, 0x00000003}, - {AUD_IIR3_0_SEL, 0x00000021}, - {AUD_DN2_AFC, 0x00000002}, - {AUD_DCOC_1_SRC, 0x0000001b}, - {AUD_DCOC1_SHIFT, 0x00000000}, - {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, - {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, - {AUD_IIR3_1_SEL, 0x00000023}, - {AUD_DN0_FREQ, 0x000035a3}, - {AUD_DN2_FREQ, 0x000029c7}, - {AUD_CRDC0_SRC_SEL, 0x00000511}, - {AUD_IIR1_0_SEL, 0x00000001}, - {AUD_IIR1_1_SEL, 0x00000000}, - {AUD_IIR3_2_SEL, 0x00000003}, - {AUD_IIR3_2_SHIFT, 0x00000000}, - {AUD_IIR3_0_SEL, 0x00000002}, - {AUD_IIR2_0_SEL, 0x00000021}, - {AUD_IIR2_0_SHIFT, 0x00000002}, - {AUD_DEEMPH0_SRC_SEL, 0x0000000b}, - {AUD_DEEMPH1_SRC_SEL, 0x0000000b}, - {AUD_POLYPH80SCALEFAC, 0x00000001}, - {AUD_START_TIMER, 0x00000000}, - { /* end of list */ }, - }; - - static const struct rlist am_l[] = { - {AUD_ERRLOGPERIOD_R, 0x00000064}, - {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF}, - {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F}, - {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F}, - {AUD_PDF_DDS_CNST_BYTE2, 0x48}, - {AUD_PDF_DDS_CNST_BYTE1, 0x3D}, - {AUD_QAM_MODE, 0x00}, - {AUD_PDF_DDS_CNST_BYTE0, 0xf5}, - {AUD_PHACC_FREQ_8MSB, 0x3a}, - {AUD_PHACC_FREQ_8LSB, 0x4a}, - {AUD_DEEMPHGAIN_R, 0x00006680}, - {AUD_DEEMPHNUMER1_R, 0x000353DE}, - {AUD_DEEMPHNUMER2_R, 0x000001B1}, - {AUD_DEEMPHDENOM1_R, 0x0000F3D0}, - {AUD_DEEMPHDENOM2_R, 0x00000000}, - {AUD_FM_MODE_ENABLE, 0x00000007}, - {AUD_POLYPH80SCALEFAC, 0x00000003}, - {AUD_AFE_12DB_EN, 0x00000001}, - {AAGC_GAIN, 0x00000000}, - {AAGC_HYST, 0x00000018}, - {AAGC_DEF, 0x00000020}, - {AUD_DN0_FREQ, 0x00000000}, - {AUD_POLY0_DDS_CONSTANT, 0x000E4DB2}, - {AUD_DCOC_0_SRC, 0x00000021}, - {AUD_IIR1_0_SEL, 0x00000000}, - {AUD_IIR1_0_SHIFT, 0x00000007}, - {AUD_IIR1_1_SEL, 0x00000002}, - {AUD_IIR1_1_SHIFT, 0x00000000}, - {AUD_DCOC_1_SRC, 0x00000003}, - {AUD_DCOC1_SHIFT, 0x00000000}, - {AUD_DCOC_PASS_IN, 0x00000000}, - {AUD_IIR1_2_SEL, 0x00000023}, - {AUD_IIR1_2_SHIFT, 0x00000000}, - {AUD_IIR1_3_SEL, 0x00000004}, - {AUD_IIR1_3_SHIFT, 0x00000007}, - {AUD_IIR1_4_SEL, 0x00000005}, - {AUD_IIR1_4_SHIFT, 0x00000007}, - {AUD_IIR3_0_SEL, 0x00000007}, - {AUD_IIR3_0_SHIFT, 0x00000000}, - {AUD_DEEMPH0_SRC_SEL, 0x00000011}, - {AUD_DEEMPH0_SHIFT, 0x00000000}, - {AUD_DEEMPH0_G0, 0x00007000}, - {AUD_DEEMPH0_A0, 0x00000000}, - {AUD_DEEMPH0_B0, 0x00000000}, - {AUD_DEEMPH0_A1, 0x00000000}, - {AUD_DEEMPH0_B1, 0x00000000}, - {AUD_DEEMPH1_SRC_SEL, 0x00000011}, - {AUD_DEEMPH1_SHIFT, 0x00000000}, - {AUD_DEEMPH1_G0, 0x00007000}, - {AUD_DEEMPH1_A0, 0x00000000}, - {AUD_DEEMPH1_B0, 0x00000000}, - {AUD_DEEMPH1_A1, 0x00000000}, - {AUD_DEEMPH1_B1, 0x00000000}, - {AUD_OUT0_SEL, 0x0000003F}, - {AUD_OUT1_SEL, 0x0000003F}, - {AUD_DMD_RA_DDS, 0x00F5C285}, - {AUD_PLL_INT, 0x0000001E}, - {AUD_PLL_DDS, 0x00000000}, - {AUD_PLL_FRAC, 0x0000E542}, - {AUD_RATE_ADJ1, 0x00000100}, - {AUD_RATE_ADJ2, 0x00000200}, - {AUD_RATE_ADJ3, 0x00000300}, - {AUD_RATE_ADJ4, 0x00000400}, - {AUD_RATE_ADJ5, 0x00000500}, - {AUD_RATE_THRES_DMD, 0x000000C0}, - { /* end of list */ }, - }; - - static const struct rlist a2_deemph50[] = { - {AUD_DEEMPH0_G0, 0x00000380}, - {AUD_DEEMPH1_G0, 0x00000380}, - {AUD_DEEMPHGAIN_R, 0x000011e1}, - {AUD_DEEMPHNUMER1_R, 0x0002a7bc}, - {AUD_DEEMPHNUMER2_R, 0x0003023c}, - { /* end of list */ }, - }; - - set_audio_start(core, SEL_A2); - switch (core->tvaudio) { - case WW_BG: - dprintk("%s PAL-BG A1/2 (status: known-good)\n", __func__); - set_audio_registers(core, a2_bgdk_common); - set_audio_registers(core, a2_bg); - set_audio_registers(core, a2_deemph50); - break; - case WW_DK: - dprintk("%s PAL-DK A1/2 (status: known-good)\n", __func__); - set_audio_registers(core, a2_bgdk_common); - set_audio_registers(core, a2_dk); - set_audio_registers(core, a2_deemph50); - break; - case WW_I: - dprintk("%s PAL-I A1 (status: known-good)\n", __func__); - set_audio_registers(core, a1_i); - set_audio_registers(core, a2_deemph50); - break; - case WW_L: - dprintk("%s AM-L (status: devel)\n", __func__); - set_audio_registers(core, am_l); - break; - case WW_NONE: - case WW_BTSC: - case WW_EIAJ: - case WW_I2SPT: - case WW_FM: - case WW_I2SADC: - case WW_M: - dprintk("%s Warning: wrong value\n", __func__); - return; - break; - }; - - mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF; - set_audio_finish(core, mode); -} - -static void set_audio_standard_EIAJ(struct cx88_core *core) -{ - static const struct rlist eiaj[] = { - /* TODO: eiaj register settings are not there yet ... */ - - { /* end of list */ }, - }; - dprintk("%s (status: unknown)\n", __func__); - - set_audio_start(core, SEL_EIAJ); - set_audio_registers(core, eiaj); - set_audio_finish(core, EN_EIAJ_AUTO_STEREO); -} - -static void set_audio_standard_FM(struct cx88_core *core, - enum cx88_deemph_type deemph) -{ - static const struct rlist fm_deemph_50[] = { - {AUD_DEEMPH0_G0, 0x0C45}, - {AUD_DEEMPH0_A0, 0x6262}, - {AUD_DEEMPH0_B0, 0x1C29}, - {AUD_DEEMPH0_A1, 0x3FC66}, - {AUD_DEEMPH0_B1, 0x399A}, - - {AUD_DEEMPH1_G0, 0x0D80}, - {AUD_DEEMPH1_A0, 0x6262}, - {AUD_DEEMPH1_B0, 0x1C29}, - {AUD_DEEMPH1_A1, 0x3FC66}, - {AUD_DEEMPH1_B1, 0x399A}, - - {AUD_POLYPH80SCALEFAC, 0x0003}, - { /* end of list */ }, - }; - static const struct rlist fm_deemph_75[] = { - {AUD_DEEMPH0_G0, 0x091B}, - {AUD_DEEMPH0_A0, 0x6B68}, - {AUD_DEEMPH0_B0, 0x11EC}, - {AUD_DEEMPH0_A1, 0x3FC66}, - {AUD_DEEMPH0_B1, 0x399A}, - - {AUD_DEEMPH1_G0, 0x0AA0}, - {AUD_DEEMPH1_A0, 0x6B68}, - {AUD_DEEMPH1_B0, 0x11EC}, - {AUD_DEEMPH1_A1, 0x3FC66}, - {AUD_DEEMPH1_B1, 0x399A}, - - {AUD_POLYPH80SCALEFAC, 0x0003}, - { /* end of list */ }, - }; - - /* It is enough to leave default values? */ - /* No, it's not! The deemphasis registers are reset to the 75us - * values by default. Analyzing the spectrum of the decoded audio - * reveals that "no deemphasis" is the same as 75 us, while the 50 us - * setting results in less deemphasis. */ - static const struct rlist fm_no_deemph[] = { - - {AUD_POLYPH80SCALEFAC, 0x0003}, - { /* end of list */ }, - }; - - dprintk("%s (status: unknown)\n", __func__); - set_audio_start(core, SEL_FMRADIO); - - switch (deemph) { - default: - case FM_NO_DEEMPH: - set_audio_registers(core, fm_no_deemph); - break; - - case FM_DEEMPH_50: - set_audio_registers(core, fm_deemph_50); - break; - - case FM_DEEMPH_75: - set_audio_registers(core, fm_deemph_75); - break; - } - - set_audio_finish(core, EN_FMRADIO_AUTO_STEREO); -} - -/* ----------------------------------------------------------- */ - -static int cx88_detect_nicam(struct cx88_core *core) -{ - int i, j = 0; - - dprintk("start nicam autodetect.\n"); - - for (i = 0; i < 6; i++) { - /* if bit1=1 then nicam is detected */ - j += ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1); - - if (j == 1) { - dprintk("nicam is detected.\n"); - return 1; - } - - /* wait a little bit for next reading status */ - msleep(10); - } - - dprintk("nicam is not detected.\n"); - return 0; -} - -void cx88_set_tvaudio(struct cx88_core *core) -{ - switch (core->tvaudio) { - case WW_BTSC: - set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO); - break; - case WW_BG: - case WW_DK: - case WW_M: - case WW_I: - case WW_L: - /* prepare all dsp registers */ - set_audio_standard_A2(core, EN_A2_FORCE_MONO1); - - /* set nicam mode - otherwise - AUD_NICAM_STATUS2 contains wrong values */ - set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO); - if (0 == cx88_detect_nicam(core)) { - /* fall back to fm / am mono */ - set_audio_standard_A2(core, EN_A2_FORCE_MONO1); - core->audiomode_current = V4L2_TUNER_MODE_MONO; - core->use_nicam = 0; - } else { - core->use_nicam = 1; - } - break; - case WW_EIAJ: - set_audio_standard_EIAJ(core); - break; - case WW_FM: - set_audio_standard_FM(core, radio_deemphasis); - break; - case WW_I2SADC: - set_audio_start(core, 0x01); - /* - * Slave/Philips/Autobaud - * NB on Nova-S bit1 NPhilipsSony appears to be inverted: - * 0= Sony, 1=Philips - */ - cx_write(AUD_I2SINPUTCNTL, core->board.i2sinputcntl); - /* Switch to "I2S ADC mode" */ - cx_write(AUD_I2SCNTL, 0x1); - set_audio_finish(core, EN_I2SIN_ENABLE); - break; - case WW_NONE: - case WW_I2SPT: - printk("%s/0: unknown tv audio mode [%d]\n", - core->name, core->tvaudio); - break; - } - return; -} - -void cx88_newstation(struct cx88_core *core) -{ - core->audiomode_manual = UNSET; - core->last_change = jiffies; -} - -void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) -{ - static const char * const m[] = { "stereo", "dual mono", "mono", "sap" }; - static const char * const p[] = { "no pilot", "pilot c1", "pilot c2", "?" }; - u32 reg, mode, pilot; - - reg = cx_read(AUD_STATUS); - mode = reg & 0x03; - pilot = (reg >> 2) & 0x03; - - if (core->astat != reg) - dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n", - reg, m[mode], p[pilot], - aud_ctl_names[cx_read(AUD_CTL) & 63]); - core->astat = reg; - - t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP | - V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; - t->rxsubchans = UNSET; - t->audmode = V4L2_TUNER_MODE_MONO; - - switch (mode) { - case 0: - t->audmode = V4L2_TUNER_MODE_STEREO; - break; - case 1: - t->audmode = V4L2_TUNER_MODE_LANG2; - break; - case 2: - t->audmode = V4L2_TUNER_MODE_MONO; - break; - case 3: - t->audmode = V4L2_TUNER_MODE_SAP; - break; - } - - switch (core->tvaudio) { - case WW_BTSC: - case WW_BG: - case WW_DK: - case WW_M: - case WW_EIAJ: - if (!core->use_nicam) { - t->rxsubchans = cx88_dsp_detect_stereo_sap(core); - break; - } - break; - case WW_NONE: - case WW_I: - case WW_L: - case WW_I2SPT: - case WW_FM: - case WW_I2SADC: - /* nothing */ - break; - } - - /* If software stereo detection is not supported... */ - if (UNSET == t->rxsubchans) { - t->rxsubchans = V4L2_TUNER_SUB_MONO; - /* If the hardware itself detected stereo, also return - stereo as an available subchannel */ - if (V4L2_TUNER_MODE_STEREO == t->audmode) - t->rxsubchans |= V4L2_TUNER_SUB_STEREO; - } - return; -} - -void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) -{ - u32 ctl = UNSET; - u32 mask = UNSET; - - if (manual) { - core->audiomode_manual = mode; - } else { - if (UNSET != core->audiomode_manual) - return; - } - core->audiomode_current = mode; - - switch (core->tvaudio) { - case WW_BTSC: - switch (mode) { - case V4L2_TUNER_MODE_MONO: - set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_MONO); - break; - case V4L2_TUNER_MODE_LANG1: - set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO); - break; - case V4L2_TUNER_MODE_LANG2: - set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP); - break; - case V4L2_TUNER_MODE_STEREO: - case V4L2_TUNER_MODE_LANG1_LANG2: - set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO); - break; - } - break; - case WW_BG: - case WW_DK: - case WW_M: - case WW_I: - case WW_L: - if (1 == core->use_nicam) { - switch (mode) { - case V4L2_TUNER_MODE_MONO: - case V4L2_TUNER_MODE_LANG1: - set_audio_standard_NICAM(core, - EN_NICAM_FORCE_MONO1); - break; - case V4L2_TUNER_MODE_LANG2: - set_audio_standard_NICAM(core, - EN_NICAM_FORCE_MONO2); - break; - case V4L2_TUNER_MODE_STEREO: - case V4L2_TUNER_MODE_LANG1_LANG2: - set_audio_standard_NICAM(core, - EN_NICAM_FORCE_STEREO); - break; - } - } else { - if ((core->tvaudio == WW_I) || (core->tvaudio == WW_L)) { - /* fall back to fm / am mono */ - set_audio_standard_A2(core, EN_A2_FORCE_MONO1); - } else { - /* TODO: Add A2 autodection */ - mask = 0x3f; - switch (mode) { - case V4L2_TUNER_MODE_MONO: - case V4L2_TUNER_MODE_LANG1: - ctl = EN_A2_FORCE_MONO1; - break; - case V4L2_TUNER_MODE_LANG2: - ctl = EN_A2_FORCE_MONO2; - break; - case V4L2_TUNER_MODE_STEREO: - case V4L2_TUNER_MODE_LANG1_LANG2: - ctl = EN_A2_FORCE_STEREO; - break; - } - } - } - break; - case WW_FM: - switch (mode) { - case V4L2_TUNER_MODE_MONO: - ctl = EN_FMRADIO_FORCE_MONO; - mask = 0x3f; - break; - case V4L2_TUNER_MODE_STEREO: - ctl = EN_FMRADIO_AUTO_STEREO; - mask = 0x3f; - break; - } - break; - case WW_I2SADC: - case WW_NONE: - case WW_EIAJ: - case WW_I2SPT: - /* DO NOTHING */ - break; - } - - if (UNSET != ctl) { - dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x " - "[status=0x%x,ctl=0x%x,vol=0x%x]\n", - mask, ctl, cx_read(AUD_STATUS), - cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL)); - cx_andor(AUD_CTL, mask, ctl); - } - return; -} - -int cx88_audio_thread(void *data) -{ - struct cx88_core *core = data; - struct v4l2_tuner t; - u32 mode = 0; - - dprintk("cx88: tvaudio thread started\n"); - set_freezable(); - for (;;) { - msleep_interruptible(1000); - if (kthread_should_stop()) - break; - try_to_freeze(); - - switch (core->tvaudio) { - case WW_BG: - case WW_DK: - case WW_M: - case WW_I: - case WW_L: - if (core->use_nicam) - goto hw_autodetect; - - /* just monitor the audio status for now ... */ - memset(&t, 0, sizeof(t)); - cx88_get_stereo(core, &t); - - if (UNSET != core->audiomode_manual) - /* manually set, don't do anything. */ - continue; - - /* monitor signal and set stereo if available */ - if (t.rxsubchans & V4L2_TUNER_SUB_STEREO) - mode = V4L2_TUNER_MODE_STEREO; - else - mode = V4L2_TUNER_MODE_MONO; - if (mode == core->audiomode_current) - continue; - /* automatically switch to best available mode */ - cx88_set_stereo(core, mode, 0); - break; - case WW_NONE: - case WW_BTSC: - case WW_EIAJ: - case WW_I2SPT: - case WW_FM: - case WW_I2SADC: -hw_autodetect: - /* stereo autodetection is supported by hardware so - we don't need to do it manually. Do nothing. */ - break; - } - } - - dprintk("cx88: tvaudio thread exiting\n"); - return 0; -} - -/* ----------------------------------------------------------- */ - -EXPORT_SYMBOL(cx88_set_tvaudio); -EXPORT_SYMBOL(cx88_newstation); -EXPORT_SYMBOL(cx88_set_stereo); -EXPORT_SYMBOL(cx88_get_stereo); -EXPORT_SYMBOL(cx88_audio_thread); - -/* - * Local variables: - * c-basic-offset: 8 - * End: - * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off - */ diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c deleted file mode 100644 index f8f8389c0362..000000000000 --- a/drivers/media/video/cx88/cx88-vbi.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> - -#include "cx88.h" - -static unsigned int vbibufs = 4; -module_param(vbibufs,int,0644); -MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32"); - -static unsigned int vbi_debug; -module_param(vbi_debug,int,0644); -MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]"); - -#define dprintk(level,fmt, arg...) if (vbi_debug >= level) \ - printk(KERN_DEBUG "%s: " fmt, dev->core->name , ## arg) - -/* ------------------------------------------------------------------ */ - -int cx8800_vbi_fmt (struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx8800_fh *fh = priv; - struct cx8800_dev *dev = fh->dev; - - f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; - f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; - f->fmt.vbi.offset = 244; - f->fmt.vbi.count[0] = VBI_LINE_COUNT; - f->fmt.vbi.count[1] = VBI_LINE_COUNT; - - if (dev->core->tvnorm & V4L2_STD_525_60) { - /* ntsc */ - f->fmt.vbi.sampling_rate = 28636363; - f->fmt.vbi.start[0] = 10; - f->fmt.vbi.start[1] = 273; - - } else if (dev->core->tvnorm & V4L2_STD_625_50) { - /* pal */ - f->fmt.vbi.sampling_rate = 35468950; - f->fmt.vbi.start[0] = 7 -1; - f->fmt.vbi.start[1] = 319 -1; - } - return 0; -} - -static int cx8800_start_vbi_dma(struct cx8800_dev *dev, - struct cx88_dmaqueue *q, - struct cx88_buffer *buf) -{ - struct cx88_core *core = dev->core; - - /* setup fifo + format */ - cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH24], - buf->vb.width, buf->risc.dma); - - cx_write(MO_VBOS_CONTROL, ( (1 << 18) | // comb filter delay fixup - (1 << 15) | // enable vbi capture - (1 << 11) )); - - /* reset counter */ - cx_write(MO_VBI_GPCNTRL, GP_COUNT_CONTROL_RESET); - q->count = 1; - - /* enable irqs */ - cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT); - cx_set(MO_VID_INTMSK, 0x0f0088); - - /* enable capture */ - cx_set(VID_CAPTURE_CONTROL,0x18); - - /* start dma */ - cx_set(MO_DEV_CNTRL2, (1<<5)); - cx_set(MO_VID_DMACNTRL, 0x88); - - return 0; -} - -int cx8800_stop_vbi_dma(struct cx8800_dev *dev) -{ - struct cx88_core *core = dev->core; - - /* stop dma */ - cx_clear(MO_VID_DMACNTRL, 0x88); - - /* disable capture */ - cx_clear(VID_CAPTURE_CONTROL,0x18); - - /* disable irqs */ - cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT); - cx_clear(MO_VID_INTMSK, 0x0f0088); - return 0; -} - -int cx8800_restart_vbi_queue(struct cx8800_dev *dev, - struct cx88_dmaqueue *q) -{ - struct cx88_buffer *buf; - - if (list_empty(&q->active)) - return 0; - - buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); - dprintk(2,"restart_queue [%p/%d]: restart dma\n", - buf, buf->vb.i); - cx8800_start_vbi_dma(dev, q, buf); - list_for_each_entry(buf, &q->active, vb.queue) - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - return 0; -} - -void cx8800_vbi_timeout(unsigned long data) -{ - struct cx8800_dev *dev = (struct cx8800_dev*)data; - struct cx88_core *core = dev->core; - struct cx88_dmaqueue *q = &dev->vbiq; - struct cx88_buffer *buf; - unsigned long flags; - - cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH24]); - - cx_clear(MO_VID_DMACNTRL, 0x88); - cx_clear(VID_CAPTURE_CONTROL, 0x18); - - spin_lock_irqsave(&dev->slock,flags); - while (!list_empty(&q->active)) { - buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); - list_del(&buf->vb.queue); - buf->vb.state = VIDEOBUF_ERROR; - wake_up(&buf->vb.done); - printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->core->name, - buf, buf->vb.i, (unsigned long)buf->risc.dma); - } - cx8800_restart_vbi_queue(dev,q); - spin_unlock_irqrestore(&dev->slock,flags); -} - -/* ------------------------------------------------------------------ */ - -static int -vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) -{ - *size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2; - if (0 == *count) - *count = vbibufs; - if (*count < 2) - *count = 2; - if (*count > 32) - *count = 32; - return 0; -} - -static int -vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct cx8800_fh *fh = q->priv_data; - struct cx8800_dev *dev = fh->dev; - struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); - unsigned int size; - int rc; - - size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2; - if (0 != buf->vb.baddr && buf->vb.bsize < size) - return -EINVAL; - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); - buf->vb.width = VBI_LINE_LENGTH; - buf->vb.height = VBI_LINE_COUNT; - buf->vb.size = size; - buf->vb.field = V4L2_FIELD_SEQ_TB; - - if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) - goto fail; - cx88_risc_buffer(dev->pci, &buf->risc, - dma->sglist, - 0, buf->vb.width * buf->vb.height, - buf->vb.width, 0, - buf->vb.height); - } - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - - fail: - cx88_free_buffer(q,buf); - return rc; -} - -static void -vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); - struct cx88_buffer *prev; - struct cx8800_fh *fh = vq->priv_data; - struct cx8800_dev *dev = fh->dev; - struct cx88_dmaqueue *q = &dev->vbiq; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - - if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue,&q->active); - cx8800_start_vbi_dma(dev, q, buf); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2,"[%p/%d] vbi_queue - first active\n", - buf, buf->vb.i); - - } else { - prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue); - list_add_tail(&buf->vb.queue,&q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - dprintk(2,"[%p/%d] buffer_queue - append to active\n", - buf, buf->vb.i); - } -} - -static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); - - cx88_free_buffer(q,buf); -} - -const struct videobuf_queue_ops cx8800_vbi_qops = { - .buf_setup = vbi_setup, - .buf_prepare = vbi_prepare, - .buf_queue = vbi_queue, - .buf_release = vbi_release, -}; - -/* ------------------------------------------------------------------ */ -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c deleted file mode 100644 index f6fcc7e763ab..000000000000 --- a/drivers/media/video/cx88/cx88-video.c +++ /dev/null @@ -1,2075 +0,0 @@ -/* - * - * device driver for Conexant 2388x based TV cards - * video4linux video interface - * - * (c) 2003-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] - * - * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org> - * - Multituner support - * - video_ioctl2 conversion - * - PAL/M fixes - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/init.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/kmod.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/dma-mapping.h> -#include <linux/delay.h> -#include <linux/kthread.h> -#include <asm/div64.h> - -#include "cx88.h" -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-event.h> -#include <media/wm8775.h> - -MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); -MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(CX88_VERSION); - -/* ------------------------------------------------------------------ */ - -static unsigned int video_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; -static unsigned int vbi_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; -static unsigned int radio_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; - -module_param_array(video_nr, int, NULL, 0444); -module_param_array(vbi_nr, int, NULL, 0444); -module_param_array(radio_nr, int, NULL, 0444); - -MODULE_PARM_DESC(video_nr,"video device numbers"); -MODULE_PARM_DESC(vbi_nr,"vbi device numbers"); -MODULE_PARM_DESC(radio_nr,"radio device numbers"); - -static unsigned int video_debug; -module_param(video_debug,int,0644); -MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); - -static unsigned int irq_debug; -module_param(irq_debug,int,0644); -MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]"); - -static unsigned int vid_limit = 16; -module_param(vid_limit,int,0644); -MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); - -#define dprintk(level,fmt, arg...) if (video_debug >= level) \ - printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) - -/* ------------------------------------------------------------------- */ -/* static data */ - -static const struct cx8800_fmt formats[] = { - { - .name = "8 bpp, gray", - .fourcc = V4L2_PIX_FMT_GREY, - .cxformat = ColorFormatY8, - .depth = 8, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "15 bpp RGB, le", - .fourcc = V4L2_PIX_FMT_RGB555, - .cxformat = ColorFormatRGB15, - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "15 bpp RGB, be", - .fourcc = V4L2_PIX_FMT_RGB555X, - .cxformat = ColorFormatRGB15 | ColorFormatBSWAP, - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "16 bpp RGB, le", - .fourcc = V4L2_PIX_FMT_RGB565, - .cxformat = ColorFormatRGB16, - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "16 bpp RGB, be", - .fourcc = V4L2_PIX_FMT_RGB565X, - .cxformat = ColorFormatRGB16 | ColorFormatBSWAP, - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "24 bpp RGB, le", - .fourcc = V4L2_PIX_FMT_BGR24, - .cxformat = ColorFormatRGB24, - .depth = 24, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "32 bpp RGB, le", - .fourcc = V4L2_PIX_FMT_BGR32, - .cxformat = ColorFormatRGB32, - .depth = 32, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "32 bpp RGB, be", - .fourcc = V4L2_PIX_FMT_RGB32, - .cxformat = ColorFormatRGB32 | ColorFormatBSWAP | ColorFormatWSWAP, - .depth = 32, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "4:2:2, packed, YUYV", - .fourcc = V4L2_PIX_FMT_YUYV, - .cxformat = ColorFormatYUY2, - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, - },{ - .name = "4:2:2, packed, UYVY", - .fourcc = V4L2_PIX_FMT_UYVY, - .cxformat = ColorFormatYUY2 | ColorFormatBSWAP, - .depth = 16, - .flags = FORMAT_FLAGS_PACKED, - }, -}; - -static const struct cx8800_fmt* 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; -} - -/* ------------------------------------------------------------------- */ - -struct cx88_ctrl { - /* control information */ - u32 id; - s32 minimum; - s32 maximum; - u32 step; - s32 default_value; - - /* control register information */ - u32 off; - u32 reg; - u32 sreg; - u32 mask; - u32 shift; -}; - -static const struct cx88_ctrl cx8800_vid_ctls[] = { - /* --- video --- */ - { - .id = V4L2_CID_BRIGHTNESS, - .minimum = 0x00, - .maximum = 0xff, - .step = 1, - .default_value = 0x7f, - .off = 128, - .reg = MO_CONTR_BRIGHT, - .mask = 0x00ff, - .shift = 0, - },{ - .id = V4L2_CID_CONTRAST, - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x3f, - .off = 0, - .reg = MO_CONTR_BRIGHT, - .mask = 0xff00, - .shift = 8, - },{ - .id = V4L2_CID_HUE, - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x7f, - .off = 128, - .reg = MO_HUE, - .mask = 0x00ff, - .shift = 0, - },{ - /* strictly, this only describes only U saturation. - * V saturation is handled specially through code. - */ - .id = V4L2_CID_SATURATION, - .minimum = 0, - .maximum = 0xff, - .step = 1, - .default_value = 0x7f, - .off = 0, - .reg = MO_UV_SATURATION, - .mask = 0x00ff, - .shift = 0, - }, { - .id = V4L2_CID_SHARPNESS, - .minimum = 0, - .maximum = 4, - .step = 1, - .default_value = 0x0, - .off = 0, - /* NOTE: the value is converted and written to both even - and odd registers in the code */ - .reg = MO_FILTER_ODD, - .mask = 7 << 7, - .shift = 7, - }, { - .id = V4L2_CID_CHROMA_AGC, - .minimum = 0, - .maximum = 1, - .default_value = 0x1, - .reg = MO_INPUT_FORMAT, - .mask = 1 << 10, - .shift = 10, - }, { - .id = V4L2_CID_COLOR_KILLER, - .minimum = 0, - .maximum = 1, - .default_value = 0x1, - .reg = MO_INPUT_FORMAT, - .mask = 1 << 9, - .shift = 9, - }, { - .id = V4L2_CID_BAND_STOP_FILTER, - .minimum = 0, - .maximum = 1, - .step = 1, - .default_value = 0x0, - .off = 0, - .reg = MO_HTOTAL, - .mask = 3 << 11, - .shift = 11, - } -}; - -static const struct cx88_ctrl cx8800_aud_ctls[] = { - { - /* --- audio --- */ - .id = V4L2_CID_AUDIO_MUTE, - .minimum = 0, - .maximum = 1, - .default_value = 1, - .reg = AUD_VOL_CTL, - .sreg = SHADOW_AUD_VOL_CTL, - .mask = (1 << 6), - .shift = 6, - },{ - .id = V4L2_CID_AUDIO_VOLUME, - .minimum = 0, - .maximum = 0x3f, - .step = 1, - .default_value = 0x3f, - .reg = AUD_VOL_CTL, - .sreg = SHADOW_AUD_VOL_CTL, - .mask = 0x3f, - .shift = 0, - },{ - .id = V4L2_CID_AUDIO_BALANCE, - .minimum = 0, - .maximum = 0x7f, - .step = 1, - .default_value = 0x40, - .reg = AUD_BAL_CTL, - .sreg = SHADOW_AUD_BAL_CTL, - .mask = 0x7f, - .shift = 0, - } -}; - -enum { - CX8800_VID_CTLS = ARRAY_SIZE(cx8800_vid_ctls), - CX8800_AUD_CTLS = ARRAY_SIZE(cx8800_aud_ctls), -}; - -/* ------------------------------------------------------------------- */ -/* resource management */ - -static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bit) -{ - struct cx88_core *core = dev->core; - if (fh->resources & bit) - /* have it already allocated */ - return 1; - - /* is it free? */ - mutex_lock(&core->lock); - if (dev->resources & bit) { - /* no, someone else uses it */ - mutex_unlock(&core->lock); - return 0; - } - /* it's free, grab it */ - fh->resources |= bit; - dev->resources |= bit; - dprintk(1,"res: get %d\n",bit); - mutex_unlock(&core->lock); - return 1; -} - -static -int res_check(struct cx8800_fh *fh, unsigned int bit) -{ - return (fh->resources & bit); -} - -static -int res_locked(struct cx8800_dev *dev, unsigned int bit) -{ - return (dev->resources & bit); -} - -static -void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits) -{ - struct cx88_core *core = dev->core; - BUG_ON((fh->resources & bits) != bits); - - mutex_lock(&core->lock); - fh->resources &= ~bits; - dev->resources &= ~bits; - dprintk(1,"res: put %d\n",bits); - mutex_unlock(&core->lock); -} - -/* ------------------------------------------------------------------ */ - -int cx88_video_mux(struct cx88_core *core, unsigned int input) -{ - /* struct cx88_core *core = dev->core; */ - - dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n", - input, INPUT(input).vmux, - INPUT(input).gpio0,INPUT(input).gpio1, - INPUT(input).gpio2,INPUT(input).gpio3); - core->input = input; - cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input).vmux << 14); - cx_write(MO_GP3_IO, INPUT(input).gpio3); - cx_write(MO_GP0_IO, INPUT(input).gpio0); - cx_write(MO_GP1_IO, INPUT(input).gpio1); - cx_write(MO_GP2_IO, INPUT(input).gpio2); - - switch (INPUT(input).type) { - case CX88_VMUX_SVIDEO: - cx_set(MO_AFECFG_IO, 0x00000001); - cx_set(MO_INPUT_FORMAT, 0x00010010); - cx_set(MO_FILTER_EVEN, 0x00002020); - cx_set(MO_FILTER_ODD, 0x00002020); - break; - default: - cx_clear(MO_AFECFG_IO, 0x00000001); - cx_clear(MO_INPUT_FORMAT, 0x00010010); - cx_clear(MO_FILTER_EVEN, 0x00002020); - cx_clear(MO_FILTER_ODD, 0x00002020); - break; - } - - /* if there are audioroutes defined, we have an external - ADC to deal with audio */ - if (INPUT(input).audioroute) { - /* The wm8775 module has the "2" route hardwired into - the initialization. Some boards may use different - routes for different inputs. HVR-1300 surely does */ - if (core->board.audio_chip && - core->board.audio_chip == V4L2_IDENT_WM8775) { - call_all(core, audio, s_routing, - INPUT(input).audioroute, 0, 0); - } - /* cx2388's C-ADC is connected to the tuner only. - When used with S-Video, that ADC is busy dealing with - chroma, so an external must be used for baseband audio */ - if (INPUT(input).type != CX88_VMUX_TELEVISION && - INPUT(input).type != CX88_VMUX_CABLE) { - /* "I2S ADC mode" */ - core->tvaudio = WW_I2SADC; - cx88_set_tvaudio(core); - } else { - /* Normal mode */ - cx_write(AUD_I2SCNTL, 0x0); - cx_clear(AUD_CTL, EN_I2SIN_ENABLE); - } - } - - return 0; -} -EXPORT_SYMBOL(cx88_video_mux); - -/* ------------------------------------------------------------------ */ - -static int start_video_dma(struct cx8800_dev *dev, - struct cx88_dmaqueue *q, - struct cx88_buffer *buf) -{ - struct cx88_core *core = dev->core; - - /* setup fifo + format */ - cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], - buf->bpl, buf->risc.dma); - cx88_set_scale(core, buf->vb.width, buf->vb.height, buf->vb.field); - cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma); - - /* reset counter */ - cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET); - q->count = 1; - - /* enable irqs */ - cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT); - - /* Enables corresponding bits at PCI_INT_STAT: - bits 0 to 4: video, audio, transport stream, VIP, Host - bit 7: timer - bits 8 and 9: DMA complete for: SRC, DST - bits 10 and 11: BERR signal asserted for RISC: RD, WR - bits 12 to 15: BERR signal asserted for: BRDG, SRC, DST, IPB - */ - cx_set(MO_VID_INTMSK, 0x0f0011); - - /* enable capture */ - cx_set(VID_CAPTURE_CONTROL,0x06); - - /* start dma */ - cx_set(MO_DEV_CNTRL2, (1<<5)); - cx_set(MO_VID_DMACNTRL, 0x11); /* Planar Y and packed FIFO and RISC enable */ - - return 0; -} - -#ifdef CONFIG_PM -static int stop_video_dma(struct cx8800_dev *dev) -{ - struct cx88_core *core = dev->core; - - /* stop dma */ - cx_clear(MO_VID_DMACNTRL, 0x11); - - /* disable capture */ - cx_clear(VID_CAPTURE_CONTROL,0x06); - - /* disable irqs */ - cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT); - cx_clear(MO_VID_INTMSK, 0x0f0011); - return 0; -} -#endif - -static int restart_video_queue(struct cx8800_dev *dev, - struct cx88_dmaqueue *q) -{ - struct cx88_core *core = dev->core; - struct cx88_buffer *buf, *prev; - - if (!list_empty(&q->active)) { - buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); - dprintk(2,"restart_queue [%p/%d]: restart dma\n", - buf, buf->vb.i); - start_video_dma(dev, q, buf); - list_for_each_entry(buf, &q->active, vb.queue) - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - return 0; - } - - prev = NULL; - for (;;) { - if (list_empty(&q->queued)) - return 0; - buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); - if (NULL == prev) { - list_move_tail(&buf->vb.queue, &q->active); - start_video_dma(dev, q, buf); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2,"[%p/%d] restart_queue - first active\n", - buf,buf->vb.i); - - } else if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_move_tail(&buf->vb.queue, &q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - dprintk(2,"[%p/%d] restart_queue - move to active\n", - buf,buf->vb.i); - } else { - return 0; - } - prev = buf; - } -} - -/* ------------------------------------------------------------------ */ - -static int -buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) -{ - struct cx8800_fh *fh = q->priv_data; - struct cx8800_dev *dev = fh->dev; - - *size = dev->fmt->depth * dev->width * dev->height >> 3; - if (0 == *count) - *count = 32; - if (*size * *count > vid_limit * 1024 * 1024) - *count = (vid_limit * 1024 * 1024) / *size; - return 0; -} - -static int -buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct cx8800_fh *fh = q->priv_data; - struct cx8800_dev *dev = fh->dev; - struct cx88_core *core = dev->core; - struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); - struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); - int rc, init_buffer = 0; - - BUG_ON(NULL == dev->fmt); - if (dev->width < 48 || dev->width > norm_maxw(core->tvnorm) || - dev->height < 32 || dev->height > norm_maxh(core->tvnorm)) - return -EINVAL; - buf->vb.size = (dev->width * dev->height * dev->fmt->depth) >> 3; - if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) - return -EINVAL; - - if (buf->fmt != dev->fmt || - buf->vb.width != dev->width || - buf->vb.height != dev->height || - buf->vb.field != field) { - buf->fmt = dev->fmt; - buf->vb.width = dev->width; - buf->vb.height = dev->height; - buf->vb.field = field; - init_buffer = 1; - } - - if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { - init_buffer = 1; - if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) - goto fail; - } - - if (init_buffer) { - buf->bpl = buf->vb.width * buf->fmt->depth >> 3; - switch (buf->vb.field) { - case V4L2_FIELD_TOP: - cx88_risc_buffer(dev->pci, &buf->risc, - dma->sglist, 0, UNSET, - buf->bpl, 0, buf->vb.height); - break; - case V4L2_FIELD_BOTTOM: - cx88_risc_buffer(dev->pci, &buf->risc, - dma->sglist, UNSET, 0, - buf->bpl, 0, buf->vb.height); - break; - case V4L2_FIELD_INTERLACED: - cx88_risc_buffer(dev->pci, &buf->risc, - dma->sglist, 0, buf->bpl, - buf->bpl, buf->bpl, - buf->vb.height >> 1); - break; - case V4L2_FIELD_SEQ_TB: - cx88_risc_buffer(dev->pci, &buf->risc, - dma->sglist, - 0, buf->bpl * (buf->vb.height >> 1), - buf->bpl, 0, - buf->vb.height >> 1); - break; - case V4L2_FIELD_SEQ_BT: - cx88_risc_buffer(dev->pci, &buf->risc, - dma->sglist, - buf->bpl * (buf->vb.height >> 1), 0, - buf->bpl, 0, - buf->vb.height >> 1); - break; - default: - BUG(); - } - } - dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", - buf, buf->vb.i, - dev->width, dev->height, dev->fmt->depth, dev->fmt->name, - (unsigned long)buf->risc.dma); - - buf->vb.state = VIDEOBUF_PREPARED; - return 0; - - fail: - cx88_free_buffer(q,buf); - return rc; -} - -static void -buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) -{ - struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); - struct cx88_buffer *prev; - struct cx8800_fh *fh = vq->priv_data; - struct cx8800_dev *dev = fh->dev; - struct cx88_core *core = dev->core; - struct cx88_dmaqueue *q = &dev->vidq; - - /* add jump to stopper */ - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); - buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue,&q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2,"[%p/%d] buffer_queue - append to queued\n", - buf, buf->vb.i); - - } else if (list_empty(&q->active)) { - list_add_tail(&buf->vb.queue,&q->active); - start_video_dma(dev, q, buf); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); - dprintk(2,"[%p/%d] buffer_queue - first active\n", - buf, buf->vb.i); - - } else { - prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue); - if (prev->vb.width == buf->vb.width && - prev->vb.height == buf->vb.height && - prev->fmt == buf->fmt) { - list_add_tail(&buf->vb.queue,&q->active); - buf->vb.state = VIDEOBUF_ACTIVE; - buf->count = q->count++; - prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); - dprintk(2,"[%p/%d] buffer_queue - append to active\n", - buf, buf->vb.i); - - } else { - list_add_tail(&buf->vb.queue,&q->queued); - buf->vb.state = VIDEOBUF_QUEUED; - dprintk(2,"[%p/%d] buffer_queue - first queued\n", - buf, buf->vb.i); - } - } -} - -static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) -{ - struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); - - cx88_free_buffer(q,buf); -} - -static const struct videobuf_queue_ops cx8800_video_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, -}; - -/* ------------------------------------------------------------------ */ - - -/* ------------------------------------------------------------------ */ - -static struct videobuf_queue *get_queue(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx8800_fh *fh = file->private_data; - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - return &fh->vidq; - case VFL_TYPE_VBI: - return &fh->vbiq; - default: - BUG(); - return NULL; - } -} - -static int get_resource(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - return RESOURCE_VIDEO; - case VFL_TYPE_VBI: - return RESOURCE_VBI; - default: - BUG(); - return 0; - } -} - -static int video_open(struct file *file) -{ - struct video_device *vdev = video_devdata(file); - struct cx8800_dev *dev = video_drvdata(file); - struct cx88_core *core = dev->core; - struct cx8800_fh *fh; - enum v4l2_buf_type type = 0; - int radio = 0; - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - break; - case VFL_TYPE_VBI: - type = V4L2_BUF_TYPE_VBI_CAPTURE; - break; - case VFL_TYPE_RADIO: - radio = 1; - break; - } - - dprintk(1, "open dev=%s radio=%d type=%s\n", - video_device_node_name(vdev), radio, v4l2_type_names[type]); - - /* allocate + initialize per filehandle data */ - fh = kzalloc(sizeof(*fh),GFP_KERNEL); - if (unlikely(!fh)) - return -ENOMEM; - - v4l2_fh_init(&fh->fh, vdev); - file->private_data = fh; - fh->dev = dev; - - mutex_lock(&core->lock); - - videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_FIELD_INTERLACED, - sizeof(struct cx88_buffer), - fh, NULL); - videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops, - &dev->pci->dev, &dev->slock, - V4L2_BUF_TYPE_VBI_CAPTURE, - V4L2_FIELD_SEQ_TB, - sizeof(struct cx88_buffer), - fh, NULL); - - if (vdev->vfl_type == VFL_TYPE_RADIO) { - dprintk(1,"video_open: setting radio device\n"); - cx_write(MO_GP3_IO, core->board.radio.gpio3); - cx_write(MO_GP0_IO, core->board.radio.gpio0); - cx_write(MO_GP1_IO, core->board.radio.gpio1); - cx_write(MO_GP2_IO, core->board.radio.gpio2); - if (core->board.radio.audioroute) { - if(core->board.audio_chip && - core->board.audio_chip == V4L2_IDENT_WM8775) { - call_all(core, audio, s_routing, - core->board.radio.audioroute, 0, 0); - } - /* "I2S ADC mode" */ - core->tvaudio = WW_I2SADC; - cx88_set_tvaudio(core); - } else { - /* FM Mode */ - core->tvaudio = WW_FM; - cx88_set_tvaudio(core); - cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); - } - call_all(core, tuner, s_radio); - } - - core->users++; - mutex_unlock(&core->lock); - v4l2_fh_add(&fh->fh); - - return 0; -} - -static ssize_t -video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) -{ - struct video_device *vdev = video_devdata(file); - struct cx8800_fh *fh = file->private_data; - - switch (vdev->vfl_type) { - case VFL_TYPE_GRABBER: - if (res_locked(fh->dev,RESOURCE_VIDEO)) - return -EBUSY; - return videobuf_read_one(&fh->vidq, data, count, ppos, - file->f_flags & O_NONBLOCK); - case VFL_TYPE_VBI: - if (!res_get(fh->dev,fh,RESOURCE_VBI)) - return -EBUSY; - return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1, - file->f_flags & O_NONBLOCK); - default: - BUG(); - return 0; - } -} - -static unsigned int -video_poll(struct file *file, struct poll_table_struct *wait) -{ - struct video_device *vdev = video_devdata(file); - struct cx8800_fh *fh = file->private_data; - struct cx88_buffer *buf; - unsigned int rc = v4l2_ctrl_poll(file, wait); - - if (vdev->vfl_type == VFL_TYPE_VBI) { - if (!res_get(fh->dev,fh,RESOURCE_VBI)) - return rc | POLLERR; - return rc | videobuf_poll_stream(file, &fh->vbiq, wait); - } - mutex_lock(&fh->vidq.vb_lock); - if (res_check(fh,RESOURCE_VIDEO)) { - /* streaming capture */ - if (list_empty(&fh->vidq.stream)) - goto done; - buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream); - } else { - /* read() capture */ - buf = (struct cx88_buffer*)fh->vidq.read_buf; - if (NULL == buf) - goto done; - } - poll_wait(file, &buf->vb.done, wait); - if (buf->vb.state == VIDEOBUF_DONE || - buf->vb.state == VIDEOBUF_ERROR) - rc |= POLLIN|POLLRDNORM; -done: - mutex_unlock(&fh->vidq.vb_lock); - return rc; -} - -static int video_release(struct file *file) -{ - struct cx8800_fh *fh = file->private_data; - struct cx8800_dev *dev = fh->dev; - - /* turn off overlay */ - if (res_check(fh, RESOURCE_OVERLAY)) { - /* FIXME */ - res_free(dev,fh,RESOURCE_OVERLAY); - } - - /* stop video capture */ - if (res_check(fh, RESOURCE_VIDEO)) { - videobuf_queue_cancel(&fh->vidq); - res_free(dev,fh,RESOURCE_VIDEO); - } - if (fh->vidq.read_buf) { - buffer_release(&fh->vidq,fh->vidq.read_buf); - kfree(fh->vidq.read_buf); - } - - /* stop vbi capture */ - if (res_check(fh, RESOURCE_VBI)) { - videobuf_stop(&fh->vbiq); - res_free(dev,fh,RESOURCE_VBI); - } - - videobuf_mmap_free(&fh->vidq); - videobuf_mmap_free(&fh->vbiq); - - mutex_lock(&dev->core->lock); - v4l2_fh_del(&fh->fh); - v4l2_fh_exit(&fh->fh); - file->private_data = NULL; - kfree(fh); - - dev->core->users--; - if (!dev->core->users) - call_all(dev->core, core, s_power, 0); - mutex_unlock(&dev->core->lock); - - return 0; -} - -static int -video_mmap(struct file *file, struct vm_area_struct * vma) -{ - return videobuf_mmap_mapper(get_queue(file), vma); -} - -/* ------------------------------------------------------------------ */ -/* VIDEO CTRL IOCTLS */ - -static int cx8800_s_vid_ctrl(struct v4l2_ctrl *ctrl) -{ - struct cx88_core *core = - container_of(ctrl->handler, struct cx88_core, video_hdl); - const struct cx88_ctrl *cc = ctrl->priv; - u32 value, mask; - - mask = cc->mask; - switch (ctrl->id) { - case V4L2_CID_SATURATION: - /* special v_sat handling */ - - value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; - - if (core->tvnorm & V4L2_STD_SECAM) { - /* For SECAM, both U and V sat should be equal */ - value = value << 8 | value; - } else { - /* Keeps U Saturation proportional to V Sat */ - value = (value * 0x5a) / 0x7f << 8 | value; - } - mask = 0xffff; - break; - case V4L2_CID_SHARPNESS: - /* 0b000, 0b100, 0b101, 0b110, or 0b111 */ - value = (ctrl->val < 1 ? 0 : ((ctrl->val + 3) << 7)); - /* needs to be set for both fields */ - cx_andor(MO_FILTER_EVEN, mask, value); - break; - case V4L2_CID_CHROMA_AGC: - value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; - break; - default: - value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; - break; - } - dprintk(1, "set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", - ctrl->id, ctrl->name, ctrl->val, cc->reg, value, - mask, cc->sreg ? " [shadowed]" : ""); - if (cc->sreg) - cx_sandor(cc->sreg, cc->reg, mask, value); - else - cx_andor(cc->reg, mask, value); - return 0; -} - -static int cx8800_s_aud_ctrl(struct v4l2_ctrl *ctrl) -{ - struct cx88_core *core = - container_of(ctrl->handler, struct cx88_core, audio_hdl); - const struct cx88_ctrl *cc = ctrl->priv; - u32 value,mask; - - /* Pass changes onto any WM8775 */ - if (core->board.audio_chip == V4L2_IDENT_WM8775) { - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - wm8775_s_ctrl(core, ctrl->id, ctrl->val); - break; - case V4L2_CID_AUDIO_VOLUME: - wm8775_s_ctrl(core, ctrl->id, (ctrl->val) ? - (0x90 + ctrl->val) << 8 : 0); - break; - case V4L2_CID_AUDIO_BALANCE: - wm8775_s_ctrl(core, ctrl->id, ctrl->val << 9); - break; - default: - break; - } - } - - mask = cc->mask; - switch (ctrl->id) { - case V4L2_CID_AUDIO_BALANCE: - value = (ctrl->val < 0x40) ? (0x7f - ctrl->val) : (ctrl->val - 0x40); - break; - case V4L2_CID_AUDIO_VOLUME: - value = 0x3f - (ctrl->val & 0x3f); - break; - default: - value = ((ctrl->val - cc->off) << cc->shift) & cc->mask; - break; - } - dprintk(1,"set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n", - ctrl->id, ctrl->name, ctrl->val, cc->reg, value, - mask, cc->sreg ? " [shadowed]" : ""); - if (cc->sreg) - cx_sandor(cc->sreg, cc->reg, mask, value); - else - cx_andor(cc->reg, mask, value); - return 0; -} - -/* ------------------------------------------------------------------ */ -/* VIDEO IOCTLS */ - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx8800_fh *fh = priv; - struct cx8800_dev *dev = fh->dev; - - f->fmt.pix.width = dev->width; - f->fmt.pix.height = dev->height; - f->fmt.pix.field = fh->vidq.field; - f->fmt.pix.pixelformat = dev->fmt->fourcc; - f->fmt.pix.bytesperline = - (f->fmt.pix.width * dev->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_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; - const struct cx8800_fmt *fmt; - enum v4l2_field field; - unsigned int maxw, maxh; - - fmt = format_by_fourcc(f->fmt.pix.pixelformat); - if (NULL == fmt) - return -EINVAL; - - field = f->fmt.pix.field; - maxw = norm_maxw(core->tvnorm); - maxh = norm_maxh(core->tvnorm); - - if (V4L2_FIELD_ANY == field) { - field = (f->fmt.pix.height > maxh/2) - ? V4L2_FIELD_INTERLACED - : V4L2_FIELD_BOTTOM; - } - - switch (field) { - case V4L2_FIELD_TOP: - case V4L2_FIELD_BOTTOM: - maxh = maxh / 2; - break; - case V4L2_FIELD_INTERLACED: - break; - default: - return -EINVAL; - } - - f->fmt.pix.field = field; - v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, - &f->fmt.pix.height, 32, maxh, 0, 0); - f->fmt.pix.bytesperline = - (f->fmt.pix.width * fmt->depth) >> 3; - f->fmt.pix.sizeimage = - f->fmt.pix.height * f->fmt.pix.bytesperline; - - return 0; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct cx8800_fh *fh = priv; - struct cx8800_dev *dev = fh->dev; - int err = vidioc_try_fmt_vid_cap (file,priv,f); - - if (0 != err) - return err; - dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat); - dev->width = f->fmt.pix.width; - dev->height = f->fmt.pix.height; - fh->vidq.field = f->fmt.pix.field; - return 0; -} - -void cx88_querycap(struct file *file, struct cx88_core *core, - struct v4l2_capability *cap) -{ - struct video_device *vdev = video_devdata(file); - - strlcpy(cap->card, core->board.name, sizeof(cap->card)); - cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; - if (UNSET != core->board.tuner_type) - cap->device_caps |= V4L2_CAP_TUNER; - switch (vdev->vfl_type) { - case VFL_TYPE_RADIO: - cap->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER; - break; - case VFL_TYPE_GRABBER: - cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE; - break; - case VFL_TYPE_VBI: - cap->device_caps |= V4L2_CAP_VBI_CAPTURE; - break; - } - cap->capabilities = cap->device_caps | V4L2_CAP_VIDEO_CAPTURE | - V4L2_CAP_VBI_CAPTURE | V4L2_CAP_DEVICE_CAPS; - if (core->board.radio.type == CX88_RADIO) - cap->capabilities |= V4L2_CAP_RADIO; -} -EXPORT_SYMBOL(cx88_querycap); - -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct cx8800_dev *dev = ((struct cx8800_fh *)priv)->dev; - struct cx88_core *core = dev->core; - - strcpy(cap->driver, "cx8800"); - sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); - cx88_querycap(file, core, cap); - return 0; -} - -static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - if (unlikely(f->index >= ARRAY_SIZE(formats))) - return -EINVAL; - - strlcpy(f->description,formats[f->index].name,sizeof(f->description)); - f->pixelformat = formats[f->index].fourcc; - - return 0; -} - -static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p) -{ - return videobuf_reqbufs(get_queue(file), p); -} - -static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p) -{ - return videobuf_querybuf(get_queue(file), p); -} - -static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p) -{ - return videobuf_qbuf(get_queue(file), p); -} - -static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) -{ - return videobuf_dqbuf(get_queue(file), p, - file->f_flags & O_NONBLOCK); -} - -static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct video_device *vdev = video_devdata(file); - struct cx8800_fh *fh = priv; - struct cx8800_dev *dev = fh->dev; - - if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) || - (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE)) - return -EINVAL; - - if (unlikely(!res_get(dev, fh, get_resource(file)))) - return -EBUSY; - return videobuf_streamon(get_queue(file)); -} - -static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) -{ - struct video_device *vdev = video_devdata(file); - struct cx8800_fh *fh = priv; - struct cx8800_dev *dev = fh->dev; - int err, res; - - if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) || - (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE)) - return -EINVAL; - - res = get_resource(file); - err = videobuf_streamoff(get_queue(file)); - if (err < 0) - return err; - res_free(dev,fh,res); - return 0; -} - -static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) -{ - struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; - - *tvnorm = core->tvnorm; - return 0; -} - -static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *tvnorms) -{ - struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; - - mutex_lock(&core->lock); - cx88_set_tvnorm(core,*tvnorms); - mutex_unlock(&core->lock); - - return 0; -} - -/* only one input in this sample driver */ -int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i) -{ - static const char * const iname[] = { - [ CX88_VMUX_COMPOSITE1 ] = "Composite1", - [ CX88_VMUX_COMPOSITE2 ] = "Composite2", - [ CX88_VMUX_COMPOSITE3 ] = "Composite3", - [ CX88_VMUX_COMPOSITE4 ] = "Composite4", - [ CX88_VMUX_SVIDEO ] = "S-Video", - [ CX88_VMUX_TELEVISION ] = "Television", - [ CX88_VMUX_CABLE ] = "Cable TV", - [ CX88_VMUX_DVB ] = "DVB", - [ CX88_VMUX_DEBUG ] = "for debug only", - }; - unsigned int n = i->index; - - if (n >= 4) - return -EINVAL; - if (0 == INPUT(n).type) - return -EINVAL; - i->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(i->name,iname[INPUT(n).type]); - if ((CX88_VMUX_TELEVISION == INPUT(n).type) || - (CX88_VMUX_CABLE == INPUT(n).type)) { - i->type = V4L2_INPUT_TYPE_TUNER; - } - i->std = CX88_NORMS; - return 0; -} -EXPORT_SYMBOL(cx88_enum_input); - -static int vidioc_enum_input (struct file *file, void *priv, - struct v4l2_input *i) -{ - struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; - return cx88_enum_input (core,i); -} - -static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) -{ - struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; - - *i = core->input; - return 0; -} - -static int vidioc_s_input (struct file *file, void *priv, unsigned int i) -{ - struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; - - if (i >= 4) - return -EINVAL; - if (0 == INPUT(i).type) - return -EINVAL; - - mutex_lock(&core->lock); - cx88_newstation(core); - cx88_video_mux(core,i); - mutex_unlock(&core->lock); - return 0; -} - -static int vidioc_g_tuner (struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; - u32 reg; - - if (unlikely(UNSET == core->board.tuner_type)) - return -EINVAL; - if (0 != t->index) - return -EINVAL; - - strcpy(t->name, "Television"); - t->capability = V4L2_TUNER_CAP_NORM; - t->rangehigh = 0xffffffffUL; - call_all(core, tuner, g_tuner, t); - - cx88_get_stereo(core ,t); - reg = cx_read(MO_DEVICE_STATUS); - t->signal = (reg & (1<<5)) ? 0xffff : 0x0000; - return 0; -} - -static int vidioc_s_tuner (struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; - - if (UNSET == core->board.tuner_type) - return -EINVAL; - if (0 != t->index) - return -EINVAL; - - cx88_set_stereo(core, t->audmode, 1); - return 0; -} - -static int vidioc_g_frequency (struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct cx8800_fh *fh = priv; - struct cx88_core *core = fh->dev->core; - - if (unlikely(UNSET == core->board.tuner_type)) - return -EINVAL; - if (f->tuner) - return -EINVAL; - - f->frequency = core->freq; - - call_all(core, tuner, g_frequency, f); - - return 0; -} - -int cx88_set_freq (struct cx88_core *core, - struct v4l2_frequency *f) -{ - if (unlikely(UNSET == core->board.tuner_type)) - return -EINVAL; - if (unlikely(f->tuner != 0)) - return -EINVAL; - - mutex_lock(&core->lock); - cx88_newstation(core); - call_all(core, tuner, s_frequency, f); - call_all(core, tuner, g_frequency, f); - core->freq = f->frequency; - - /* When changing channels it is required to reset TVAUDIO */ - msleep (10); - cx88_set_tvaudio(core); - - mutex_unlock(&core->lock); - - return 0; -} -EXPORT_SYMBOL(cx88_set_freq); - -static int vidioc_s_frequency (struct file *file, void *priv, - struct v4l2_frequency *f) -{ - struct cx8800_fh *fh = priv; - struct cx88_core *core = fh->dev->core; - - return cx88_set_freq(core, f); -} - -static int vidioc_g_chip_ident(struct file *file, void *priv, - struct v4l2_dbg_chip_ident *chip) -{ - if (!v4l2_chip_match_host(&chip->match)) - return -EINVAL; - chip->revision = 0; - chip->ident = V4L2_IDENT_UNKNOWN; - return 0; -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int vidioc_g_register (struct file *file, void *fh, - struct v4l2_dbg_register *reg) -{ - struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - /* cx2388x has a 24-bit register space */ - reg->val = cx_read(reg->reg & 0xffffff); - reg->size = 4; - return 0; -} - -static int vidioc_s_register (struct file *file, void *fh, - struct v4l2_dbg_register *reg) -{ - struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - - if (!v4l2_chip_match_host(®->match)) - return -EINVAL; - cx_write(reg->reg & 0xffffff, reg->val); - return 0; -} -#endif - -/* ----------------------------------------------------------- */ -/* RADIO ESPECIFIC IOCTLS */ -/* ----------------------------------------------------------- */ - -static int radio_g_tuner (struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; - - if (unlikely(t->index > 0)) - return -EINVAL; - - strcpy(t->name, "Radio"); - - call_all(core, tuner, g_tuner, t); - return 0; -} - -/* FIXME: Should add a standard for radio */ - -static int radio_s_tuner (struct file *file, void *priv, - struct v4l2_tuner *t) -{ - struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; - - if (0 != t->index) - return -EINVAL; - if (t->audmode > V4L2_TUNER_MODE_STEREO) - t->audmode = V4L2_TUNER_MODE_STEREO; - - call_all(core, tuner, s_tuner, t); - - return 0; -} - -/* ----------------------------------------------------------- */ - -static void cx8800_vid_timeout(unsigned long data) -{ - struct cx8800_dev *dev = (struct cx8800_dev*)data; - struct cx88_core *core = dev->core; - struct cx88_dmaqueue *q = &dev->vidq; - struct cx88_buffer *buf; - unsigned long flags; - - cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]); - - cx_clear(MO_VID_DMACNTRL, 0x11); - cx_clear(VID_CAPTURE_CONTROL, 0x06); - - spin_lock_irqsave(&dev->slock,flags); - while (!list_empty(&q->active)) { - buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); - list_del(&buf->vb.queue); - buf->vb.state = VIDEOBUF_ERROR; - wake_up(&buf->vb.done); - printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name, - buf, buf->vb.i, (unsigned long)buf->risc.dma); - } - restart_video_queue(dev,q); - spin_unlock_irqrestore(&dev->slock,flags); -} - -static const char *cx88_vid_irqs[32] = { - "y_risci1", "u_risci1", "v_risci1", "vbi_risc1", - "y_risci2", "u_risci2", "v_risci2", "vbi_risc2", - "y_oflow", "u_oflow", "v_oflow", "vbi_oflow", - "y_sync", "u_sync", "v_sync", "vbi_sync", - "opc_err", "par_err", "rip_err", "pci_abort", -}; - -static void cx8800_vid_irq(struct cx8800_dev *dev) -{ - struct cx88_core *core = dev->core; - u32 status, mask, count; - - status = cx_read(MO_VID_INTSTAT); - mask = cx_read(MO_VID_INTMSK); - if (0 == (status & mask)) - return; - cx_write(MO_VID_INTSTAT, status); - if (irq_debug || (status & mask & ~0xff)) - cx88_print_irqbits(core->name, "irq vid", - cx88_vid_irqs, ARRAY_SIZE(cx88_vid_irqs), - status, mask); - - /* risc op code error */ - if (status & (1 << 16)) { - printk(KERN_WARNING "%s/0: video risc op code error\n",core->name); - cx_clear(MO_VID_DMACNTRL, 0x11); - cx_clear(VID_CAPTURE_CONTROL, 0x06); - cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]); - } - - /* risc1 y */ - if (status & 0x01) { - spin_lock(&dev->slock); - count = cx_read(MO_VIDY_GPCNT); - cx88_wakeup(core, &dev->vidq, count); - spin_unlock(&dev->slock); - } - - /* risc1 vbi */ - if (status & 0x08) { - spin_lock(&dev->slock); - count = cx_read(MO_VBI_GPCNT); - cx88_wakeup(core, &dev->vbiq, count); - spin_unlock(&dev->slock); - } - - /* risc2 y */ - if (status & 0x10) { - dprintk(2,"stopper video\n"); - spin_lock(&dev->slock); - restart_video_queue(dev,&dev->vidq); - spin_unlock(&dev->slock); - } - - /* risc2 vbi */ - if (status & 0x80) { - dprintk(2,"stopper vbi\n"); - spin_lock(&dev->slock); - cx8800_restart_vbi_queue(dev,&dev->vbiq); - spin_unlock(&dev->slock); - } -} - -static irqreturn_t cx8800_irq(int irq, void *dev_id) -{ - struct cx8800_dev *dev = dev_id; - struct cx88_core *core = dev->core; - u32 status; - int loop, handled = 0; - - for (loop = 0; loop < 10; loop++) { - status = cx_read(MO_PCI_INTSTAT) & - (core->pci_irqmask | PCI_INT_VIDINT); - if (0 == status) - goto out; - cx_write(MO_PCI_INTSTAT, status); - handled = 1; - - if (status & core->pci_irqmask) - cx88_core_irq(core,status); - if (status & PCI_INT_VIDINT) - cx8800_vid_irq(dev); - }; - if (10 == loop) { - printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n", - core->name); - cx_write(MO_PCI_INTMSK,0); - } - - out: - return IRQ_RETVAL(handled); -} - -/* ----------------------------------------------------------- */ -/* exported stuff */ - -static const struct v4l2_file_operations video_fops = -{ - .owner = THIS_MODULE, - .open = video_open, - .release = video_release, - .read = video_read, - .poll = video_poll, - .mmap = video_mmap, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops video_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, - .vidioc_g_std = vidioc_g_std, - .vidioc_s_std = vidioc_s_std, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = vidioc_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, -#endif -}; - -static const struct video_device cx8800_video_template = { - .name = "cx8800-video", - .fops = &video_fops, - .ioctl_ops = &video_ioctl_ops, - .tvnorms = CX88_NORMS, -}; - -static const struct v4l2_ioctl_ops vbi_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_g_fmt_vbi_cap = cx8800_vbi_fmt, - .vidioc_try_fmt_vbi_cap = cx8800_vbi_fmt, - .vidioc_s_fmt_vbi_cap = cx8800_vbi_fmt, - .vidioc_reqbufs = vidioc_reqbufs, - .vidioc_querybuf = vidioc_querybuf, - .vidioc_qbuf = vidioc_qbuf, - .vidioc_dqbuf = vidioc_dqbuf, - .vidioc_g_std = vidioc_g_std, - .vidioc_s_std = vidioc_s_std, - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - .vidioc_streamon = vidioc_streamon, - .vidioc_streamoff = vidioc_streamoff, - .vidioc_g_tuner = vidioc_g_tuner, - .vidioc_s_tuner = vidioc_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_g_chip_ident = vidioc_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, -#endif -}; - -static const struct video_device cx8800_vbi_template = { - .name = "cx8800-vbi", - .fops = &video_fops, - .ioctl_ops = &vbi_ioctl_ops, - .tvnorms = CX88_NORMS, -}; - -static const struct v4l2_file_operations radio_fops = -{ - .owner = THIS_MODULE, - .open = video_open, - .poll = v4l2_ctrl_poll, - .release = video_release, - .unlocked_ioctl = video_ioctl2, -}; - -static const struct v4l2_ioctl_ops radio_ioctl_ops = { - .vidioc_querycap = vidioc_querycap, - .vidioc_g_tuner = radio_g_tuner, - .vidioc_s_tuner = radio_s_tuner, - .vidioc_g_frequency = vidioc_g_frequency, - .vidioc_s_frequency = vidioc_s_frequency, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, - .vidioc_g_chip_ident = vidioc_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = vidioc_g_register, - .vidioc_s_register = vidioc_s_register, -#endif -}; - -static const struct video_device cx8800_radio_template = { - .name = "cx8800-radio", - .fops = &radio_fops, - .ioctl_ops = &radio_ioctl_ops, -}; - -static const struct v4l2_ctrl_ops cx8800_ctrl_vid_ops = { - .s_ctrl = cx8800_s_vid_ctrl, -}; - -static const struct v4l2_ctrl_ops cx8800_ctrl_aud_ops = { - .s_ctrl = cx8800_s_aud_ctrl, -}; - -/* ----------------------------------------------------------- */ - -static void cx8800_unregister_video(struct cx8800_dev *dev) -{ - if (dev->radio_dev) { - if (video_is_registered(dev->radio_dev)) - video_unregister_device(dev->radio_dev); - else - video_device_release(dev->radio_dev); - dev->radio_dev = NULL; - } - if (dev->vbi_dev) { - if (video_is_registered(dev->vbi_dev)) - video_unregister_device(dev->vbi_dev); - else - video_device_release(dev->vbi_dev); - dev->vbi_dev = NULL; - } - if (dev->video_dev) { - if (video_is_registered(dev->video_dev)) - video_unregister_device(dev->video_dev); - else - video_device_release(dev->video_dev); - dev->video_dev = NULL; - } -} - -static int __devinit cx8800_initdev(struct pci_dev *pci_dev, - const struct pci_device_id *pci_id) -{ - struct cx8800_dev *dev; - struct cx88_core *core; - int err; - int i; - - dev = kzalloc(sizeof(*dev),GFP_KERNEL); - if (NULL == dev) - return -ENOMEM; - - /* pci init */ - dev->pci = pci_dev; - if (pci_enable_device(pci_dev)) { - err = -EIO; - goto fail_free; - } - core = cx88_core_get(dev->pci); - if (NULL == core) { - err = -EINVAL; - goto fail_free; - } - dev->core = core; - - /* print pci info */ - dev->pci_rev = pci_dev->revision; - pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); - printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " - "latency: %d, mmio: 0x%llx\n", core->name, - pci_name(pci_dev), dev->pci_rev, pci_dev->irq, - dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0)); - - pci_set_master(pci_dev); - if (!pci_dma_supported(pci_dev,DMA_BIT_MASK(32))) { - printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name); - err = -EIO; - goto fail_core; - } - - /* initialize driver struct */ - spin_lock_init(&dev->slock); - core->tvnorm = V4L2_STD_NTSC_M; - - /* init video dma queues */ - INIT_LIST_HEAD(&dev->vidq.active); - INIT_LIST_HEAD(&dev->vidq.queued); - dev->vidq.timeout.function = cx8800_vid_timeout; - dev->vidq.timeout.data = (unsigned long)dev; - init_timer(&dev->vidq.timeout); - cx88_risc_stopper(dev->pci,&dev->vidq.stopper, - MO_VID_DMACNTRL,0x11,0x00); - - /* init vbi dma queues */ - INIT_LIST_HEAD(&dev->vbiq.active); - INIT_LIST_HEAD(&dev->vbiq.queued); - dev->vbiq.timeout.function = cx8800_vbi_timeout; - dev->vbiq.timeout.data = (unsigned long)dev; - init_timer(&dev->vbiq.timeout); - cx88_risc_stopper(dev->pci,&dev->vbiq.stopper, - MO_VID_DMACNTRL,0x88,0x00); - - /* get irq */ - err = request_irq(pci_dev->irq, cx8800_irq, - IRQF_SHARED | IRQF_DISABLED, core->name, dev); - if (err < 0) { - printk(KERN_ERR "%s/0: can't get IRQ %d\n", - core->name,pci_dev->irq); - goto fail_core; - } - cx_set(MO_PCI_INTMSK, core->pci_irqmask); - - for (i = 0; i < CX8800_AUD_CTLS; i++) { - const struct cx88_ctrl *cc = &cx8800_aud_ctls[i]; - struct v4l2_ctrl *vc; - - vc = v4l2_ctrl_new_std(&core->audio_hdl, &cx8800_ctrl_aud_ops, - cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value); - if (vc == NULL) { - err = core->audio_hdl.error; - goto fail_core; - } - vc->priv = (void *)cc; - } - - for (i = 0; i < CX8800_VID_CTLS; i++) { - const struct cx88_ctrl *cc = &cx8800_vid_ctls[i]; - struct v4l2_ctrl *vc; - - vc = v4l2_ctrl_new_std(&core->video_hdl, &cx8800_ctrl_vid_ops, - cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value); - if (vc == NULL) { - err = core->video_hdl.error; - goto fail_core; - } - vc->priv = (void *)cc; - if (vc->id == V4L2_CID_CHROMA_AGC) - core->chroma_agc = vc; - } - v4l2_ctrl_add_handler(&core->video_hdl, &core->audio_hdl); - - /* load and configure helper modules */ - - if (core->board.audio_chip == V4L2_IDENT_WM8775) { - struct i2c_board_info wm8775_info = { - .type = "wm8775", - .addr = 0x36 >> 1, - .platform_data = &core->wm8775_data, - }; - struct v4l2_subdev *sd; - - if (core->boardnr == CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1) - core->wm8775_data.is_nova_s = true; - else - core->wm8775_data.is_nova_s = false; - - sd = v4l2_i2c_new_subdev_board(&core->v4l2_dev, &core->i2c_adap, - &wm8775_info, NULL); - if (sd != NULL) { - core->sd_wm8775 = sd; - sd->grp_id = WM8775_GID; - } - } - - if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) { - /* This probes for a tda9874 as is used on some - Pixelview Ultra boards. */ - v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap, - "tvaudio", 0, I2C_ADDRS(0xb0 >> 1)); - } - - switch (core->boardnr) { - case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: - case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: { - static const struct i2c_board_info rtc_info = { - I2C_BOARD_INFO("isl1208", 0x6f) - }; - - request_module("rtc-isl1208"); - core->i2c_rtc = i2c_new_device(&core->i2c_adap, &rtc_info); - } - /* break intentionally omitted */ - case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: - request_module("ir-kbd-i2c"); - } - - /* Sets device info at pci_dev */ - pci_set_drvdata(pci_dev, dev); - - dev->width = 320; - dev->height = 240; - dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); - - /* initial device configuration */ - mutex_lock(&core->lock); - cx88_set_tvnorm(core, core->tvnorm); - v4l2_ctrl_handler_setup(&core->video_hdl); - v4l2_ctrl_handler_setup(&core->audio_hdl); - cx88_video_mux(core, 0); - - /* register v4l devices */ - dev->video_dev = cx88_vdev_init(core,dev->pci, - &cx8800_video_template,"video"); - video_set_drvdata(dev->video_dev, dev); - dev->video_dev->ctrl_handler = &core->video_hdl; - err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, - video_nr[core->nr]); - if (err < 0) { - printk(KERN_ERR "%s/0: can't register video device\n", - core->name); - goto fail_unreg; - } - printk(KERN_INFO "%s/0: registered device %s [v4l2]\n", - core->name, video_device_node_name(dev->video_dev)); - - dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi"); - video_set_drvdata(dev->vbi_dev, dev); - err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, - vbi_nr[core->nr]); - if (err < 0) { - printk(KERN_ERR "%s/0: can't register vbi device\n", - core->name); - goto fail_unreg; - } - printk(KERN_INFO "%s/0: registered device %s\n", - core->name, video_device_node_name(dev->vbi_dev)); - - if (core->board.radio.type == CX88_RADIO) { - dev->radio_dev = cx88_vdev_init(core,dev->pci, - &cx8800_radio_template,"radio"); - video_set_drvdata(dev->radio_dev, dev); - dev->radio_dev->ctrl_handler = &core->audio_hdl; - err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO, - radio_nr[core->nr]); - if (err < 0) { - printk(KERN_ERR "%s/0: can't register radio device\n", - core->name); - goto fail_unreg; - } - printk(KERN_INFO "%s/0: registered device %s\n", - core->name, video_device_node_name(dev->radio_dev)); - } - - /* start tvaudio thread */ - if (core->board.tuner_type != TUNER_ABSENT) { - core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio"); - if (IS_ERR(core->kthread)) { - err = PTR_ERR(core->kthread); - printk(KERN_ERR "%s/0: failed to create cx88 audio thread, err=%d\n", - core->name, err); - } - } - mutex_unlock(&core->lock); - - return 0; - -fail_unreg: - cx8800_unregister_video(dev); - free_irq(pci_dev->irq, dev); - mutex_unlock(&core->lock); -fail_core: - cx88_core_put(core,dev->pci); -fail_free: - kfree(dev); - return err; -} - -static void __devexit cx8800_finidev(struct pci_dev *pci_dev) -{ - struct cx8800_dev *dev = pci_get_drvdata(pci_dev); - struct cx88_core *core = dev->core; - - /* stop thread */ - if (core->kthread) { - kthread_stop(core->kthread); - core->kthread = NULL; - } - - if (core->ir) - cx88_ir_stop(core); - - cx88_shutdown(core); /* FIXME */ - pci_disable_device(pci_dev); - - /* unregister stuff */ - - free_irq(pci_dev->irq, dev); - cx8800_unregister_video(dev); - pci_set_drvdata(pci_dev, NULL); - - /* free memory */ - btcx_riscmem_free(dev->pci,&dev->vidq.stopper); - cx88_core_put(core,dev->pci); - kfree(dev); -} - -#ifdef CONFIG_PM -static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state) -{ - struct cx8800_dev *dev = pci_get_drvdata(pci_dev); - struct cx88_core *core = dev->core; - - /* stop video+vbi capture */ - spin_lock(&dev->slock); - if (!list_empty(&dev->vidq.active)) { - printk("%s/0: suspend video\n", core->name); - stop_video_dma(dev); - del_timer(&dev->vidq.timeout); - } - if (!list_empty(&dev->vbiq.active)) { - printk("%s/0: suspend vbi\n", core->name); - cx8800_stop_vbi_dma(dev); - del_timer(&dev->vbiq.timeout); - } - spin_unlock(&dev->slock); - - if (core->ir) - cx88_ir_stop(core); - /* FIXME -- shutdown device */ - cx88_shutdown(core); - - pci_save_state(pci_dev); - if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) { - pci_disable_device(pci_dev); - dev->state.disabled = 1; - } - return 0; -} - -static int cx8800_resume(struct pci_dev *pci_dev) -{ - struct cx8800_dev *dev = pci_get_drvdata(pci_dev); - struct cx88_core *core = dev->core; - int err; - - if (dev->state.disabled) { - err=pci_enable_device(pci_dev); - if (err) { - printk(KERN_ERR "%s/0: can't enable device\n", - core->name); - return err; - } - - dev->state.disabled = 0; - } - err= pci_set_power_state(pci_dev, PCI_D0); - if (err) { - printk(KERN_ERR "%s/0: can't set power state\n", core->name); - pci_disable_device(pci_dev); - dev->state.disabled = 1; - - return err; - } - pci_restore_state(pci_dev); - - /* FIXME: re-initialize hardware */ - cx88_reset(core); - if (core->ir) - cx88_ir_start(core); - - cx_set(MO_PCI_INTMSK, core->pci_irqmask); - - /* restart video+vbi capture */ - spin_lock(&dev->slock); - if (!list_empty(&dev->vidq.active)) { - printk("%s/0: resume video\n", core->name); - restart_video_queue(dev,&dev->vidq); - } - if (!list_empty(&dev->vbiq.active)) { - printk("%s/0: resume vbi\n", core->name); - cx8800_restart_vbi_queue(dev,&dev->vbiq); - } - spin_unlock(&dev->slock); - - return 0; -} -#endif - -/* ----------------------------------------------------------- */ - -static const struct pci_device_id cx8800_pci_tbl[] = { - { - .vendor = 0x14f1, - .device = 0x8800, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - },{ - /* --- end of list --- */ - } -}; -MODULE_DEVICE_TABLE(pci, cx8800_pci_tbl); - -static struct pci_driver cx8800_pci_driver = { - .name = "cx8800", - .id_table = cx8800_pci_tbl, - .probe = cx8800_initdev, - .remove = __devexit_p(cx8800_finidev), -#ifdef CONFIG_PM - .suspend = cx8800_suspend, - .resume = cx8800_resume, -#endif -}; - -static int __init cx8800_init(void) -{ - printk(KERN_INFO "cx88/0: cx2388x v4l2 driver version %s loaded\n", - CX88_VERSION); - return pci_register_driver(&cx8800_pci_driver); -} - -static void __exit cx8800_fini(void) -{ - pci_unregister_driver(&cx8800_pci_driver); -} - -module_init(cx8800_init); -module_exit(cx8800_fini); diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c deleted file mode 100644 index d77f8ecab9d7..000000000000 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - - cx88-vp3054-i2c.c -- support for the secondary I2C bus of the - DNTV Live! DVB-T Pro (VP-3054), wired as: - GPIO[0] -> SCL, GPIO[1] -> SDA - - (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> - -#include <asm/io.h> - -#include "cx88.h" -#include "cx88-vp3054-i2c.h" - -MODULE_DESCRIPTION("driver for cx2388x VP3054 design"); -MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); -MODULE_LICENSE("GPL"); - -/* ----------------------------------------------------------------------- */ - -static void vp3054_bit_setscl(void *data, int state) -{ - struct cx8802_dev *dev = data; - struct cx88_core *core = dev->core; - struct vp3054_i2c_state *vp3054_i2c = dev->vp3054; - - if (state) { - vp3054_i2c->state |= 0x0001; /* SCL high */ - vp3054_i2c->state &= ~0x0100; /* external pullup */ - } else { - vp3054_i2c->state &= ~0x0001; /* SCL low */ - vp3054_i2c->state |= 0x0100; /* drive pin */ - } - cx_write(MO_GP0_IO, 0x010000 | vp3054_i2c->state); - cx_read(MO_GP0_IO); -} - -static void vp3054_bit_setsda(void *data, int state) -{ - struct cx8802_dev *dev = data; - struct cx88_core *core = dev->core; - struct vp3054_i2c_state *vp3054_i2c = dev->vp3054; - - if (state) { - vp3054_i2c->state |= 0x0002; /* SDA high */ - vp3054_i2c->state &= ~0x0200; /* tristate pin */ - } else { - vp3054_i2c->state &= ~0x0002; /* SDA low */ - vp3054_i2c->state |= 0x0200; /* drive pin */ - } - cx_write(MO_GP0_IO, 0x020000 | vp3054_i2c->state); - cx_read(MO_GP0_IO); -} - -static int vp3054_bit_getscl(void *data) -{ - struct cx8802_dev *dev = data; - struct cx88_core *core = dev->core; - u32 state; - - state = cx_read(MO_GP0_IO); - return (state & 0x01) ? 1 : 0; -} - -static int vp3054_bit_getsda(void *data) -{ - struct cx8802_dev *dev = data; - struct cx88_core *core = dev->core; - u32 state; - - state = cx_read(MO_GP0_IO); - return (state & 0x02) ? 1 : 0; -} - -/* ----------------------------------------------------------------------- */ - -static const struct i2c_algo_bit_data vp3054_i2c_algo_template = { - .setsda = vp3054_bit_setsda, - .setscl = vp3054_bit_setscl, - .getsda = vp3054_bit_getsda, - .getscl = vp3054_bit_getscl, - .udelay = 16, - .timeout = 200, -}; - -/* ----------------------------------------------------------------------- */ - -int vp3054_i2c_probe(struct cx8802_dev *dev) -{ - struct cx88_core *core = dev->core; - struct vp3054_i2c_state *vp3054_i2c; - int rc; - - if (core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) - return 0; - - vp3054_i2c = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL); - if (vp3054_i2c == NULL) - return -ENOMEM; - dev->vp3054 = vp3054_i2c; - - memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template, - sizeof(vp3054_i2c->algo)); - - vp3054_i2c->adap.dev.parent = &dev->pci->dev; - strlcpy(vp3054_i2c->adap.name, core->name, - sizeof(vp3054_i2c->adap.name)); - vp3054_i2c->adap.owner = THIS_MODULE; - vp3054_i2c->algo.data = dev; - i2c_set_adapdata(&vp3054_i2c->adap, dev); - vp3054_i2c->adap.algo_data = &vp3054_i2c->algo; - - vp3054_bit_setscl(dev,1); - vp3054_bit_setsda(dev,1); - - rc = i2c_bit_add_bus(&vp3054_i2c->adap); - if (0 != rc) { - printk("%s: vp3054_i2c register FAILED\n", core->name); - - kfree(dev->vp3054); - dev->vp3054 = NULL; - } - - return rc; -} - -void vp3054_i2c_remove(struct cx8802_dev *dev) -{ - struct vp3054_i2c_state *vp3054_i2c = dev->vp3054; - - if (vp3054_i2c == NULL || - dev->core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) - return; - - i2c_del_adapter(&vp3054_i2c->adap); - kfree(vp3054_i2c); -} - -EXPORT_SYMBOL(vp3054_i2c_probe); -EXPORT_SYMBOL(vp3054_i2c_remove); diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.h b/drivers/media/video/cx88/cx88-vp3054-i2c.h deleted file mode 100644 index be99c931dc3e..000000000000 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - - cx88-vp3054-i2c.h -- support for the secondary I2C bus of the - DNTV Live! DVB-T Pro (VP-3054), wired as: - GPIO[0] -> SCL, GPIO[1] -> SDA - - (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/* ----------------------------------------------------------------------- */ -struct vp3054_i2c_state { - struct i2c_adapter adap; - struct i2c_algo_bit_data algo; - u32 state; -}; - -/* ----------------------------------------------------------------------- */ -#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) -int vp3054_i2c_probe(struct cx8802_dev *dev); -void vp3054_i2c_remove(struct cx8802_dev *dev); -#else -static inline int vp3054_i2c_probe(struct cx8802_dev *dev) -{ return 0; } -static inline void vp3054_i2c_remove(struct cx8802_dev *dev) -{ } -#endif diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h deleted file mode 100644 index 44ffc8b3d45f..000000000000 --- a/drivers/media/video/cx88/cx88.h +++ /dev/null @@ -1,748 +0,0 @@ -/* - * - * v4l2 device driver for cx2388x based TV cards - * - * (c) 2003,04 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs] - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/pci.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <linux/videodev2.h> -#include <linux/kdev_t.h> - -#include <media/v4l2-device.h> -#include <media/v4l2-fh.h> -#include <media/tuner.h> -#include <media/tveeprom.h> -#include <media/videobuf-dma-sg.h> -#include <media/v4l2-chip-ident.h> -#include <media/cx2341x.h> -#include <media/videobuf-dvb.h> -#include <media/ir-kbd-i2c.h> -#include <media/wm8775.h> - -#include "btcx-risc.h" -#include "cx88-reg.h" -#include "tuner-xc2028.h" - -#include <linux/mutex.h> - -#define CX88_VERSION "0.0.9" - -#define UNSET (-1U) - -#define CX88_MAXBOARDS 8 - -/* Max number of inputs by card */ -#define MAX_CX88_INPUT 8 - -/* ----------------------------------------------------------- */ -/* defines and enums */ - -/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM/LC */ -#define CX88_NORMS (V4L2_STD_ALL \ - & ~V4L2_STD_PAL_H \ - & ~V4L2_STD_NTSC_M_KR \ - & ~V4L2_STD_SECAM_LC) - -#define FORMAT_FLAGS_PACKED 0x01 -#define FORMAT_FLAGS_PLANAR 0x02 - -#define VBI_LINE_COUNT 17 -#define VBI_LINE_LENGTH 2048 - -#define AUD_RDS_LINES 4 - -/* need "shadow" registers for some write-only ones ... */ -#define SHADOW_AUD_VOL_CTL 1 -#define SHADOW_AUD_BAL_CTL 2 -#define SHADOW_MAX 3 - -/* FM Radio deemphasis type */ -enum cx88_deemph_type { - FM_NO_DEEMPH = 0, - FM_DEEMPH_50, - FM_DEEMPH_75 -}; - -enum cx88_board_type { - CX88_BOARD_NONE = 0, - CX88_MPEG_DVB, - CX88_MPEG_BLACKBIRD -}; - -enum cx8802_board_access { - CX8802_DRVCTL_SHARED = 1, - CX8802_DRVCTL_EXCLUSIVE = 2, -}; - -/* ----------------------------------------------------------- */ -/* tv norms */ - -static unsigned int inline norm_maxw(v4l2_std_id norm) -{ - return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768; -} - - -static unsigned int inline norm_maxh(v4l2_std_id norm) -{ - return (norm & V4L2_STD_625_50) ? 576 : 480; -} - -/* ----------------------------------------------------------- */ -/* static data */ - -struct cx8800_fmt { - const char *name; - u32 fourcc; /* v4l2 format id */ - int depth; - int flags; - u32 cxformat; -}; - -/* ----------------------------------------------------------- */ -/* SRAM memory management data (see cx88-core.c) */ - -#define SRAM_CH21 0 /* video */ -#define SRAM_CH22 1 -#define SRAM_CH23 2 -#define SRAM_CH24 3 /* vbi */ -#define SRAM_CH25 4 /* audio */ -#define SRAM_CH26 5 -#define SRAM_CH28 6 /* mpeg */ -#define SRAM_CH27 7 /* audio rds */ -/* more */ - -struct sram_channel { - const char *name; - 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; -}; -extern const struct sram_channel cx88_sram_channels[]; - -/* ----------------------------------------------------------- */ -/* card configuration */ - -#define CX88_BOARD_NOAUTO UNSET -#define CX88_BOARD_UNKNOWN 0 -#define CX88_BOARD_HAUPPAUGE 1 -#define CX88_BOARD_GDI 2 -#define CX88_BOARD_PIXELVIEW 3 -#define CX88_BOARD_ATI_WONDER_PRO 4 -#define CX88_BOARD_WINFAST2000XP_EXPERT 5 -#define CX88_BOARD_AVERTV_STUDIO_303 6 -#define CX88_BOARD_MSI_TVANYWHERE_MASTER 7 -#define CX88_BOARD_WINFAST_DV2000 8 -#define CX88_BOARD_LEADTEK_PVR2000 9 -#define CX88_BOARD_IODATA_GVVCP3PCI 10 -#define CX88_BOARD_PROLINK_PLAYTVPVR 11 -#define CX88_BOARD_ASUS_PVR_416 12 -#define CX88_BOARD_MSI_TVANYWHERE 13 -#define CX88_BOARD_KWORLD_DVB_T 14 -#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1 15 -#define CX88_BOARD_KWORLD_LTV883 16 -#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q 17 -#define CX88_BOARD_HAUPPAUGE_DVB_T1 18 -#define CX88_BOARD_CONEXANT_DVB_T1 19 -#define CX88_BOARD_PROVIDEO_PV259 20 -#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS 21 -#define CX88_BOARD_PCHDTV_HD3000 22 -#define CX88_BOARD_DNTV_LIVE_DVB_T 23 -#define CX88_BOARD_HAUPPAUGE_ROSLYN 24 -#define CX88_BOARD_DIGITALLOGIC_MEC 25 -#define CX88_BOARD_IODATA_GVBCTV7E 26 -#define CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO 27 -#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T 28 -#define CX88_BOARD_ADSTECH_DVB_T_PCI 29 -#define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1 30 -#define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31 -#define CX88_BOARD_AVERMEDIA_ULTRATV_MC_550 32 -#define CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD 33 -#define CX88_BOARD_ATI_HDTVWONDER 34 -#define CX88_BOARD_WINFAST_DTV1000 35 -#define CX88_BOARD_AVERTV_303 36 -#define CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1 37 -#define CX88_BOARD_HAUPPAUGE_NOVASE2_S1 38 -#define CX88_BOARD_KWORLD_DVBS_100 39 -#define CX88_BOARD_HAUPPAUGE_HVR1100 40 -#define CX88_BOARD_HAUPPAUGE_HVR1100LP 41 -#define CX88_BOARD_DNTV_LIVE_DVB_T_PRO 42 -#define CX88_BOARD_KWORLD_DVB_T_CX22702 43 -#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44 -#define CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT 45 -#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID 46 -#define CX88_BOARD_PCHDTV_HD5500 47 -#define CX88_BOARD_KWORLD_MCE200_DELUXE 48 -#define CX88_BOARD_PIXELVIEW_PLAYTV_P7000 49 -#define CX88_BOARD_NPGTECH_REALTV_TOP10FM 50 -#define CX88_BOARD_WINFAST_DTV2000H 51 -#define CX88_BOARD_GENIATECH_DVBS 52 -#define CX88_BOARD_HAUPPAUGE_HVR3000 53 -#define CX88_BOARD_NORWOOD_MICRO 54 -#define CX88_BOARD_TE_DTV_250_OEM_SWANN 55 -#define CX88_BOARD_HAUPPAUGE_HVR1300 56 -#define CX88_BOARD_ADSTECH_PTV_390 57 -#define CX88_BOARD_PINNACLE_PCTV_HD_800i 58 -#define CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO 59 -#define CX88_BOARD_PINNACLE_HYBRID_PCTV 60 -#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL 61 -#define CX88_BOARD_POWERCOLOR_REAL_ANGEL 62 -#define CX88_BOARD_GENIATECH_X8000_MT 63 -#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64 -#define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65 -#define CX88_BOARD_PROLINK_PV_8000GT 66 -#define CX88_BOARD_KWORLD_ATSC_120 67 -#define CX88_BOARD_HAUPPAUGE_HVR4000 68 -#define CX88_BOARD_HAUPPAUGE_HVR4000LITE 69 -#define CX88_BOARD_TEVII_S460 70 -#define CX88_BOARD_OMICOM_SS4_PCI 71 -#define CX88_BOARD_TBS_8920 72 -#define CX88_BOARD_TEVII_S420 73 -#define CX88_BOARD_PROLINK_PV_GLOBAL_XTREME 74 -#define CX88_BOARD_PROF_7300 75 -#define CX88_BOARD_SATTRADE_ST4200 76 -#define CX88_BOARD_TBS_8910 77 -#define CX88_BOARD_PROF_6200 78 -#define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79 -#define CX88_BOARD_HAUPPAUGE_IRONLY 80 -#define CX88_BOARD_WINFAST_DTV1800H 81 -#define CX88_BOARD_WINFAST_DTV2000H_J 82 -#define CX88_BOARD_PROF_7301 83 -#define CX88_BOARD_SAMSUNG_SMT_7020 84 -#define CX88_BOARD_TWINHAN_VP1027_DVBS 85 -#define CX88_BOARD_TEVII_S464 86 -#define CX88_BOARD_WINFAST_DTV2000H_PLUS 87 -#define CX88_BOARD_WINFAST_DTV1800H_XC4000 88 -#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36 89 -#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43 90 - -enum cx88_itype { - CX88_VMUX_COMPOSITE1 = 1, - CX88_VMUX_COMPOSITE2, - CX88_VMUX_COMPOSITE3, - CX88_VMUX_COMPOSITE4, - CX88_VMUX_SVIDEO, - CX88_VMUX_TELEVISION, - CX88_VMUX_CABLE, - CX88_VMUX_DVB, - CX88_VMUX_DEBUG, - CX88_RADIO, -}; - -struct cx88_input { - enum cx88_itype type; - u32 gpio0, gpio1, gpio2, gpio3; - unsigned int vmux:2; - unsigned int audioroute:4; -}; - -struct cx88_board { - const char *name; - unsigned int tuner_type; - unsigned int radio_type; - unsigned char tuner_addr; - unsigned char radio_addr; - int tda9887_conf; - struct cx88_input input[MAX_CX88_INPUT]; - struct cx88_input radio; - enum cx88_board_type mpeg; - unsigned int audio_chip; - int num_frontends; - - /* Used for I2S devices */ - int i2sinputcntl; -}; - -struct cx88_subid { - u16 subvendor; - u16 subdevice; - u32 card; -}; - -enum cx88_tvaudio { - WW_NONE = 1, - WW_BTSC, - WW_BG, - WW_DK, - WW_I, - WW_L, - WW_EIAJ, - WW_I2SPT, - WW_FM, - WW_I2SADC, - WW_M -}; - -#define INPUT(nr) (core->board.input[nr]) - -/* ----------------------------------------------------------- */ -/* device / file handle status */ - -#define RESOURCE_OVERLAY 1 -#define RESOURCE_VIDEO 2 -#define RESOURCE_VBI 4 - -#define BUFFER_TIMEOUT msecs_to_jiffies(2000) - -/* buffer for one video frame */ -struct cx88_buffer { - /* common v4l buffer stuff -- must be first */ - struct videobuf_buffer vb; - - /* cx88 specific */ - unsigned int bpl; - struct btcx_riscmem risc; - const struct cx8800_fmt *fmt; - u32 count; -}; - -struct cx88_dmaqueue { - struct list_head active; - struct list_head queued; - struct timer_list timeout; - struct btcx_riscmem stopper; - u32 count; -}; - -struct cx88_core { - struct list_head devlist; - atomic_t refcount; - - /* board name */ - int nr; - char name[32]; - - /* pci stuff */ - int pci_bus; - int pci_slot; - u32 __iomem *lmmio; - u8 __iomem *bmmio; - u32 shadow[SHADOW_MAX]; - int pci_irqmask; - - /* i2c i/o */ - struct i2c_adapter i2c_adap; - struct i2c_algo_bit_data i2c_algo; - struct i2c_client i2c_client; - u32 i2c_state, i2c_rc; - - /* config info -- analog */ - struct v4l2_device v4l2_dev; - struct v4l2_ctrl_handler video_hdl; - struct v4l2_ctrl *chroma_agc; - struct v4l2_ctrl_handler audio_hdl; - struct v4l2_subdev *sd_wm8775; - struct i2c_client *i2c_rtc; - unsigned int boardnr; - struct cx88_board board; - - /* Supported V4L _STD_ tuner formats */ - unsigned int tuner_formats; - - /* config info -- dvb */ -#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) - int (*prev_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); -#endif - void (*gate_ctrl)(struct cx88_core *core, int open); - - /* state info */ - struct task_struct *kthread; - v4l2_std_id tvnorm; - enum cx88_tvaudio tvaudio; - u32 audiomode_manual; - u32 audiomode_current; - u32 input; - u32 last_analog_input; - u32 astat; - u32 use_nicam; - unsigned long last_change; - - /* IR remote control state */ - struct cx88_IR *ir; - - /* I2C remote data */ - struct IR_i2c_init_data init_data; - struct wm8775_platform_data wm8775_data; - - struct mutex lock; - /* various v4l controls */ - u32 freq; - int users; - int mpeg_users; - - /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ - struct cx8802_dev *dvbdev; - enum cx88_board_type active_type_id; - int active_ref; - int active_fe_id; -}; - -static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev) -{ - return container_of(v4l2_dev, struct cx88_core, v4l2_dev); -} - -#define call_hw(core, grpid, o, f, args...) \ - do { \ - if (!core->i2c_rc) { \ - if (core->gate_ctrl) \ - core->gate_ctrl(core, 1); \ - v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \ - if (core->gate_ctrl) \ - core->gate_ctrl(core, 0); \ - } \ - } while (0) - -#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args) - -#define WM8775_GID (1 << 0) - -#define wm8775_s_ctrl(core, id, val) \ - do { \ - struct v4l2_ctrl *ctrl_ = \ - v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id); \ - if (ctrl_ && !core->i2c_rc) { \ - if (core->gate_ctrl) \ - core->gate_ctrl(core, 1); \ - v4l2_ctrl_s_ctrl(ctrl_, val); \ - if (core->gate_ctrl) \ - core->gate_ctrl(core, 0); \ - } \ - } while (0) - -#define wm8775_g_ctrl(core, id) \ - ({ \ - struct v4l2_ctrl *ctrl_ = \ - v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id); \ - s32 val = 0; \ - if (ctrl_ && !core->i2c_rc) { \ - if (core->gate_ctrl) \ - core->gate_ctrl(core, 1); \ - val = v4l2_ctrl_g_ctrl(ctrl_); \ - if (core->gate_ctrl) \ - core->gate_ctrl(core, 0); \ - } \ - val; \ - }) - -struct cx8800_dev; -struct cx8802_dev; - -/* ----------------------------------------------------------- */ -/* function 0: video stuff */ - -struct cx8800_fh { - struct v4l2_fh fh; - struct cx8800_dev *dev; - unsigned int resources; - - /* video capture */ - struct videobuf_queue vidq; - - /* vbi capture */ - struct videobuf_queue vbiq; -}; - -struct cx8800_suspend_state { - int disabled; -}; - -struct cx8800_dev { - struct cx88_core *core; - spinlock_t slock; - - /* various device info */ - unsigned int resources; - struct video_device *video_dev; - struct video_device *vbi_dev; - struct video_device *radio_dev; - - /* pci i/o */ - struct pci_dev *pci; - unsigned char pci_rev,pci_lat; - - const struct cx8800_fmt *fmt; - unsigned int width, height; - - /* capture queues */ - struct cx88_dmaqueue vidq; - struct cx88_dmaqueue vbiq; - - /* various v4l controls */ - - /* other global state info */ - struct cx8800_suspend_state state; -}; - -/* ----------------------------------------------------------- */ -/* function 1: audio/alsa stuff */ -/* =============> moved to cx88-alsa.c <====================== */ - - -/* ----------------------------------------------------------- */ -/* function 2: mpeg stuff */ - -struct cx8802_fh { - struct v4l2_fh fh; - struct cx8802_dev *dev; - struct videobuf_queue mpegq; -}; - -struct cx8802_suspend_state { - int disabled; -}; - -struct cx8802_driver { - struct cx88_core *core; - - /* List of drivers attached to device */ - struct list_head drvlist; - - /* Type of driver and access required */ - enum cx88_board_type type_id; - enum cx8802_board_access hw_access; - - /* MPEG 8802 internal only */ - int (*suspend)(struct pci_dev *pci_dev, pm_message_t state); - int (*resume)(struct pci_dev *pci_dev); - - /* Callers to the following functions must hold core->lock */ - - /* MPEG 8802 -> mini driver - Driver probe and configuration */ - int (*probe)(struct cx8802_driver *drv); - int (*remove)(struct cx8802_driver *drv); - - /* MPEG 8802 -> mini driver - Access for hardware control */ - int (*advise_acquire)(struct cx8802_driver *drv); - int (*advise_release)(struct cx8802_driver *drv); - - /* MPEG 8802 <- mini driver - Access for hardware control */ - int (*request_acquire)(struct cx8802_driver *drv); - int (*request_release)(struct cx8802_driver *drv); -}; - -struct cx8802_dev { - struct cx88_core *core; - spinlock_t slock; - - /* pci i/o */ - struct pci_dev *pci; - unsigned char pci_rev,pci_lat; - - /* dma queues */ - struct cx88_dmaqueue mpegq; - u32 ts_packet_size; - u32 ts_packet_count; - - /* other global state info */ - struct cx8802_suspend_state state; - - /* for blackbird only */ - struct list_head devlist; -#if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \ - defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE) - struct video_device *mpeg_dev; - u32 mailbox; - int width; - int height; - unsigned char mpeg_active; /* nonzero if mpeg encoder is active */ - - /* mpeg params */ - struct cx2341x_handler cxhdl; -#endif - -#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) - /* for dvb only */ - struct videobuf_dvb_frontends frontends; -#endif - -#if defined(CONFIG_VIDEO_CX88_VP3054) || \ - defined(CONFIG_VIDEO_CX88_VP3054_MODULE) - /* For VP3045 secondary I2C bus support */ - struct vp3054_i2c_state *vp3054; -#endif - /* for switching modulation types */ - unsigned char ts_gen_cntrl; - - /* List of attached drivers; must hold core->lock to access */ - struct list_head drvlist; - - struct work_struct request_module_wk; -}; - -/* ----------------------------------------------------------- */ - -#define cx_read(reg) readl(core->lmmio + ((reg)>>2)) -#define cx_write(reg,value) writel((value), core->lmmio + ((reg)>>2)) -#define cx_writeb(reg,value) writeb((value), core->bmmio + (reg)) - -#define cx_andor(reg,mask,value) \ - writel((readl(core->lmmio+((reg)>>2)) & ~(mask)) |\ - ((value) & (mask)), core->lmmio+((reg)>>2)) -#define cx_set(reg,bit) cx_andor((reg),(bit),(bit)) -#define cx_clear(reg,bit) cx_andor((reg),(bit),0) - -#define cx_wait(d) { if (need_resched()) schedule(); else udelay(d); } - -/* shadow registers */ -#define cx_sread(sreg) (core->shadow[sreg]) -#define cx_swrite(sreg,reg,value) \ - (core->shadow[sreg] = value, \ - writel(core->shadow[sreg], core->lmmio + ((reg)>>2))) -#define cx_sandor(sreg,reg,mask,value) \ - (core->shadow[sreg] = (core->shadow[sreg] & ~(mask)) | ((value) & (mask)), \ - writel(core->shadow[sreg], core->lmmio + ((reg)>>2))) - -/* ----------------------------------------------------------- */ -/* cx88-core.c */ - -extern void cx88_print_irqbits(const char *name, const char *tag, const char *strings[], - int len, u32 bits, u32 mask); - -extern int cx88_core_irq(struct cx88_core *core, u32 status); -extern void cx88_wakeup(struct cx88_core *core, - struct cx88_dmaqueue *q, u32 count); -extern void cx88_shutdown(struct cx88_core *core); -extern int cx88_reset(struct cx88_core *core); - -extern int -cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, - struct scatterlist *sglist, - unsigned int top_offset, unsigned int bottom_offset, - unsigned int bpl, unsigned int padding, unsigned int lines); -extern int -cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, - struct scatterlist *sglist, unsigned int bpl, - unsigned int lines, unsigned int lpi); -extern int -cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, - u32 reg, u32 mask, u32 value); -extern void -cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf); - -extern void cx88_risc_disasm(struct cx88_core *core, - struct btcx_riscmem *risc); -extern int cx88_sram_channel_setup(struct cx88_core *core, - const struct sram_channel *ch, - unsigned int bpl, u32 risc); -extern void cx88_sram_channel_dump(struct cx88_core *core, - const struct sram_channel *ch); - -extern int cx88_set_scale(struct cx88_core *core, unsigned int width, - unsigned int height, enum v4l2_field field); -extern int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm); - -extern struct video_device *cx88_vdev_init(struct cx88_core *core, - struct pci_dev *pci, - const struct video_device *template_, - const char *type); -extern struct cx88_core* cx88_core_get(struct pci_dev *pci); -extern void cx88_core_put(struct cx88_core *core, - struct pci_dev *pci); - -extern int cx88_start_audio_dma(struct cx88_core *core); -extern int cx88_stop_audio_dma(struct cx88_core *core); - - -/* ----------------------------------------------------------- */ -/* cx88-vbi.c */ - -/* Can be used as g_vbi_fmt, try_vbi_fmt and s_vbi_fmt */ -int cx8800_vbi_fmt (struct file *file, void *priv, - struct v4l2_format *f); - -/* -int cx8800_start_vbi_dma(struct cx8800_dev *dev, - struct cx88_dmaqueue *q, - struct cx88_buffer *buf); -*/ -int cx8800_stop_vbi_dma(struct cx8800_dev *dev); -int cx8800_restart_vbi_queue(struct cx8800_dev *dev, - struct cx88_dmaqueue *q); -void cx8800_vbi_timeout(unsigned long data); - -extern const struct videobuf_queue_ops cx8800_vbi_qops; - -/* ----------------------------------------------------------- */ -/* cx88-i2c.c */ - -extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci); - - -/* ----------------------------------------------------------- */ -/* cx88-cards.c */ - -extern int cx88_tuner_callback(void *dev, int component, int command, int arg); -extern int cx88_get_resources(const struct cx88_core *core, - struct pci_dev *pci); -extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr); -extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl); - -/* ----------------------------------------------------------- */ -/* cx88-tvaudio.c */ - -void cx88_set_tvaudio(struct cx88_core *core); -void cx88_newstation(struct cx88_core *core); -void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t); -void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual); -int cx88_audio_thread(void *data); - -int cx8802_register_driver(struct cx8802_driver *drv); -int cx8802_unregister_driver(struct cx8802_driver *drv); - -/* Caller must hold core->lock */ -struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype); - -/* ----------------------------------------------------------- */ -/* cx88-dsp.c */ - -s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core); - -/* ----------------------------------------------------------- */ -/* cx88-input.c */ - -int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci); -int cx88_ir_fini(struct cx88_core *core); -void cx88_ir_irq(struct cx88_core *core); -int cx88_ir_start(struct cx88_core *core); -void cx88_ir_stop(struct cx88_core *core); -extern void cx88_i2c_init_ir(struct cx88_core *core); - -/* ----------------------------------------------------------- */ -/* cx88-mpeg.c */ - -int cx8802_buf_prepare(struct videobuf_queue *q,struct cx8802_dev *dev, - struct cx88_buffer *buf, enum v4l2_field field); -void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf); -void cx8802_cancel_buffers(struct cx8802_dev *dev); - -/* ----------------------------------------------------------- */ -/* cx88-video.c*/ -int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i); -int cx88_set_freq (struct cx88_core *core,struct v4l2_frequency *f); -int cx88_video_mux(struct cx88_core *core, unsigned int input); -void cx88_querycap(struct file *file, struct cx88_core *core, - struct v4l2_capability *cap); |