diff options
author | Ricardo Cerqueira <devnull@localhost> | 2006-01-03 13:39:32 +0000 |
---|---|---|
committer | Ricardo Cerqueira <devnull@localhost> | 2006-01-03 13:39:32 +0000 |
commit | 3381470ddd2164da2e33c1319a55f2deaac33baa (patch) | |
tree | 75472aaec8ae2a93f109474d98bdacbcd9b9adb3 /linux/drivers | |
parent | 7330a69cebde835c35bcede119a03dc8f1982e33 (diff) | |
download | mediapointer-dvb-s2-3381470ddd2164da2e33c1319a55f2deaac33baa.tar.gz mediapointer-dvb-s2-3381470ddd2164da2e33c1319a55f2deaac33baa.tar.bz2 |
cx88-alsa, now with working sound goodness
From: Ricardo Cerqueira <v4l@cerqueira.org>
It's still not perfect (lots of over and underruns), but there's now working
audio.
Dropped the videobuf queues (too geared for video...) in favor of a single
RISC databuffer, and changed the remaining code accordingly. And it works ;)
Signed-off-by:
Diffstat (limited to 'linux/drivers')
-rw-r--r-- | linux/drivers/media/video/cx88/cx88-alsa.c | 557 |
1 files changed, 155 insertions, 402 deletions
diff --git a/linux/drivers/media/video/cx88/cx88-alsa.c b/linux/drivers/media/video/cx88/cx88-alsa.c index 9040fcc92..5d23b7347 100644 --- a/linux/drivers/media/video/cx88/cx88-alsa.c +++ b/linux/drivers/media/video/cx88/cx88-alsa.c @@ -1,9 +1,10 @@ /* - * $Id: cx88-alsa.c,v 1.21 2005/12/30 15:57:25 rmcc Exp $ + * $Id: cx88-alsa.c,v 1.22 2006/01/03 13:39:32 rmcc Exp $ * * Support for audio capture * PCI function #1 of the cx2388x. * + * (c) 2006 Ricardo Cerqueira <v4l@cerqueira.org> * (c) 2005 Mauro Carvalho Chehab <mchehab@brturbo.com.br> * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org> * Based on bt87x.c by Clemens Ladisch <clemens@ladisch.de> @@ -91,13 +92,19 @@ struct cx88_audio_dev { unsigned int dma_size; unsigned int period_size; + unsigned int num_periods; + unsigned int current_period; + struct videobuf_dmabuf dma_risc; + struct snd_dma_buffer alsa_risc; int mixer_volume[MIXER_ADDR_LAST+1][2]; int capture_source[MIXER_ADDR_LAST+1][2]; long int bufsize; + long int read_count; long int read_offset; + struct cx88_buffer *buf; u32 __iomem *mmio; long opened; @@ -146,6 +153,7 @@ MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled."); ****************************************************************************/ MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards"); +MODULE_AUTHOR("Ricardo Cerqueira"); MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@brturbo.com.br>"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Conexant,23881}," @@ -163,24 +171,28 @@ MODULE_PARM_DESC(debug,"enable debug messages"); * BOARD Specific: Sets audio DMA */ -int _cx88_start_audio_dma(snd_cx88_card_t *chip, - struct cx88_dmaqueue *q, - struct cx88_buffer *buf) +int _cx88_start_audio_dma(snd_cx88_card_t *chip) { + struct cx88_buffer *buf = chip->buf; struct cx88_core *core=chip->core; + struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25]; + - dprintk(1, "Starting audio DMA\n"); + dprintk(1, "Starting audio DMA for %i bpl and %i (%i) lines at ptr2 %08x\n",buf->bpl, chip->num_periods, audio_ch->fifo_size / buf->bpl, audio_ch->fifo_start); + //dprintk(1, "Starting audio DMA at RISC %08lx for %i bpl\n",(unsigned long)buf->risc.dma,buf->bpl); /* setup fifo + format - out channel */ + //cx88_sram_channel_setup(chip->core, audio_ch, buf->bpl, 0); + + //snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), audio_ch->fifo_size, &chip->alsa_risc); cx88_sram_channel_setup(chip->core, &cx88_sram_channels[SRAM_CH25], buf->bpl, buf->risc.dma); /* sets bpl size */ cx_write(MO_AUDD_LNGTH, buf->bpl); - cx_write(MO_AUDR_LNGTH, buf->bpl); /* reset counter */ - cx_write(MO_AUDD_GPCNTRL,GP_COUNT_CONTROL_RESET); + //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 */ @@ -204,12 +216,16 @@ int _cx88_start_audio_dma(snd_cx88_card_t *chip, ); #endif + //dprintk(2, "Is queue reading? A: %x\n",chip->fh->vb_q.reading); + /* start dma */ cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */ cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */ + chip->current_period = 0; - q->count = 1; + if (debug) + cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]); return 0; } @@ -227,28 +243,15 @@ int _cx88_stop_audio_dma(snd_cx88_card_t *chip) /* disable irqs */ cx_clear(MO_PCI_INTMSK, 0x000002); cx_set(MO_AUD_INTMSK, 0); - return 0; -} - -#define MAX_IRQ_LOOP 10 - -/* - * BOARD Specific: Threats timeouts - */ -static void cx8801_timeout(unsigned long data) -{ - snd_cx88_card_t *chip = (snd_cx88_card_t *)data; - - dprintk(0, "cx88_alsa: %s\n",__FUNCTION__); if (debug) cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]); - _cx88_stop_audio_dma(chip); -#if 0 - do_cancel_buffers(dev,"timeout",1); -#endif + + return 0; } +#define MAX_IRQ_LOOP 10 + /* * BOARD Specific: IRQ dma bits */ @@ -276,30 +279,43 @@ static void cx8801_aud_irq(snd_cx88_card_t *chip) status = cx_read(MO_AUD_INTSTAT); mask = cx_read(MO_AUD_INTMSK); - if (0 == (status & mask)) + if (0 == (status & mask)) { + spin_unlock(&chip->reg_lock); return; + } cx_write(MO_AUD_INTSTAT, status); if (debug || (status & mask & ~0xff)) cx88_print_irqbits(core->name, "irq aud", cx88_aud_irqs, status, mask); /* risc op code error */ if (status & (1 << 16)) { - printk(KERN_WARNING "%s/0: video risc op code error\n",core->name); + printk(KERN_WARNING "%s/0: audio risc op code error\n",core->name); cx_clear(MO_AUD_DMACNTRL, 0x11); -#if 0 /* FIXME: anything else? */ - cx_clear(VID_CAPTURE_CONTROL, 0x06); -#endif cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]); } /* risc1 downstream */ if (status & 0x01) { + printk("AUDIO DATA!\n"); spin_lock(&chip->reg_lock); count = cx_read(MO_AUDD_GPCNT); - cx88_wakeup(core, &chip->q, count); +// cx88_wakeup(core, &chip->q, count); spin_unlock(&chip->reg_lock); + chip->read_count += chip->dma_size; + chip->current_period = (chip->current_period + 1) % chip->num_periods; + snd_pcm_period_elapsed(chip->substream); } + printk("Still kicking...\n"); + if (chip->read_count >= chip->period_size) { + printk("Elapsing?\n"); + spin_lock(&chip->reg_lock); + //snd_pcm_period_elapsed(chip->substream); + spin_unlock(&chip->reg_lock); + } + + printk("Leaving audio IRQ handler...\n"); + /* FIXME: Any other status should deserve a special handling? */ } @@ -317,22 +333,17 @@ static irqreturn_t cx8801_irq(int irq, void *dev_id, struct pt_regs *regs) status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x02); 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\n" ); + //dprintk( 3, " loop: %d/%d\n", loop, MAX_IRQ_LOOP ); + //dprintk( 3, " status: %d\n", status ); handled = 1; cx_write(MO_PCI_INTSTAT, status); - if (status & core->pci_irqmask) - { - dprintk( 3, " passing to core\n" ); - cx88_core_irq(core,status); - } if (status & 0x02) - { + { dprintk( 1, " ALSA IRQ handling\n" ); cx8801_aud_irq(chip); - } + } }; if (MAX_IRQ_LOOP == loop) { @@ -346,233 +357,12 @@ static irqreturn_t cx8801_irq(int irq, void *dev_id, struct pt_regs *regs) return IRQ_RETVAL(handled); } -/* - =====================> FIXME - */ - -#if 0 -static void snd_cx88_pci_error(bt87x_t *chip, unsigned int status) -{ - u16 pci_status; - - pci_read_config_word(chip->pci, PCI_STATUS, &pci_status); - pci_status &= PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY; - pci_write_config_word(chip->pci, PCI_STATUS, pci_status); - if (pci_status != PCI_STATUS_DETECTED_PARITY) - snd_printk(KERN_ERR "Aieee - PCI error! status %#08x, PCI status %#04x\n", - status & ERROR_INTERRUPTS, pci_status); - else { - snd_printk(KERN_ERR "Aieee - PCI parity error detected!\n"); - /* error 'handling' similar to aic7xxx_pci.c: */ - chip->pci_parity_errors++; - if (chip->pci_parity_errors > 20) { - snd_printk(KERN_ERR "Too many PCI parity errors observed.\n"); - snd_printk(KERN_ERR "Some device on this bus is generating bad parity.\n"); - snd_printk(KERN_ERR "This is an error *observed by*, not *generated by*, this card.\n"); - snd_printk(KERN_ERR "PCI parity error checking has been disabled.\n"); - chip->interrupt_mask &= ~(INT_PPERR | INT_RIPERR); - snd_bt87x_writel(chip, REG_INT_MASK, chip->interrupt_mask); - } - } -} -#endif - -/**************************************************************************** - Videobuf setup code - ****************************************************************************/ - -static int -buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) -{ - struct cx8801_fh *fh = q->priv_data; - struct cx88_audio_dev *chip = fh->dev; - - *size = fh->size; - if (0 == *count) - *count = 32; - - if (*count < 2) - *count = 2; - if (*count > 32) - *count = 32; - - dprintk(2,"Count=%d, size=%d\n" ,*count,*size); - return 0; -} - -static int -buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, - enum v4l2_field field) -{ - struct cx8801_fh *fh = q->priv_data; - struct cx88_audio_dev *chip = fh->dev; - struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); - int rc; - unsigned int size=fh->size; - - if (0 != buf->vb.baddr && buf->vb.bsize < size) - return -EINVAL; - - if (STATE_NEEDS_INIT == buf->vb.state) { - buf->vb.width = size; - buf->vb.height = 1; - buf->vb.size = size; - buf->vb.field = V4L2_FIELD_SEQ_TB; - - if (0 != (rc = videobuf_iolock(chip->pci,&buf->vb,NULL))) - goto fail; - cx88_risc_buffer(chip->pci, &buf->risc, - buf->vb.dma.sglist, - 0, buf->vb.width * buf->vb.height, - buf->vb.width, 0, - buf->vb.height); - } - buf->vb.state = STATE_PREPARED; - - dprintk_core(2,"[%p/%d] buffer_prepare - size: %d - dma=0x%08lx\n", - buf, buf->vb.i, - fh->size, - (unsigned long)buf->risc.dma); - - chip->dma_risc = buf->vb.dma; - return 0; - - fail: - cx88_free_buffer(chip->pci,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 cx8801_fh *fh = vq->priv_data; - struct cx88_audio_dev *chip = fh->dev; - struct cx88_dmaqueue *q = &chip->q; - - - dprintk(2,"Buffer 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(q->stopper.dma); - if (!buf->bpl && chip->period_size) - buf->bpl = chip->period_size; - - - if (!list_empty(&q->queued)) { - list_add_tail(&buf->vb.queue,&q->queued); - buf->vb.state = STATE_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); - _cx88_start_audio_dma(chip, q, buf); - printk("DEBUG TEMP: buf bpl is %d\n",buf->bpl); - buf->vb.state = STATE_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 = STATE_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 = STATE_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); - struct cx8801_fh *fh = q->priv_data; - - cx88_free_buffer(fh->dev->pci,buf); -} - -static struct videobuf_queue_ops audio_qops = { - .buf_setup = buffer_setup, - .buf_prepare = buffer_prepare, - .buf_queue = buffer_queue, - .buf_release = buffer_release, -}; - -static int dsp_buffer_init(snd_cx88_card_t *chip) -{ - int err = 0; - struct cx8801_fh *fh; - struct v4l2_requestbuffers req; - int deb; - - BUG_ON(!chip->dma_size); - - /* allocate + initialize per filehandle data */ - fh = kmalloc(sizeof(*fh),GFP_KERNEL); - if (NULL == fh) - return -ENOMEM; - memset(fh,0,sizeof(*fh)); - fh->dev = chip; - fh->size = chip->dma_size; - - dprintk(1,"queue init\n"); - videobuf_queue_init(&fh->vb_q, &audio_qops, - chip->pci, &chip->reg_lock, - V4L2_BUF_TYPE_PRIVATE, - V4L2_FIELD_NONE, - sizeof(struct cx88_buffer), - fh); - - chip->fh=fh; - dprintk(1,"queue read start (coming from %d)\n",err); - deb = videobuf_read_start(&fh->vb_q); - dprintk(1,"dma init (coming from %d)\n",deb); - videobuf_dma_init(&chip->dma_risc); - dprintk(1,"dma init kernel\n"); - err = videobuf_dma_init_kernel(&chip->dma_risc, PCI_DMA_FROMDEVICE, - (chip->dma_size + PAGE_SIZE) >> PAGE_SHIFT); - if (0 != err) - return err; - - memset(&req,0,sizeof(req)); - req.type = fh->vb_q.type; - req.count = 2; - req.memory = V4L2_MEMORY_MMAP; - - //dprintk(1,"request bufers\n"); -// videobuf_reqbufs(&fh->vb_q, &req); - -// dprintk(1,"prepare bufers\n"); -// videobuf_qbuf(&fh->vb_q, &req); - -// dprintk(1,"start stream\n"); -// err=videobuf_streamon(&fh->vb_q); - - return 0; -} static int dsp_buffer_free(snd_cx88_card_t *chip) { BUG_ON(!chip->dma_size); - videobuf_dma_free(&chip->dma_risc); +// videobuf_dma_free(&chip->dma_risc); chip->dma_size = 0; @@ -593,16 +383,16 @@ static snd_pcm_hardware_t snd_cx88_digital_hw = { 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, + .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000, + .rate_min = 32000, + .rate_max = 96000, + .channels_min = 1, .channels_max = 2, - .buffer_bytes_max = (1024*256), - .period_bytes_min = 64, - .period_bytes_max = 256, - .periods_min = 2, - .periods_max = 1024, + .buffer_bytes_max = (4*128), + .period_bytes_min = 128, + .period_bytes_max = 128, + .periods_min = 4, + .periods_max = 4, }; /* @@ -634,6 +424,9 @@ static int snd_cx88_pcm_open(snd_pcm_substream_t *substream) chip->substream = substream; + chip->read_count = 0; + chip->read_offset = 0; + pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); if (pcm == NULL) { err=-ENOMEM; @@ -663,9 +456,11 @@ static int snd_cx88_close(snd_pcm_substream_t *substream) { snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); - chip->substream = NULL; + + dprintk(2,"PCM close\n"); clear_bit(0, &chip->opened); smp_mb__after_clear_bit(); + dprintk(2,"Returning from PCM close\n"); return 0; } @@ -675,36 +470,72 @@ static int snd_cx88_close(snd_pcm_substream_t *substream) static int snd_cx88_hw_params(snd_pcm_substream_t * substream, snd_pcm_hw_params_t * hw_params) { - int err; snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); + struct cx88_buffer *buf; printk("ALSA HW_params\n"); + if (substream->runtime->dma_area) { - videobuf_queue_cancel(&chip->fh->vb_q); - videobuf_dma_pci_unmap(chip->pci, &chip->dma_risc); - dsp_buffer_free(chip); + //videobuf_read_stop(&chip->fh->vb_q); + //videobuf_dma_pci_unmap(chip->pci, &chip->dma_risc); + //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); + dprintk(1,"Setting buffer\n"); - dsp_buffer_init(chip); + //dsp_buffer_init(chip); - if (0 != (err = videobuf_dma_pci_map(chip->pci, &chip->dma_risc))) { - dsp_buffer_free(chip); - return err; - } + buf = kmalloc(sizeof(*buf),GFP_KERNEL); + if (NULL == buf) + return -ENOMEM; + memset(buf,0,sizeof(*buf)); + + + buf->vb.memory = V4L2_MEMORY_MMAP; + buf->vb.width = 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, + (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); + + videobuf_dma_pci_map(chip->pci,&buf->vb.dma); - dprintk(1,"Buffer ready at 0x%x\n",(int )chip->dma_risc.vmalloc); + cx88_risc_databuffer(chip->pci, &buf->risc, + buf->vb.dma.sglist, + buf->vb.width, buf->vb.height); +#if 0 + cx88_risc_buffer(chip->pci, &buf->risc, + buf->vb.dma.sglist, + 0, buf->vb.width * buf->vb.height, + buf->vb.width, 0, + buf->vb.height); +#endif + + 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; + + dprintk(1,"Buffer ready at %u\n",chip->dma_risc.nr_pages); substream->runtime->dma_area = chip->dma_risc.vmalloc; - //return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); return 0; } @@ -716,13 +547,18 @@ static int snd_cx88_hw_free(snd_pcm_substream_t * substream) snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); - if (substream->runtime->dma_area) { - videobuf_queue_cancel(&chip->fh->vb_q); + dprintk(2,"HW free\n"); + if (substream->runtime->dma_area) { + dprintk(2,"Freeing buffer\n"); videobuf_dma_pci_unmap(chip->pci, &chip->dma_risc); + videobuf_dma_free(&chip->dma_risc); + btcx_riscmem_free(chip->pci,&chip->buf->risc); + kfree(chip->buf); dsp_buffer_free(chip); substream->runtime->dma_area = NULL; } - //return snd_pcm_lib_free_pages(substream); + dprintk(2,"Returning from HW free\n"); + return 0; } /* @@ -730,8 +566,7 @@ static int snd_cx88_hw_free(snd_pcm_substream_t * substream) */ static int snd_cx88_prepare(snd_pcm_substream_t *substream) { - snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); - struct cx88_core *core=chip->core; + //snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); printk("ALSA Prepare\n"); //spin_lock_irq(&chip->reg_lock); @@ -749,7 +584,7 @@ static int snd_cx88_prepare(snd_pcm_substream_t *substream) static int snd_cx88_card_trigger(snd_pcm_substream_t *substream, int cmd) { snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); - struct cx8801_fh *fh = chip->fh; + //struct cx8801_fh *fh = chip->fh; int err; dprintk(2,"PCM Trigger cmd=%d\n",cmd); @@ -757,12 +592,14 @@ static int snd_cx88_card_trigger(snd_pcm_substream_t *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_START: + dprintk(1,"start stream\n"); //err=videobuf_streamon(&fh->vb_q); - //err=_cx88_start_audio_dma(chip); + err=_cx88_start_audio_dma(chip); break; case SNDRV_PCM_TRIGGER_STOP: - // err=videobuf_streamoff(&fh->vb_q); - //err=_cx88_stop_audio_dma(chip); + dprintk(1,"stop stream\n"); + //err=videobuf_streamoff(&fh->vb_q); + err=_cx88_stop_audio_dma(chip); break; default: err=-EINVAL; @@ -771,7 +608,7 @@ static int snd_cx88_card_trigger(snd_pcm_substream_t *substream, int cmd) spin_unlock(&chip->reg_lock); - return 0; + dprintk(2,"Leaving PCM Trigger\n"); return err; } @@ -782,8 +619,19 @@ static snd_pcm_uframes_t snd_cx88_pointer(snd_pcm_substream_t *substream) { snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; + //struct cx88_core *core = chip->core; + + 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; + } + printk("Pointer time, will return %li, read %li\n",chip->read_offset,chip->read_count); + return bytes_to_frames(runtime, chip->read_offset); -// return (snd_pcm_uframes_t)bytes_to_frames(runtime, chip->current_line * chip->line_bytes); +// printk("Pointer time, will return %li\n",chip->current_period * chip->period_size); +// return (snd_pcm_uframes_t)bytes_to_frames(runtime, chip->current_period * chip->period_size); } /* @@ -798,7 +646,7 @@ static snd_pcm_ops_t snd_cx88_pcm_ops = { .prepare = snd_cx88_prepare, .trigger = snd_cx88_card_trigger, .pointer = snd_cx88_pointer, - .page = snd_pcm_sgbuf_ops_page, + //.page = snd_pcm_sgbuf_ops_page, }; /* @@ -815,11 +663,8 @@ static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, char *name) pcm->private_data = chip; strcpy(pcm->name, name); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx88_pcm_ops); - return snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_DEV_SG, - snd_dma_pci_data(chip->pci), - 128 * 1024, - (255 * 4092 + 1023) & ~1023); + + return 0; } /**************************************************************************** @@ -871,58 +716,6 @@ static snd_kcontrol_new_t snd_cx88_capture_volume = { .put = snd_cx88_capture_volume_put, }; -/* - *************************************** - */ -#if 0 -static int snd_cx88_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *info) -{ - static char *texts[3] = {"TV Tuner", "FM", "Mic/Line"}; - - info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - info->count = 1; - info->value.enumerated.items = 3; - if (info->value.enumerated.item > 2) - info->value.enumerated.item = 2; - strcpy(info->value.enumerated.name, texts[info->value.enumerated.item]); - return 0; -} - -static int snd_cx88_capture_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value) -{ - snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); -/*#if 0*/ - value->value.enumerated.item[0] = (chip->reg_control & CTL_A_SEL_MASK) >> CTL_A_SEL_SHIFT; -/*#endif*/ - return 0; -} - -static int snd_cx88_capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value) -{ - snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); - u32 old_control; - int changed; -/*#if 0*/ - spin_lock_irq(&chip->reg_lock); - old_control = chip->reg_control; - chip->reg_control = (chip->reg_control & ~CTL_A_SEL_MASK) - | (value->value.enumerated.item[0] << CTL_A_SEL_SHIFT); - snd_cx88_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control); - changed = chip->reg_control != old_control; - spin_unlock_irq(&chip->reg_lock); -/*#endif*/ - return changed; -} - -static snd_kcontrol_new_t snd_cx88_capture_source = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = snd_cx88_capture_source_info, - .get = snd_cx88_capture_source_get, - .put = snd_cx88_capture_source_put, -}; - -#endif /**************************************************************************** Basic Flow for Sound Devices @@ -947,28 +740,15 @@ MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl); static int snd_cx88_free(snd_cx88_card_t *chip) { dprintk(1,"cx88 free\n"); -#if 0 - if (chip->mmio) { - snd_bt87x_stop(chip); - if (chip->irq >= 0) - synchronize_irq(chip->irq); - - iounmap(chip->mmio); - } -#endif if (chip->irq >= 0){ synchronize_irq(chip->irq); free_irq(chip->irq, chip); } - /* free memory */ - - //pci_release_regions(chip->pci); - -// btcx_riscmem_free(chip->pci,&chip->q.stopper); + //btcx_riscmem_free(chip->pci,&chip->q.stopper); cx88_core_put(chip->core,chip->pci); - //kfree(chip); + pci_disable_device(chip->pci); return 0; } @@ -976,12 +756,12 @@ static int snd_cx88_free(snd_cx88_card_t *chip) /* * Component Destructor */ -static int snd_cx88_dev_free(snd_card_t * card) +static void snd_cx88_dev_free(snd_card_t * card) { snd_cx88_card_t *chip = card->private_data; dprintk(1,"cx88 dev free\n"); - return snd_cx88_free(chip); + snd_cx88_free(chip); } @@ -1019,27 +799,8 @@ static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci, chip->irq = -1; spin_lock_init(&chip->reg_lock); -#if 0 - if (!request_mem_region(pci_resource_start(pci,0), - pci_resource_len(pci,0), - "CX88 audio")) { - err = -EBUSY; - printk(KERN_ERR "%s: can't get MMIO memory @ 0x%lx\n", - "CX88 audio",pci_resource_start(pci,0)); - kfree(chip); - pci_disable_device(pci); - return err; - } - chip->mmio = ioremap_nocache(pci_resource_start(pci, 0), - pci_resource_len(pci, 0)); - if (!chip->mmio) { - kfree(chip); - snd_printk(KERN_ERR "cannot remap io memory\n"); - return -ENOMEM; - } -#endif - core = cx88_core_get(chip->pci); + cx88_reset(core); if (NULL == core) { err = -EINVAL; kfree (chip); @@ -1054,15 +815,6 @@ static int __devinit snd_cx88_create(snd_card_t *card, struct pci_dev *pci, #if 1 /* From cx88-mpeg.c */ - /* init dma queue */ - INIT_LIST_HEAD(&chip->q.active); - INIT_LIST_HEAD(&chip->q.queued); - chip->q.timeout.function = cx8801_timeout; - chip->q.timeout.data = (unsigned long)chip; - init_timer(&chip->q.timeout); - cx88_risc_stopper(chip->pci,&chip->q.stopper, - MO_AUD_DMACNTRL, 0x11,0x00); - /* get irq */ err = request_irq(chip->pci->irq, cx8801_irq, SA_SHIRQ | SA_INTERRUPT, chip->core->name, chip); @@ -1158,7 +910,7 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, static void __devexit cx88_audio_finidev(struct pci_dev *pci) { struct cx88_audio_dev *card = pci_get_drvdata(pci); - struct cx88_core *core = card->core; + //struct cx88_core *core = card->core; //_cx88_stop_audio_dma(card); @@ -1223,9 +975,10 @@ static int cx88_audio_init(void) */ static void cx88_audio_fini(void) { - int idx; -/* printk(KERN_INFO "cx88 fini\n"); +/* + int idx; + printk(KERN_INFO "cx88 fini\n"); for (idx = 0; idx < SNDRV_CARDS; idx++) { snd_card_free(snd_cx88_cards[idx]); snd_cx88_cards[idx] = NULL; |