diff options
Diffstat (limited to 'drivers/media/video/cx88')
-rw-r--r-- | drivers/media/video/cx88/Kconfig | 4 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-alsa.c | 315 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-blackbird.c | 31 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-cards.c | 219 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-core.c | 222 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-dvb.c | 25 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-i2c.c | 27 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-input.c | 20 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-mpeg.c | 142 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-reg.h | 35 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-tvaudio.c | 22 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-vbi.c | 13 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-video.c | 169 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-vp3054-i2c.c | 5 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88.h | 39 |
15 files changed, 659 insertions, 629 deletions
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index f750a543c961..eeb5224ca101 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -4,7 +4,7 @@ config VIDEO_CX88 select I2C_ALGOBIT select FW_LOADER select VIDEO_BTCX - select VIDEO_BUF + select VIDEOBUF_DMA_SG select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_IR @@ -46,7 +46,7 @@ config VIDEO_CX88_BLACKBIRD config VIDEO_CX88_DVB tristate "DVB/ATSC Support for cx2388x based TV cards" depends on VIDEO_CX88 && DVB_CORE - select VIDEO_BUF_DVB + select VIDEOBUF_DVB select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 2d666b56020c..90c36c5705c3 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -3,6 +3,7 @@ * 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> @@ -27,7 +28,9 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/interrupt.h> +#include <linux/vmalloc.h> #include <linux/dma-mapping.h> +#include <linux/pci.h> #include <asm/delay.h> #include <sound/driver.h> @@ -46,21 +49,16 @@ #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 ****************************************************************************/ -/* These can be replaced after done */ -#define MIXER_ADDR_LAST MAX_CX88_INPUT - struct cx88_audio_dev { struct cx88_core *core; struct cx88_dmaqueue q; /* pci i/o */ struct pci_dev *pci; - unsigned char pci_rev,pci_lat; /* audio controls */ int irq; @@ -68,24 +66,17 @@ struct cx88_audio_dev { 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; - - int mixer_volume[MIXER_ADDR_LAST+1][2]; - int capture_source[MIXER_ADDR_LAST+1][2]; - - long int read_count; - long int read_offset; - - struct cx88_buffer *buf; + struct videobuf_dmabuf *dma_risc; - long opened; - struct snd_pcm_substream *substream; + struct cx88_buffer *buf; + struct snd_pcm_substream *substream; }; typedef struct cx88_audio_dev snd_cx88_card_t; @@ -98,7 +89,6 @@ typedef struct cx88_audio_dev snd_cx88_card_t; static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; -static struct snd_card *snd_cx88_cards[SNDRV_CARDS]; module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled."); @@ -136,38 +126,39 @@ static int _cx88_start_audio_dma(snd_cx88_card_t *chip) struct cx88_core *core=chip->core; struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25]; - - dprintk(1, "Starting audio DMA for %i bytes/line and %i (%i) lines at address %08x\n",buf->bpl, chip->num_periods, audio_ch->fifo_size / buf->bpl, audio_ch->fifo_start); + /* 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, &cx88_sram_channels[SRAM_CH25], - buf->bpl, buf->risc.dma); + 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); - - dprintk(1,"Enabling IRQ, setting mask from 0x%x to 0x%x\n",chip->core->pci_irqmask,(chip->core->pci_irqmask | 0x02)); - /* enable irqs */ - cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | 0x02); + 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, - (1<<16)| - (1<<12)| - (1<<4)| - (1<<0) - ); + 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, &cx88_sram_channels[SRAM_CH25]); + cx88_sram_channel_dump(chip->core, audio_ch); return 0; } @@ -184,13 +175,9 @@ static int _cx88_stop_audio_dma(snd_cx88_card_t *chip) cx_clear(MO_AUD_DMACNTRL, 0x11); /* disable irqs */ - cx_clear(MO_PCI_INTMSK, 0x02); - cx_clear(MO_AUD_INTMSK, - (1<<16)| - (1<<12)| - (1<<4)| - (1<<0) - ); + 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]); @@ -198,7 +185,7 @@ static int _cx88_stop_audio_dma(snd_cx88_card_t *chip) return 0; } -#define MAX_IRQ_LOOP 10 +#define MAX_IRQ_LOOP 50 /* * BOARD Specific: IRQ dma bits @@ -223,42 +210,32 @@ static void cx8801_aud_irq(snd_cx88_card_t *chip) { struct cx88_core *core = chip->core; u32 status, mask; - u32 count; status = cx_read(MO_AUD_INTSTAT); mask = cx_read(MO_AUD_INTMSK); - if (0 == (status & mask)) { - spin_unlock(&chip->reg_lock); + 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 & (1 << 16)) { - printk(KERN_WARNING "%s/0: audio risc op code error\n",core->name); + 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]); } - - /* risc1 downstream */ - if (status & 0x01) { - spin_lock(&chip->reg_lock); - count = cx_read(MO_AUDD_GPCNT); - spin_unlock(&chip->reg_lock); - if (chip->read_count == 0) - chip->read_count += chip->dma_size; + if (status & AUD_INT_DN_SYNC) { + dprintk(1, "Downstream sync error\n"); + cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET); + return; } - - if (chip->read_count >= chip->period_size) { - dprintk(2, "Elapsing period\n"); + /* risc1 downstream */ + if (status & AUD_INT_DN_RISCI1) { + atomic_set(&chip->count, cx_read(MO_AUDD_GPCNT)); snd_pcm_period_elapsed(chip->substream); } - - dprintk(3,"Leaving audio IRQ handler...\n"); - /* FIXME: Any other status should deserve a special handling? */ } @@ -273,27 +250,26 @@ static irqreturn_t cx8801_irq(int irq, void *dev_id) int loop, handled = 0; for (loop = 0; loop < MAX_IRQ_LOOP; loop++) { - status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x02); + status = cx_read(MO_PCI_INTSTAT) & + (core->pci_irqmask | PCI_INT_AUDINT); if (0 == status) goto out; - dprintk( 3, "cx8801_irq\n" ); - dprintk( 3, " loop: %d/%d\n", loop, MAX_IRQ_LOOP ); - dprintk( 3, " status: %d\n", status ); + 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 & 0x02) - { - dprintk( 2, " ALSA IRQ handling\n" ); + if (status & core->pci_irqmask) + cx88_core_irq(core, status); + if (status & PCI_INT_AUDINT) cx8801_aud_irq(chip); - } - }; + } if (MAX_IRQ_LOOP == loop) { - dprintk( 0, "clearing mask\n" ); - dprintk(1,"%s/0: irq loop -- clearing mask\n", + printk(KERN_ERR + "%s/1: IRQ loop detected, disabling interrupts\n", core->name); - cx_clear(MO_PCI_INTMSK,0x02); + cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT); } out: @@ -306,14 +282,15 @@ static int dsp_buffer_free(snd_cx88_card_t *chip) BUG_ON(!chip->dma_size); dprintk(2,"Freeing buffer\n"); - videobuf_pci_dma_unmap(chip->pci, &chip->dma_risc); - videobuf_dma_free(&chip->dma_risc); + videobuf_pci_dma_unmap(chip->pci, 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; + return 0; } /**************************************************************************** @@ -323,6 +300,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip) /* * Digital hardware definition */ +#define DEFAULT_FIFO_SIZE 4096 static struct snd_pcm_hardware snd_cx88_digital_hw = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | @@ -333,22 +311,18 @@ static struct snd_pcm_hardware snd_cx88_digital_hw = { .rates = SNDRV_PCM_RATE_48000, .rate_min = 48000, .rate_max = 48000, - .channels_min = 1, + .channels_min = 2, .channels_max = 2, - .buffer_bytes_max = (2*2048), - .period_bytes_min = 2048, - .period_bytes_max = 2048, - .periods_min = 2, - .periods_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 runtime free - */ -static void snd_card_cx88_runtime_free(struct snd_pcm_runtime *runtime) -{ -} -/* * audio pcm capture open callback */ static int snd_cx88_pcm_open(struct snd_pcm_substream *substream) @@ -357,26 +331,24 @@ static int snd_cx88_pcm_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; int err; - if (test_and_set_bit(0, &chip->opened)) - return -EBUSY; - - err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); + err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS); if (err < 0) goto _error; chip->substream = substream; - chip->read_count = 0; - chip->read_offset = 0; - - runtime->private_free = snd_card_cx88_runtime_free; 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"); - clear_bit(0, &chip->opened); - smp_mb__after_clear_bit(); return err; } @@ -385,11 +357,6 @@ _error: */ static int snd_cx88_close(struct snd_pcm_substream *substream) { - snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); - - clear_bit(0, &chip->opened); - smp_mb__after_clear_bit(); - return 0; } @@ -400,55 +367,67 @@ 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_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)); - dprintk(1,"Setting buffer\n"); - - buf = kzalloc(sizeof(*buf),GFP_KERNEL); + buf = videobuf_pci_alloc(sizeof(*buf)); if (NULL == buf) return -ENOMEM; buf->vb.memory = V4L2_MEMORY_MMAP; + buf->vb.field = V4L2_FIELD_NONE; buf->vb.width = chip->period_size; + buf->bpl = chip->period_size; buf->vb.height = chip->num_periods; buf->vb.size = chip->dma_size; - buf->vb.field = V4L2_FIELD_NONE; - videobuf_dma_init(&buf->vb.dma); - videobuf_dma_init_kernel(&buf->vb.dma,PCI_DMA_FROMDEVICE, + dma=videobuf_to_dma(&buf->vb); + videobuf_dma_init(dma); + ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); + if (ret < 0) + goto error; - videobuf_pci_dma_map(chip->pci,&buf->vb.dma); + ret = videobuf_pci_dma_map(chip->pci,dma); + if (ret < 0) + goto error; + ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist, + buf->vb.width, buf->vb.height, 1); + if (ret < 0) + goto error; - cx88_risc_databuffer(chip->pci, &buf->risc, - buf->vb.dma.sglist, - buf->vb.width, buf->vb.height); - - buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); + /* Loop back to start of program */ + buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC); buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); buf->vb.state = STATE_PREPARED; - buf->bpl = chip->period_size; chip->buf = buf; - chip->dma_risc = buf->vb.dma; + chip->dma_risc = dma; - dprintk(1,"Buffer ready at %u\n",chip->dma_risc.nr_pages); - substream->runtime->dma_area = chip->dma_risc.vmalloc; + substream->runtime->dma_area = chip->dma_risc->vmalloc; + substream->runtime->dma_bytes = chip->dma_size; + substream->runtime->dma_addr = 0; return 0; + +error: + kfree(buf); + return ret; } /* @@ -475,7 +454,6 @@ static int snd_cx88_prepare(struct snd_pcm_substream *substream) return 0; } - /* * trigger callback */ @@ -484,6 +462,7 @@ 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) { @@ -510,17 +489,24 @@ 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; - if (chip->read_count) { - chip->read_count -= snd_pcm_lib_period_bytes(substream); - chip->read_offset += snd_pcm_lib_period_bytes(substream); - if (chip->read_offset == chip->dma_size) - chip->read_offset = 0; - } + count = atomic_read(&chip->count); - dprintk(2, "Pointer time, will return %li, read %li\n",chip->read_offset,chip->read_count); - return bytes_to_frames(runtime, chip->read_offset); +// dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __FUNCTION__, +// 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); } /* @@ -535,6 +521,7 @@ static struct snd_pcm_ops snd_cx88_pcm_ops = { .prepare = snd_cx88_prepare, .trigger = snd_cx88_card_trigger, .pointer = snd_cx88_pointer, + .page = snd_cx88_page, }; /* @@ -562,7 +549,7 @@ static int snd_cx88_capture_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *info) { info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 1; + info->count = 2; info->value.integer.min = 0; info->value.integer.max = 0x3f; @@ -575,8 +562,12 @@ static int snd_cx88_capture_volume_get(struct snd_kcontrol *kcontrol, { 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[0] = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f); + 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; } @@ -587,16 +578,31 @@ static int snd_cx88_capture_volume_put(struct snd_kcontrol *kcontrol, { snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); struct cx88_core *core=chip->core; - int v; - u32 old_control; - + int v, b; + int changed = 0; + u32 old; + + b = value->value.integer.value[1] - value->value.integer.value[0]; + if (b < 0) { + v = 0x3f - value->value.integer.value[0]; + b = (-b) | 0x40; + } else { + v = 0x3f - value->value.integer.value[1]; + } + /* Do we really know this will always be called with IRQs on? */ spin_lock_irq(&chip->reg_lock); - old_control = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f); - v = 0x3f - (value->value.integer.value[0] & 0x3f); - cx_andor(AUD_VOL_CTL, 0x3f, v); + old = cx_read(AUD_VOL_CTL); + if (v != (old & 0x3f)) { + cx_write(AUD_VOL_CTL, (old & ~0x3f) | v); + changed = 1; + } + if (cx_read(AUD_BAL_CTL) != b) { + cx_write(AUD_BAL_CTL, b); + changed = 1; + } spin_unlock_irq(&chip->reg_lock); - return v != old_control; + return changed; } static struct snd_kcontrol_new snd_cx88_capture_volume = { @@ -665,6 +671,7 @@ static int __devinit snd_cx88_create(struct snd_card *card, snd_cx88_card_t *chip; struct cx88_core *core; int err; + unsigned char pci_lat; *rchip = NULL; @@ -709,13 +716,12 @@ static int __devinit snd_cx88_create(struct snd_card *card, } /* print pci info */ - pci_read_config_byte(pci, PCI_CLASS_REVISION, &chip->pci_rev); - pci_read_config_byte(pci, PCI_LATENCY_TIMER, &chip->pci_lat); + 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), chip->pci_rev, pci->irq, - chip->pci_lat,(unsigned long long)pci_resource_start(pci,0)); + 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); @@ -753,17 +759,12 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, return (err); err = snd_cx88_pcm(chip, 0, "CX88 Digital"); - - if (err < 0) { - snd_card_free(card); - return (err); - } + if (err < 0) + goto error; err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_capture_volume, chip)); - if (err < 0) { - snd_card_free(card); - return (err); - } + if (err < 0) + goto error; strcpy (card->driver, "CX88x"); sprintf(card->shortname, "Conexant CX%x", pci->device); @@ -775,16 +776,16 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, card->driver,devno); err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return (err); - } - snd_cx88_cards[devno] = card; - + if (err < 0) + goto error; pci_set_drvdata(pci,card); devno++; return 0; + +error: + snd_card_free(card); + return err; } /* * ALSA destructor diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index f2fcdb92ecce..6d6f5048d762 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -27,7 +27,6 @@ */ #include <linux/module.h> -#include <linux/moduleparam.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/delay.h> @@ -734,14 +733,14 @@ static int vidioc_querycap (struct file *file, void *priv, struct cx88_core *core = dev->core; strcpy(cap->driver, "cx88_blackbird"); - strlcpy(cap->card, cx88_boards[core->board].name,sizeof(cap->card)); + strlcpy(cap->card, core->board.name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); cap->version = CX88_VERSION_CODE; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; - if (UNSET != core->tuner_type) + if (UNSET != core->board.tuner_type) cap->capabilities |= V4L2_CAP_TUNER; return 0; } @@ -877,7 +876,7 @@ static int vidioc_g_ext_ctrls (struct file *file, void *priv, if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) return -EINVAL; - return cx2341x_ext_ctrls(&dev->params, f, VIDIOC_G_EXT_CTRLS); + return cx2341x_ext_ctrls(&dev->params, 0, f, VIDIOC_G_EXT_CTRLS); } static int vidioc_s_ext_ctrls (struct file *file, void *priv, @@ -890,7 +889,7 @@ static int vidioc_s_ext_ctrls (struct file *file, void *priv, if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) return -EINVAL; p = dev->params; - err = cx2341x_ext_ctrls(&p, f, VIDIOC_S_EXT_CTRLS); + err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS); if (!err) { err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p); dev->params = p; @@ -908,7 +907,7 @@ static int vidioc_try_ext_ctrls (struct file *file, void *priv, if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG) return -EINVAL; p = dev->params; - err = cx2341x_ext_ctrls(&p, f, VIDIOC_TRY_EXT_CTRLS); + err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS); return err; } @@ -990,7 +989,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, struct cx8802_fh *fh = priv; struct cx88_core *core = fh->dev->core; - if (unlikely(UNSET == core->tuner_type)) + if (unlikely(UNSET == core->board.tuner_type)) return -EINVAL; f->type = V4L2_TUNER_ANALOG_TV; @@ -1028,7 +1027,7 @@ static int vidioc_g_tuner (struct file *file, void *priv, struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; u32 reg; - if (unlikely(UNSET == core->tuner_type)) + if (unlikely(UNSET == core->board.tuner_type)) return -EINVAL; if (0 != t->index) return -EINVAL; @@ -1049,7 +1048,7 @@ static int vidioc_s_tuner (struct file *file, void *priv, { struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; - if (UNSET == core->tuner_type) + if (UNSET == core->board.tuner_type) return -EINVAL; if (0 != t->index) return -EINVAL; @@ -1078,7 +1077,7 @@ static int mpeg_open(struct inode *inode, struct file *file) struct cx8802_driver *drv = NULL; int err; - dev = cx8802_get_device(inode); + dev = cx8802_get_device(inode); dprintk( 1, "%s\n", __FUNCTION__); @@ -1112,7 +1111,7 @@ static int mpeg_open(struct inode *inode, struct file *file) file->private_data = fh; fh->dev = dev; - videobuf_queue_init(&fh->mpegq, &blackbird_qops, + videobuf_queue_pci_init(&fh->mpegq, &blackbird_qops, dev->pci, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, @@ -1235,7 +1234,7 @@ static struct video_device cx8802_mpeg_template = .vidioc_s_tuner = vidioc_s_tuner, .vidioc_s_std = vidioc_s_std, .tvnorms = CX88_NORMS, - .current_norm = V4L2_STD_NTSC_M, + .current_norm = V4L2_STD_NTSC_M, }; /* ------------------------------------------------------------------ */ @@ -1246,7 +1245,7 @@ static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv) struct cx88_core *core = drv->core; int err = 0; - switch (core->board) { + 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. @@ -1268,7 +1267,7 @@ static int cx8802_blackbird_advise_release(struct cx8802_driver *drv) struct cx88_core *core = drv->core; int err = 0; - switch (core->board) { + switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_HVR1300: /* Exit leaving the cx23416 on the bus */ break; @@ -1316,13 +1315,13 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) dprintk( 1, "%s\n", __FUNCTION__); dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", - core->board, + core->boardnr, core->name, core->pci_bus, core->pci_slot); err = -ENODEV; - if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD)) + if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD)) goto fail_core; dev->width = 720; diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 6a136ddbccf8..a4eb6a87a761 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -27,10 +27,26 @@ #include "cx88.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"); + /* ------------------------------------------------------------------ */ /* board config info */ -struct cx88_board cx88_boards[] = { +static const struct cx88_board cx88_boards[] = { [CX88_BOARD_UNKNOWN] = { .name = "UNKNOWN/GENERIC", .tuner_type = UNSET, @@ -575,35 +591,34 @@ struct cx88_board cx88_boards[] = { .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, - .gpio1 = 0x00000000, - .gpio2 = 0x00000000, - .gpio3 = 0x00000000, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x00008400, - .gpio1 = 0x00000000, - .gpio2 = 0x00000000, - .gpio3 = 0x00000000, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x00008400, - .gpio1 = 0x00000000, - .gpio2 = 0x00000000, - .gpio3 = 0x00000000, }}, .radio = { .type = CX88_RADIO, - .vmux = 2, - .gpio0 = 0x00008400, - .gpio1 = 0x00000000, - .gpio2 = 0x00000000, - .gpio3 = 0x00000000, + .gpio0 = 0x00008404, }, .mpeg = CX88_MPEG_DVB, }, @@ -1356,12 +1371,11 @@ struct cx88_board cx88_boards[] = { }}, }, }; -const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); /* ------------------------------------------------------------------ */ /* PCI subsystem IDs */ -struct cx88_subid cx88_subids[] = { +static const struct cx88_subid cx88_subids[] = { { .subvendor = 0x0070, .subdevice = 0x3400, @@ -1667,7 +1681,6 @@ struct cx88_subid cx88_subids[] = { .card = CX88_BOARD_ADSTECH_PTV_390, }, }; -const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids); /* ----------------------------------------------------------------------- */ /* some leadtek specific stuff */ @@ -1688,12 +1701,12 @@ static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data) return; } - core->has_radio = 1; - core->tuner_type = (eeprom_data[6] == 0x13) ? 43 : 38; + core->board.tuner_type = (eeprom_data[6] == 0x13) ? + TUNER_PHILIPS_FM1236_MK3 : TUNER_PHILIPS_FM1216ME_MK3; printk(KERN_INFO "%s: Leadtek Winfast 2000XP Expert config: " "tuner=%d, eeprom[0]=0x%02x\n", - core->name, core->tuner_type, eeprom_data[0]); + core->name, core->board.tuner_type, eeprom_data[0]); } static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) @@ -1701,9 +1714,9 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) struct tveeprom tv; tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data); - core->tuner_type = tv.tuner_type; + core->board.tuner_type = tv.tuner_type; core->tuner_formats = tv.tuner_formats; - core->has_radio = tv.has_radio; + core->board.radio.type = tv.has_radio ? CX88_RADIO : 0; /* Make sure we support the board model */ switch (tv.model) @@ -1793,8 +1806,9 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) name ? name : "unknown"); if (NULL == name) return; - core->tuner_type = gdi_tuner[eeprom_data[0x0d]].id; - core->has_radio = gdi_tuner[eeprom_data[0x0d]].fm; + core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id; + core->board.radio.type = gdi_tuner[eeprom_data[0x0d]].fm ? + CX88_RADIO : 0; } /* ----------------------------------------------------------------------- */ @@ -1833,7 +1847,7 @@ static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core) /* ----------------------------------------------------------------------- */ -void cx88_card_list(struct cx88_core *core, struct pci_dev *pci) +static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci) { int i; @@ -1854,14 +1868,14 @@ void cx88_card_list(struct cx88_core *core, struct pci_dev *pci) } printk("%s: Here is a list of valid choices for the card=<n> insmod option:\n", core->name); - for (i = 0; i < cx88_bcount; i++) + for (i = 0; i < ARRAY_SIZE(cx88_boards); i++) printk("%s: card=%d -> %s\n", core->name, i, cx88_boards[i].name); } -void cx88_card_setup_pre_i2c(struct cx88_core *core) +static void cx88_card_setup_pre_i2c(struct cx88_core *core) { - switch (core->board) { + 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 */ @@ -1875,7 +1889,7 @@ void cx88_card_setup_pre_i2c(struct cx88_core *core) } } -void cx88_card_setup(struct cx88_core *core) +static void cx88_card_setup(struct cx88_core *core) { static u8 eeprom[256]; @@ -1884,7 +1898,7 @@ void cx88_card_setup(struct cx88_core *core) tveeprom_read(&core->i2c_client,eeprom,sizeof(eeprom)); } - switch (core->board) { + switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE: case CX88_BOARD_HAUPPAUGE_ROSLYN: if (0 == core->i2c_rc) @@ -1928,7 +1942,7 @@ void cx88_card_setup(struct cx88_core *core) msleep(1); cx_set(MO_GP0_IO, 0x00000101); if (0 == core->i2c_rc && - core->board == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID) + core->boardnr == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID) dvico_fusionhdtv_hybrid_init(core); break; case CX88_BOARD_KWORLD_DVB_T: @@ -1966,13 +1980,148 @@ void cx88_card_setup(struct cx88_core *core) } break; } - if (cx88_boards[core->board].radio.type == CX88_RADIO) - core->has_radio = 1; } /* ------------------------------------------------------------------ */ -EXPORT_SYMBOL(cx88_boards); +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); + + 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); + if (0 != cx88_get_resources(core, pci)) { + 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; + + /* 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)); + + printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", + core->name,pci->subsystem_vendor, + pci->subsystem_device, core->board.name, + core->boardnr, card[core->nr] == core->boardnr ? + "insmod option" : "autodetected"); + + if (tuner[core->nr] != UNSET) + core->board.tuner_type = tuner[core->nr]; + if (radio[core->nr] != UNSET) + core->board.radio_type = radio[core->nr]; + + printk(KERN_INFO "%s: TV tuner type %d, Radio tuner type %d\n", + core->name, core->board.tuner_type, core->board.radio_type); + + /* init hardware */ + cx88_reset(core); + cx88_card_setup_pre_i2c(core); + cx88_i2c_init(core, pci); + cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL); + cx88_card_setup(core); + cx88_ir_init(core, pci); + + return core; +} + +/* ------------------------------------------------------------------ */ /* * Local variables: diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index f31ec96924b9..62e8dd24c5f5 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -28,7 +28,6 @@ #include <linux/init.h> #include <linux/list.h> #include <linux/module.h> -#include <linux/moduleparam.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/kmod.h> @@ -52,22 +51,6 @@ static unsigned int core_debug = 0; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); -static unsigned int latency = UNSET; -module_param(latency,int,0444); -MODULE_PARM_DESC(latency,"pci latency timer"); - -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 nicam = 0; module_param(nicam,int,0644); MODULE_PARM_DESC(nicam,"tv audio is nicam"); @@ -85,13 +68,15 @@ 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 u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, unsigned int offset, u32 sync_line, unsigned int bpl, unsigned int padding, - unsigned int lines) + unsigned int lines, unsigned int lpi) { struct scatterlist *sg; - unsigned int line,todo; + unsigned int line,todo,sol; /* sync instruction */ if (sync_line != NO_SYNC_LINE) @@ -104,15 +89,19 @@ static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, 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|RISC_SOL|RISC_EOL|bpl); + *(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|RISC_SOL| + *(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); @@ -163,10 +152,10 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, rp = risc->cpu; if (UNSET != top_offset) rp = cx88_risc_field(rp, sglist, top_offset, 0, - bpl, padding, lines); + bpl, padding, lines, 0); if (UNSET != bottom_offset) rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200, - bpl, padding, lines); + bpl, padding, lines, 0); /* save pointer to jmp instruction address */ risc->jmp = rp; @@ -176,7 +165,7 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, struct scatterlist *sglist, unsigned int bpl, - unsigned int lines) + unsigned int lines, unsigned int lpi) { u32 instructions; u32 *rp; @@ -193,7 +182,7 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, /* write risc instructions */ rp = risc->cpu; - rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines); + rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi); /* save pointer to jmp instruction address */ risc->jmp = rp; @@ -224,10 +213,12 @@ int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, 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(&buf->vb,0,0); - videobuf_dma_unmap(q, &buf->vb.dma); - videobuf_dma_free(&buf->vb.dma); + videobuf_dma_unmap(q, dma); + videobuf_dma_free(dma); btcx_riscmem_free((struct pci_dev *)q->dev, &buf->risc); buf->vb.state = STATE_NEEDS_INIT; } @@ -451,10 +442,13 @@ void cx88_sram_channel_dump(struct cx88_core *core, printk("%s: cmds: %-12s: 0x%08x\n", core->name,name[i], cx_read(ch->cmds_start + 4*i)); - for (i = 0; i < 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); - cx88_risc_decode(risc); + 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); @@ -514,7 +508,7 @@ int cx88_core_irq(struct cx88_core *core, u32 status) { int handled = 0; - if (status & (1<<18)) { + if (status & PCI_INT_IR_SMPINT) { cx88_ir_irq(core); handled++; } @@ -738,7 +732,7 @@ int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int heig value |= (1 << 15); value |= (1 << 16); } - if (INPUT(core->input)->type == CX88_VMUX_SVIDEO) + 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) @@ -833,7 +827,7 @@ static int set_tvaudio(struct cx88_core *core) { v4l2_std_id norm = core->tvnorm; - if (CX88_VMUX_TELEVISION != INPUT(core->input)->type) + if (CX88_VMUX_TELEVISION != INPUT(core->input).type) return 0; if (V4L2_STD_PAL_BG & norm) { @@ -997,61 +991,6 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm) /* ------------------------------------------------------------------ */ -static int cx88_pci_quirks(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; -} - -/* ------------------------------------------------------------------ */ - struct video_device *cx88_vdev_init(struct cx88_core *core, struct pci_dev *pci, struct video_device *template, @@ -1067,122 +1006,38 @@ struct video_device *cx88_vdev_init(struct cx88_core *core, vfd->dev = &pci->dev; vfd->release = video_device_release; snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", - core->name, type, cx88_boards[core->board].name); + core->name, type, core->board.name); return vfd; } -static int get_ressources(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: can't get MMIO memory @ 0x%llx\n", - core->name,(unsigned long long)pci_resource_start(pci,0)); - return -EBUSY; -} - struct cx88_core* cx88_core_get(struct pci_dev *pci) { struct cx88_core *core; - struct list_head *item; - int i; mutex_lock(&devlist); - list_for_each(item,&cx88_devlist) { - core = list_entry(item, struct cx88_core, 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 != get_ressources(core,pci)) - goto fail_unlock; + if (0 != cx88_get_resources(core, pci)) { + mutex_unlock(&devlist); + return NULL; + } atomic_inc(&core->refcount); mutex_unlock(&devlist); return core; } - core = kzalloc(sizeof(*core),GFP_KERNEL); - if (NULL == core) - goto fail_unlock; - - atomic_inc(&core->refcount); - core->pci_bus = pci->bus->number; - core->pci_slot = PCI_SLOT(pci->devfn); - core->pci_irqmask = 0x00fc00; - mutex_init(&core->lock); - - core->nr = cx88_devcount++; - sprintf(core->name,"cx88[%d]",core->nr); - if (0 != get_ressources(core,pci)) { - printk(KERN_ERR "CORE %s No more PCI ressources for " - "subsystem: %04x:%04x, board: %s\n", - core->name,pci->subsystem_vendor, - pci->subsystem_device, - cx88_boards[core->board].name); - - cx88_devcount--; - goto fail_free; - } - list_add_tail(&core->devlist,&cx88_devlist); - - /* 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; - - /* board config */ - core->board = UNSET; - if (card[core->nr] < cx88_bcount) - core->board = card[core->nr]; - for (i = 0; UNSET == core->board && i < cx88_idcount; i++) - if (pci->subsystem_vendor == cx88_subids[i].subvendor && - pci->subsystem_device == cx88_subids[i].subdevice) - core->board = cx88_subids[i].card; - if (UNSET == core->board) { - core->board = CX88_BOARD_UNKNOWN; - cx88_card_list(core,pci); + + core = cx88_core_create(pci, cx88_devcount); + if (NULL != core) { + cx88_devcount++; + list_add_tail(&core->devlist, &cx88_devlist); } - printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", - core->name,pci->subsystem_vendor, - pci->subsystem_device,cx88_boards[core->board].name, - core->board, card[core->nr] == core->board ? - "insmod option" : "autodetected"); - - core->tuner_type = tuner[core->nr]; - core->radio_type = radio[core->nr]; - if (UNSET == core->tuner_type) - core->tuner_type = cx88_boards[core->board].tuner_type; - if (UNSET == core->radio_type) - core->radio_type = cx88_boards[core->board].radio_type; - if (!core->tuner_addr) - core->tuner_addr = cx88_boards[core->board].tuner_addr; - if (!core->radio_addr) - core->radio_addr = cx88_boards[core->board].radio_addr; - - printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n", - core->tuner_type, core->tuner_addr<<1, - core->radio_type, core->radio_addr<<1); - - core->tda9887_conf = cx88_boards[core->board].tda9887_conf; - - /* init hardware */ - cx88_reset(core); - cx88_card_setup_pre_i2c(core); - cx88_i2c_init(core,pci); - cx88_call_i2c_clients (core, TUNER_SET_STANDBY, NULL); - cx88_card_setup(core); - cx88_ir_init(core,pci); mutex_unlock(&devlist); return core; - -fail_free: - kfree(core); -fail_unlock: - mutex_unlock(&devlist); - return NULL; } void cx88_core_put(struct cx88_core *core, struct pci_dev *pci) @@ -1229,6 +1084,9 @@ 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 diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 1773b40467dc..d16e5c6d21c0 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -378,7 +378,7 @@ static int dvb_register(struct cx8802_dev *dev) dev->ts_gen_cntrl = 0x0c; /* init frontend */ - switch (dev->core->board) { + switch (dev->core->boardnr) { case CX88_BOARD_HAUPPAUGE_DVB_T1: dev->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config, @@ -482,7 +482,7 @@ static int dvb_register(struct cx8802_dev *dev) &dev->core->i2c_adap, DVB_PLL_FMD1216ME); } #else - printk("%s: built without vp3054 support\n", dev->core->name); + printk(KERN_ERR "%s/2: built without vp3054 support\n", dev->core->name); #endif break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: @@ -625,12 +625,12 @@ static int dvb_register(struct cx8802_dev *dev) } break; default: - printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", + printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", dev->core->name); break; } if (NULL == dev->dvb.frontend) { - printk("%s: frontend initialization failed\n",dev->core->name); + printk(KERN_ERR "%s/2: frontend initialization failed\n", dev->core->name); return -1; } @@ -653,7 +653,7 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) int err = 0; dprintk( 1, "%s\n", __FUNCTION__); - switch (core->board) { + 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 @@ -676,7 +676,7 @@ static int cx8802_dvb_advise_release(struct cx8802_driver *drv) int err = 0; dprintk( 1, "%s\n", __FUNCTION__); - switch (core->board) { + switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_HVR1300: /* Do Nothing, leave the cx22702 on the bus. */ break; @@ -694,13 +694,13 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) dprintk( 1, "%s\n", __FUNCTION__); dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", - core->board, + core->boardnr, core->name, core->pci_bus, core->pci_slot); err = -ENODEV; - if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) + if (!(core->board.mpeg & CX88_MPEG_DVB)) goto fail_core; /* If vp3054 isn't enabled, a stub will just return 0 */ @@ -709,8 +709,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) goto fail_core; /* dvb stuff */ - printk("%s/2: cx2388x based dvb card\n", core->name); - videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops, + printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); + videobuf_queue_pci_init(&dev->dvb.dvbq, &dvb_qops, dev->pci, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, @@ -718,7 +718,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) dev); err = dvb_register(dev); if (err != 0) - printk("%s dvb_register failed err = %d\n", __FUNCTION__, err); + printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n", + core->name, err); fail_core: return err; @@ -747,7 +748,7 @@ static struct cx8802_driver cx8802_dvb_driver = { static int dvb_init(void) { - printk(KERN_INFO "cx2388x dvb driver version %d.%d.%d loaded\n", + printk(KERN_INFO "cx88/2: cx2388x dvb driver version %d.%d.%d loaded\n", (CX88_VERSION_CODE >> 16) & 0xff, (CX88_VERSION_CODE >> 8) & 0xff, CX88_VERSION_CODE & 0xff); diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 78bbcfab9670..c8b1c50625f4 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -28,7 +28,6 @@ */ #include <linux/module.h> -#include <linux/moduleparam.h> #include <linux/init.h> #include <asm/io.h> @@ -108,28 +107,28 @@ static int attach_inform(struct i2c_client *client) if (!client->driver->command) return 0; - if (core->radio_type != UNSET) { - if ((core->radio_addr==ADDR_UNSET)||(core->radio_addr==client->addr)) { + if (core->board.radio_type != UNSET) { + if ((core->board.radio_addr==ADDR_UNSET)||(core->board.radio_addr==client->addr)) { tun_setup.mode_mask = T_RADIO; - tun_setup.type = core->radio_type; - tun_setup.addr = core->radio_addr; + tun_setup.type = core->board.radio_type; + tun_setup.addr = core->board.radio_addr; client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); } } - if (core->tuner_type != UNSET) { - if ((core->tuner_addr==ADDR_UNSET)||(core->tuner_addr==client->addr)) { + if (core->board.tuner_type != UNSET) { + if ((core->board.tuner_addr==ADDR_UNSET)||(core->board.tuner_addr==client->addr)) { tun_setup.mode_mask = T_ANALOG_TV; - tun_setup.type = core->tuner_type; - tun_setup.addr = core->tuner_addr; + tun_setup.type = core->board.tuner_type; + tun_setup.addr = core->board.tuner_addr; client->driver->command (client,TUNER_SET_TYPE_ADDR, &tun_setup); } } - if (core->tda9887_conf) - client->driver->command(client, TDA9887_SET_CONFIG, &core->tda9887_conf); + if (core->board.tda9887_conf) + client->driver->command(client, TDA9887_SET_CONFIG, &core->board.tda9887_conf); return 0; } @@ -146,7 +145,7 @@ void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg) if (0 != core->i2c_rc) return; -#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) +#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) if ( (core->dvbdev) && (core->dvbdev->dvb.frontend) ) { if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl) core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1); @@ -204,9 +203,9 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) memcpy(&core->i2c_algo, &cx8800_i2c_algo_template, sizeof(core->i2c_algo)); - if (core->tuner_type != TUNER_ABSENT) + if (core->board.tuner_type != TUNER_ABSENT) core->i2c_adap.class |= I2C_CLASS_TV_ANALOG; - if (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) + if (core->board.mpeg & CX88_MPEG_DVB) core->i2c_adap.class |= I2C_CLASS_TV_DIGITAL; core->i2c_adap.dev.parent = &pci->dev; diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index f5d4a565346e..e52de3968c63 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -27,7 +27,6 @@ #include <linux/input.h> #include <linux/pci.h> #include <linux/module.h> -#include <linux/moduleparam.h> #include "cx88.h" #include <media/ir-common.h> @@ -74,7 +73,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) /* read gpio value */ gpio = cx_read(ir->gpio_addr); - switch (core->board) { + 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 @@ -113,7 +112,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) (gpio & ir->mask_keydown) ? " down" : "", (gpio & ir->mask_keyup) ? " up" : ""); - if (ir->core->board == CX88_BOARD_NORWOOD_MICRO) { + if (ir->core->boardnr == CX88_BOARD_NORWOOD_MICRO) { u32 gpio_key = cx_read(MO_GP0_IO); data = (data << 4) | ((gpio_key & 0xf0) >> 4); @@ -159,7 +158,7 @@ static void cx88_ir_work(struct work_struct *work) mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling)); } -static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) +void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) { if (ir->polling) { setup_timer(&ir->timer, ir_timer, (unsigned long)ir); @@ -167,17 +166,17 @@ static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir) schedule_work(&ir->work); } if (ir->sampling) { - core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */ + core->pci_irqmask |= PCI_INT_IR_SMPINT; cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */ cx_write(MO_DDSCFG_IO, 0x5); /* enable */ } } -static void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) +void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir) { if (ir->sampling) { cx_write(MO_DDSCFG_IO, 0x0); - core->pci_irqmask &= ~(1 << 18); + core->pci_irqmask &= ~PCI_INT_IR_SMPINT; } if (ir->polling) { @@ -204,7 +203,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->input = input_dev; /* detect & configure */ - switch (core->board) { + switch (core->boardnr) { case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_KWORLD_DVB_T_CX22702: @@ -314,8 +313,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) } /* init input device */ - snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", - cx88_boards[core->board].name); + snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name); snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci)); ir_input_init(input_dev, &ir->ir, ir_type, ir_codes); @@ -406,7 +404,7 @@ void cx88_ir_irq(struct cx88_core *core) ir_dump_samples(ir->samples, ir->scount); /* decode it */ - switch (core->board) { + switch (core->boardnr) { case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4); diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index da7a6b591a67..a652f294d23d 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -23,12 +23,10 @@ */ #include <linux/module.h> -#include <linux/moduleparam.h> #include <linux/init.h> #include <linux/device.h> #include <linux/dma-mapping.h> #include <linux/interrupt.h> -#include <linux/dma-mapping.h> #include <asm/delay.h> #include "cx88.h" @@ -56,9 +54,9 @@ static void request_module_async(struct work_struct *work) { struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk); - if (cx88_boards[dev->core->board].mpeg & CX88_MPEG_DVB) + if (dev->core->board.mpeg & CX88_MPEG_DVB) request_module("cx88-dvb"); - if (cx88_boards[dev->core->board].mpeg & CX88_MPEG_BLACKBIRD) + if (dev->core->board.mpeg & CX88_MPEG_BLACKBIRD) request_module("cx88-blackbird"); } @@ -96,7 +94,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id); if ( (core->active_type_id == CX88_MPEG_DVB) && - (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) ) { + (core->board.mpeg & CX88_MPEG_DVB) ) { dprintk( 1, "cx8802_start_dma doing .dvb\n"); /* negedge driven & software reset */ @@ -104,7 +102,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, udelay(100); cx_write(MO_PINMUX_IO, 0x00); cx_write(TS_HW_SOP_CNTRL,0x47<<16|188<<4|0x01); - switch (core->board) { + 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: @@ -125,7 +123,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl); udelay(100); } else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) && - (cx88_boards[core->board].mpeg & 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 */ @@ -139,7 +137,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, udelay(100); } else { printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__, - cx88_boards[core->board].mpeg ); + core->board.mpeg ); return -EINVAL; } @@ -149,7 +147,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev, /* enable irqs */ dprintk( 1, "setting the interrupt mask\n" ); - cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04); + cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_TSINT); cx_set(MO_TS_INTMSK, 0x1f0011); /* start dma */ @@ -167,7 +165,7 @@ static int cx8802_stop_dma(struct cx8802_dev *dev) cx_clear(MO_TS_DMACNTRL, 0x11); /* disable irqs */ - cx_clear(MO_PCI_INTMSK, 0x000004); + cx_clear(MO_PCI_INTMSK, PCI_INT_TSINT); cx_clear(MO_TS_INTMSK, 0x1f0011); /* Reset the controller */ @@ -181,43 +179,43 @@ static int cx8802_restart_queue(struct cx8802_dev *dev, struct cx88_buffer *buf; struct list_head *item; - dprintk( 1, "cx8802_restart_queue\n" ); + 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 = STATE_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 = STATE_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; - } + 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 = STATE_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 = STATE_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; } @@ -239,6 +237,7 @@ 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", __FUNCTION__, buf); @@ -254,8 +253,8 @@ int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev, if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) goto fail; cx88_risc_databuffer(dev->pci, &buf->risc, - buf->vb.dma.sglist, - buf->vb.width, buf->vb.height); + dma->sglist, + buf->vb.width, buf->vb.height, 0); } buf->vb.state = STATE_PREPARED; return 0; @@ -414,7 +413,8 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id) int loop, handled = 0; for (loop = 0; loop < MAX_IRQ_LOOP; loop++) { - status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04); + status = cx_read(MO_PCI_INTSTAT) & + (core->pci_irqmask | PCI_INT_TSINT); if (0 == status) goto out; dprintk( 1, "cx8802_irq\n" ); @@ -425,7 +425,7 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id) if (status & core->pci_irqmask) cx88_core_irq(core,status); - if (status & 0x04) + if (status & PCI_INT_TSINT) cx8802_mpeg_irq(dev); }; if (MAX_IRQ_LOOP == loop) { @@ -676,22 +676,24 @@ int cx8802_register_driver(struct cx8802_driver *drv) struct list_head *list; int err = 0, i = 0; - printk(KERN_INFO "%s() ->registering driver type=%s access=%s\n", __FUNCTION__ , - drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird", - drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive"); + 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_INFO "%s() cx8802_driver is invalid\n", __FUNCTION__ ); + printk(KERN_ERR "cx88/2: cx8802_driver is invalid\n"); return err; } list_for_each(list,&cx8802_devlist) { h = list_entry(list, struct cx8802_dev, devlist); - printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n", - h->core->name,h->pci->subsystem_vendor, - h->pci->subsystem_device,cx88_boards[h->core->board].name, - h->core->board); + printk(KERN_INFO + "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", + h->core->name, h->pci->subsystem_vendor, + h->pci->subsystem_device, h->core->board.name, + h->core->boardnr); /* Bring up a new struct for each driver instance */ driver = kzalloc(sizeof(*drv),GFP_KERNEL); @@ -713,7 +715,9 @@ int cx8802_register_driver(struct cx8802_driver *drv) list_add_tail(&driver->devlist,&h->drvlist.devlist); mutex_unlock(&drv->core->lock); } else { - printk(KERN_ERR "%s() ->probe failed err = %d\n", __FUNCTION__, err); + printk(KERN_ERR + "%s/2: cx8802 probe failed, err = %d\n", + h->core->name, err); } } @@ -733,17 +737,20 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) struct list_head *list2, *q; int err = 0, i = 0; - printk(KERN_INFO "%s() ->unregistering driver type=%s\n", __FUNCTION__ , - drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird"); + 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"); list_for_each(list,&cx8802_devlist) { i++; h = list_entry(list, struct cx8802_dev, devlist); - printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n", - h->core->name,h->pci->subsystem_vendor, - h->pci->subsystem_device,cx88_boards[h->core->board].name, - h->core->board); + printk(KERN_INFO + "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n", + h->core->name, h->pci->subsystem_vendor, + h->pci->subsystem_device, h->core->board.name, + h->core->boardnr); list_for_each_safe(list2, q, &h->drvlist.devlist) { d = list_entry(list2, struct cx8802_driver, devlist); @@ -758,7 +765,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv) list_del(list2); mutex_unlock(&drv->core->lock); } else - printk(KERN_ERR "%s() ->remove failed err = %d\n", __FUNCTION__, err); + printk(KERN_ERR "%s/2: cx8802 driver remove " + "failed (%d)\n", h->core->name, err); } @@ -783,7 +791,7 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, printk("%s/2: cx2388x 8802 Driver Manager\n", core->name); err = -ENODEV; - if (!cx88_boards[core->board].mpeg) + if (!core->board.mpeg) goto fail_core; err = -ENOMEM; @@ -866,7 +874,7 @@ static struct pci_driver cx8802_pci_driver = { static int cx8802_init(void) { - printk(KERN_INFO "cx2388x cx88-mpeg Driver Manager version %d.%d.%d loaded\n", + printk(KERN_INFO "cx88/2: cx2388x MPEG-TS Driver Manager version %d.%d.%d loaded\n", (CX88_VERSION_CODE >> 16) & 0xff, (CX88_VERSION_CODE >> 8) & 0xff, CX88_VERSION_CODE & 0xff); diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h index d3bf5b17b1d4..2ec52d1cdea0 100644 --- a/drivers/media/video/cx88/cx88-reg.h +++ b/drivers/media/video/cx88/cx88-reg.h @@ -582,6 +582,28 @@ /* ---------------------------------------------------------------------- */ /* 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 @@ -590,6 +612,19 @@ #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 diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 1cc2d286a1cb..76e5c78d8ae4 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -36,7 +36,6 @@ */ #include <linux/module.h> -#include <linux/moduleparam.h> #include <linux/errno.h> #include <linux/freezer.h> #include <linux/kernel.h> @@ -62,6 +61,10 @@ static unsigned int always_analog = 0; module_param(always_analog,int,0644); MODULE_PARM_DESC(always_analog,"force analog audio out"); +static unsigned int radio_deemphasis = 0; +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) @@ -140,7 +143,7 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) cx_write(AUD_RATE_THRES_DMD, 0x000000C0); cx88_start_audio_dma(core); - if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { + 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 */ @@ -149,7 +152,7 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl) cx_write(AUD_I2SCNTL, 0); /* cx_write(AUD_APB_IN_RATE_ADJ, 0); */ } - if ((always_analog) || (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD))) { + if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) { ctl |= EN_DAC_ENABLE; cx_write(AUD_CTL, ctl); } @@ -678,6 +681,10 @@ static void set_audio_standard_FM(struct cx88_core *core, }; /* 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}, @@ -688,6 +695,7 @@ static void set_audio_standard_FM(struct cx88_core *core, set_audio_start(core, SEL_FMRADIO); switch (deemph) { + default: case FM_NO_DEEMPH: set_audio_registers(core, fm_no_deemph); break; @@ -757,7 +765,7 @@ void cx88_set_tvaudio(struct cx88_core *core) set_audio_standard_EIAJ(core); break; case WW_FM: - set_audio_standard_FM(core, FM_NO_DEEMPH); + set_audio_standard_FM(core, radio_deemphasis); break; case WW_NONE: default: @@ -790,9 +798,9 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) core->astat = reg; /* TODO - Reading from AUD_STATUS is not enough - for auto-detecting sap/dual-fm/nicam. - Add some code here later. + Reading from AUD_STATUS is not enough + for auto-detecting sap/dual-fm/nicam. + Add some code here later. */ return; diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c index 86c1cf8334bc..babb08556406 100644 --- a/drivers/media/video/cx88/cx88-vbi.c +++ b/drivers/media/video/cx88/cx88-vbi.c @@ -2,7 +2,6 @@ */ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/moduleparam.h> #include <linux/init.h> #include <linux/slab.h> @@ -67,7 +66,7 @@ static int cx8800_start_vbi_dma(struct cx8800_dev *dev, q->count = 1; /* enable irqs */ - cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01); + cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT); cx_set(MO_VID_INTMSK, 0x0f0088); /* enable capture */ @@ -91,7 +90,7 @@ int cx8800_stop_vbi_dma(struct cx8800_dev *dev) cx_clear(VID_CAPTURE_CONTROL,0x18); /* disable irqs */ - cx_clear(MO_PCI_INTMSK, 0x000001); + cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT); cx_clear(MO_VID_INTMSK, 0x0f0088); return 0; } @@ -100,7 +99,6 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev, struct cx88_dmaqueue *q) { struct cx88_buffer *buf; - struct list_head *item; if (list_empty(&q->active)) return 0; @@ -109,10 +107,8 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev, dprintk(2,"restart_queue [%p/%d]: restart dma\n", buf, buf->vb.i); cx8800_start_vbi_dma(dev, q, buf); - list_for_each(item,&q->active) { - buf = list_entry(item, struct cx88_buffer, vb.queue); + list_for_each_entry(buf, &q->active, vb.queue) buf->count = q->count++; - } mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); return 0; } @@ -173,6 +169,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, return -EINVAL; if (STATE_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; @@ -181,7 +178,7 @@ vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) goto fail; cx88_risc_buffer(dev->pci, &buf->risc, - buf->vb.dma.sglist, + dma->sglist, 0, buf->vb.width * buf->vb.height, buf->vb.width, 0, buf->vb.height); diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 06b233a7b20b..231ae6c4dd22 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -28,7 +28,6 @@ #include <linux/init.h> #include <linux/list.h> #include <linux/module.h> -#include <linux/moduleparam.h> #include <linux/kmod.h> #include <linux/kernel.h> #include <linux/slab.h> @@ -36,7 +35,6 @@ #include <linux/dma-mapping.h> #include <linux/delay.h> #include <linux/kthread.h> -#include <linux/dma-mapping.h> #include <asm/div64.h> #include "cx88.h" @@ -369,17 +367,17 @@ 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); + 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); + 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) { + switch (INPUT(input).type) { case CX88_VMUX_SVIDEO: cx_set(MO_AFECFG_IO, 0x00000001); cx_set(MO_INPUT_FORMAT, 0x00010010); @@ -394,9 +392,9 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) break; } - if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { + if (core->board.mpeg & CX88_MPEG_BLACKBIRD) { /* sets sound input from external adc */ - if (INPUT(input)->extadc) + if (INPUT(input).extadc) cx_set(AUD_CTL, EN_I2SIN_ENABLE); else cx_clear(AUD_CTL, EN_I2SIN_ENABLE); @@ -424,7 +422,7 @@ static int start_video_dma(struct cx8800_dev *dev, q->count = 1; /* enable irqs */ - cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x01); + 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 @@ -457,7 +455,7 @@ static int stop_video_dma(struct cx8800_dev *dev) cx_clear(VID_CAPTURE_CONTROL,0x06); /* disable irqs */ - cx_clear(MO_PCI_INTMSK, 0x000001); + cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT); cx_clear(MO_VID_INTMSK, 0x0f0011); return 0; } @@ -468,17 +466,14 @@ static int restart_video_queue(struct cx8800_dev *dev, { struct cx88_core *core = dev->core; struct cx88_buffer *buf, *prev; - struct list_head *item; 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(item,&q->active) { - buf = list_entry(item, struct cx88_buffer, vb.queue); - buf->count = q->count++; - } + list_for_each_entry(buf, &q->active, vb.queue) + buf->count = q->count++; mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); return 0; } @@ -536,6 +531,7 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, 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 == fh->fmt); @@ -568,30 +564,30 @@ buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, switch (buf->vb.field) { case V4L2_FIELD_TOP: cx88_risc_buffer(dev->pci, &buf->risc, - buf->vb.dma.sglist, 0, UNSET, + dma->sglist, 0, UNSET, buf->bpl, 0, buf->vb.height); break; case V4L2_FIELD_BOTTOM: cx88_risc_buffer(dev->pci, &buf->risc, - buf->vb.dma.sglist, UNSET, 0, + dma->sglist, UNSET, 0, buf->bpl, 0, buf->vb.height); break; case V4L2_FIELD_INTERLACED: cx88_risc_buffer(dev->pci, &buf->risc, - buf->vb.dma.sglist, 0, buf->bpl, + 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, - buf->vb.dma.sglist, + 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, - buf->vb.dma.sglist, + dma->sglist, buf->bpl * (buf->vb.height >> 1), 0, buf->bpl, 0, buf->vb.height >> 1); @@ -714,12 +710,10 @@ static int video_open(struct inode *inode, struct file *file) struct cx8800_dev *h,*dev = NULL; struct cx88_core *core; struct cx8800_fh *fh; - struct list_head *list; enum v4l2_buf_type type = 0; int radio = 0; - list_for_each(list,&cx8800_devlist) { - h = list_entry(list, struct cx8800_dev, devlist); + list_for_each_entry(h, &cx8800_devlist, devlist) { if (h->video_dev->minor == minor) { dev = h; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -754,13 +748,13 @@ static int video_open(struct inode *inode, struct file *file) fh->height = 240; fh->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); - videobuf_queue_init(&fh->vidq, &cx8800_video_qops, + videobuf_queue_pci_init(&fh->vidq, &cx8800_video_qops, dev->pci, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED, sizeof(struct cx88_buffer), fh); - videobuf_queue_init(&fh->vbiq, &cx8800_vbi_qops, + videobuf_queue_pci_init(&fh->vbiq, &cx8800_vbi_qops, dev->pci, &dev->slock, V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_FIELD_SEQ_TB, @@ -768,12 +762,11 @@ static int video_open(struct inode *inode, struct file *file) fh); if (fh->radio) { - int board = core->board; dprintk(1,"video_open: setting radio device\n"); - cx_write(MO_GP3_IO, cx88_boards[board].radio.gpio3); - cx_write(MO_GP0_IO, cx88_boards[board].radio.gpio0); - cx_write(MO_GP1_IO, cx88_boards[board].radio.gpio1); - cx_write(MO_GP2_IO, cx88_boards[board].radio.gpio2); + 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); core->tvaudio = WW_FM; cx88_set_tvaudio(core); cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); @@ -1079,8 +1072,7 @@ static int vidioc_querycap (struct file *file, void *priv, struct cx88_core *core = dev->core; strcpy(cap->driver, "cx8800"); - strlcpy(cap->card, cx88_boards[core->board].name, - sizeof(cap->card)); + strlcpy(cap->card, core->board.name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); cap->version = CX88_VERSION_CODE; cap->capabilities = @@ -1088,7 +1080,7 @@ static int vidioc_querycap (struct file *file, void *priv, V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_VBI_CAPTURE; - if (UNSET != core->tuner_type) + if (UNSET != core->board.tuner_type) cap->capabilities |= V4L2_CAP_TUNER; return 0; } @@ -1108,28 +1100,9 @@ static int vidioc_enum_fmt_cap (struct file *file, void *priv, #ifdef CONFIG_VIDEO_V4L1_COMPAT static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) { - struct cx8800_fh *fh = priv; - struct videobuf_queue *q; - struct v4l2_requestbuffers req; - unsigned int i; - int err; + struct cx8800_fh *fh = priv; - q = get_queue(fh); - memset(&req,0,sizeof(req)); - req.type = q->type; - req.count = 8; - req.memory = V4L2_MEMORY_MMAP; - err = videobuf_reqbufs(q,&req); - if (err < 0) - return err; - - mbuf->frames = req.count; - mbuf->size = 0; - for (i = 0; i < mbuf->frames; i++) { - mbuf->offsets[i] = q->bufs[i]->boff; - mbuf->size += q->bufs[i]->bsize; - } - return 0; + return videobuf_cgmbuf (get_queue(fh), mbuf, 8); } #endif @@ -1222,14 +1195,14 @@ int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i) n = i->index; if (n >= 4) return -EINVAL; - if (0 == INPUT(n)->type) + if (0 == INPUT(n).type) return -EINVAL; memset(i,0,sizeof(*i)); i->index = n; i->type = V4L2_INPUT_TYPE_CAMERA; - strcpy(i->name,iname[INPUT(n)->type]); - if ((CX88_VMUX_TELEVISION == INPUT(n)->type) || - (CX88_VMUX_CABLE == INPUT(n)->type)) + 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; @@ -1298,7 +1271,7 @@ static int vidioc_g_tuner (struct file *file, void *priv, struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; u32 reg; - if (unlikely(UNSET == core->tuner_type)) + if (unlikely(UNSET == core->board.tuner_type)) return -EINVAL; if (0 != t->index) return -EINVAL; @@ -1319,7 +1292,7 @@ static int vidioc_s_tuner (struct file *file, void *priv, { struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; - if (UNSET == core->tuner_type) + if (UNSET == core->board.tuner_type) return -EINVAL; if (0 != t->index) return -EINVAL; @@ -1334,7 +1307,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, struct cx8800_fh *fh = priv; struct cx88_core *core = fh->dev->core; - if (unlikely(UNSET == core->tuner_type)) + if (unlikely(UNSET == core->board.tuner_type)) return -EINVAL; /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */ @@ -1349,7 +1322,7 @@ static int vidioc_g_frequency (struct file *file, void *priv, int cx88_set_freq (struct cx88_core *core, struct v4l2_frequency *f) { - if (unlikely(UNSET == core->tuner_type)) + if (unlikely(UNSET == core->board.tuner_type)) return -EINVAL; if (unlikely(f->tuner != 0)) return -EINVAL; @@ -1420,8 +1393,7 @@ static int radio_querycap (struct file *file, void *priv, struct cx88_core *core = dev->core; strcpy(cap->driver, "cx8800"); - strlcpy(cap->card, cx88_boards[core->board].name, - sizeof(cap->card)); + strlcpy(cap->card, core->board.name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci)); cap->version = CX88_VERSION_CODE; cap->capabilities = V4L2_CAP_TUNER; @@ -1608,7 +1580,8 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id) int loop, handled = 0; for (loop = 0; loop < 10; loop++) { - status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x01); + status = cx_read(MO_PCI_INTSTAT) & + (core->pci_irqmask | PCI_INT_VIDINT); if (0 == status) goto out; cx_write(MO_PCI_INTSTAT, status); @@ -1616,7 +1589,7 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id) if (status & core->pci_irqmask) cx88_core_irq(core,status); - if (status & 0x01) + if (status & PCI_INT_VIDINT) cx8800_vid_irq(dev); }; if (10 == loop) { @@ -1717,6 +1690,10 @@ static struct video_device cx8800_radio_template = .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_g_frequency = vidioc_g_frequency, .vidioc_s_frequency = vidioc_s_frequency, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .vidioc_g_register = vidioc_g_register, + .vidioc_s_register = vidioc_s_register, +#endif }; /* ----------------------------------------------------------- */ @@ -1818,26 +1795,32 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, err = request_irq(pci_dev->irq, cx8800_irq, IRQF_SHARED | IRQF_DISABLED, core->name, dev); if (err < 0) { - printk(KERN_ERR "%s: can't get IRQ %d\n", + 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); /* load and configure helper modules */ - if (TUNER_ABSENT != core->tuner_type) + if (TUNER_ABSENT != core->board.tuner_type) request_module("tuner"); - if (cx88_boards[ core->board ].audio_chip == AUDIO_CHIP_WM8775) + if (core->board.audio_chip == AUDIO_CHIP_WM8775) request_module("wm8775"); + switch (core->boardnr) { + case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: + request_module("ir-kbd-i2c"); + request_module("rtc-isl1208"); + } + /* register v4l devices */ dev->video_dev = cx88_vdev_init(core,dev->pci, &cx8800_video_template,"video"); err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, video_nr[core->nr]); if (err < 0) { - printk(KERN_INFO "%s: can't register video device\n", + printk(KERN_ERR "%s/0: can't register video device\n", core->name); goto fail_unreg; } @@ -1848,20 +1831,20 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, vbi_nr[core->nr]); if (err < 0) { - printk(KERN_INFO "%s/0: can't register vbi device\n", + printk(KERN_ERR "%s/0: can't register vbi device\n", core->name); goto fail_unreg; } printk(KERN_INFO "%s/0: registered device vbi%d\n", core->name,dev->vbi_dev->minor & 0x1f); - if (core->has_radio) { + if (core->board.radio.type == CX88_RADIO) { dev->radio_dev = cx88_vdev_init(core,dev->pci, &cx8800_radio_template,"radio"); err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO, radio_nr[core->nr]); if (err < 0) { - printk(KERN_INFO "%s/0: can't register radio device\n", + printk(KERN_ERR "%s/0: can't register radio device\n", core->name); goto fail_unreg; } @@ -1881,12 +1864,12 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, mutex_unlock(&core->lock); /* start tvaudio thread */ - if (core->tuner_type != TUNER_ABSENT) { + 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 "Failed to create cx88 audio thread, err=%d\n", - err); + printk(KERN_ERR "%s/0: failed to create cx88 audio thread, err=%d\n", + core->name, err); } } return 0; @@ -1937,17 +1920,19 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state) /* stop video+vbi capture */ spin_lock(&dev->slock); if (!list_empty(&dev->vidq.active)) { - printk("%s: suspend video\n", core->name); + 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: suspend vbi\n", core->name); + 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, core->ir); /* FIXME -- shutdown device */ cx88_shutdown(core); @@ -1968,8 +1953,8 @@ static int cx8800_resume(struct pci_dev *pci_dev) if (dev->state.disabled) { err=pci_enable_device(pci_dev); if (err) { - printk(KERN_ERR "%s: can't enable device\n", - core->name); + printk(KERN_ERR "%s/0: can't enable device\n", + core->name); return err; } @@ -1977,9 +1962,7 @@ static int cx8800_resume(struct pci_dev *pci_dev) } err= pci_set_power_state(pci_dev, PCI_D0); if (err) { - printk(KERN_ERR "%s: can't enable device\n", - core->name); - + printk(KERN_ERR "%s/0: can't set power state\n", core->name); pci_disable_device(pci_dev); dev->state.disabled = 1; @@ -1989,15 +1972,19 @@ static int cx8800_resume(struct pci_dev *pci_dev) /* FIXME: re-initialize hardware */ cx88_reset(core); + if (core->ir) + cx88_ir_start(core, core->ir); + + cx_set(MO_PCI_INTMSK, core->pci_irqmask); /* restart video+vbi capture */ spin_lock(&dev->slock); if (!list_empty(&dev->vidq.active)) { - printk("%s: resume video\n", core->name); + printk("%s/0: resume video\n", core->name); restart_video_queue(dev,&dev->vidq); } if (!list_empty(&dev->vbiq.active)) { - printk("%s: resume vbi\n", core->name); + printk("%s/0: resume vbi\n", core->name); cx8800_restart_vbi_queue(dev,&dev->vbiq); } spin_unlock(&dev->slock); @@ -2033,7 +2020,7 @@ static struct pci_driver cx8800_pci_driver = { static int cx8800_init(void) { - printk(KERN_INFO "cx2388x v4l2 driver version %d.%d.%d loaded\n", + printk(KERN_INFO "cx88/0: cx2388x v4l2 driver version %d.%d.%d loaded\n", (CX88_VERSION_CODE >> 16) & 0xff, (CX88_VERSION_CODE >> 8) & 0xff, CX88_VERSION_CODE & 0xff); diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c index cd0877636a32..77c37889232b 100644 --- a/drivers/media/video/cx88/cx88-vp3054-i2c.c +++ b/drivers/media/video/cx88/cx88-vp3054-i2c.c @@ -23,7 +23,6 @@ */ #include <linux/module.h> -#include <linux/moduleparam.h> #include <linux/init.h> #include <asm/io.h> @@ -111,7 +110,7 @@ int vp3054_i2c_probe(struct cx8802_dev *dev) struct vp3054_i2c_state *vp3054_i2c; int rc; - if (core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) + if (core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) return 0; dev->card_priv = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL); @@ -152,7 +151,7 @@ void vp3054_i2c_remove(struct cx8802_dev *dev) struct vp3054_i2c_state *vp3054_i2c = dev->card_priv; if (vp3054_i2c == NULL || - dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) + dev->core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO) return; i2c_del_adapter(&vp3054_i2c->adap); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 809126866a3e..42e0a9b8c550 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -28,11 +28,11 @@ #include <media/v4l2-common.h> #include <media/tuner.h> #include <media/tveeprom.h> -#include <media/video-buf.h> +#include <media/videobuf-dma-sg.h> #include <media/cx2341x.h> #include <media/audiochip.h> -#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) -#include <media/video-buf-dvb.h> +#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) +#include <media/videobuf-dvb.h> #endif #include "btcx-risc.h" @@ -226,8 +226,8 @@ enum cx88_itype { struct cx88_input { enum cx88_itype type; - unsigned int vmux; u32 gpio0, gpio1, gpio2, gpio3; + unsigned int vmux:2; unsigned int extadc:1; }; @@ -250,7 +250,7 @@ struct cx88_subid { u32 card; }; -#define INPUT(nr) (&cx88_boards[core->board].input[nr]) +#define INPUT(nr) (core->board.input[nr]) /* ----------------------------------------------------------- */ /* device / file handle status */ @@ -304,19 +304,14 @@ struct cx88_core { u32 i2c_state, i2c_rc; /* config info -- analog */ - unsigned int board; - unsigned int tuner_type; - unsigned int radio_type; - unsigned char tuner_addr; - unsigned char radio_addr; - unsigned int tda9887_conf; - unsigned int has_radio; + unsigned int boardnr; + struct cx88_board board; /* Supported V4L _STD_ tuner formats */ unsigned int tuner_formats; /* config info -- dvb */ -#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) +#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 @@ -463,7 +458,7 @@ struct cx8802_dev { int width; int height; -#if defined(CONFIG_VIDEO_BUF_DVB) || defined(CONFIG_VIDEO_BUF_DVB_MODULE) +#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) /* for dvb only */ struct videobuf_dvb dvb; @@ -524,7 +519,7 @@ cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, extern int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, struct scatterlist *sglist, unsigned int bpl, - unsigned int lines); + 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); @@ -585,15 +580,9 @@ extern void cx88_call_i2c_clients(struct cx88_core *core, /* ----------------------------------------------------------- */ /* cx88-cards.c */ -extern struct cx88_board cx88_boards[]; -extern const unsigned int cx88_bcount; - -extern struct cx88_subid cx88_subids[]; -extern const unsigned int cx88_idcount; - -extern void cx88_card_list(struct cx88_core *core, struct pci_dev *pci); -extern void cx88_card_setup(struct cx88_core *core); -extern void cx88_card_setup_pre_i2c(struct cx88_core *core); +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); /* ----------------------------------------------------------- */ /* cx88-tvaudio.c */ @@ -625,6 +614,8 @@ struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board 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); +void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir); +void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir); /* ----------------------------------------------------------- */ /* cx88-mpeg.c */ |