diff options
author | James Courtier-Dutton <James@superbug.co.uk> | 2005-05-28 07:28:21 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2005-06-22 06:27:12 -0400 |
commit | 883130b476e7f8baa608dabe52c455ac351f7c39 (patch) | |
tree | bd252f2384b7ed8565512c77fa6f0734581b12f0 | |
parent | ed144f3cdcf8f9b9280e04ca1a831c85a8fbb488 (diff) |
[ALSA] Implement S32_LE(24bit) and 96000 capture rates etc.
CA0106 driver
Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
-rw-r--r-- | sound/pci/ca0106/ca0106_main.c | 63 |
1 files changed, 59 insertions, 4 deletions
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 58d9026c8ca6..1c26206b4fb9 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -216,10 +216,10 @@ static snd_pcm_hardware_t snd_ca0106_capture_hw = { | |||
216 | SNDRV_PCM_INFO_INTERLEAVED | | 216 | SNDRV_PCM_INFO_INTERLEAVED | |
217 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 217 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
218 | SNDRV_PCM_INFO_MMAP_VALID), | 218 | SNDRV_PCM_INFO_MMAP_VALID), |
219 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 219 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, |
220 | .rates = SNDRV_PCM_RATE_48000, | 220 | .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000, |
221 | .rate_min = 48000, | 221 | .rate_min = 44100, |
222 | .rate_max = 48000, | 222 | .rate_max = 192000, |
223 | .channels_min = 2, | 223 | .channels_min = 2, |
224 | .channels_max = 2, | 224 | .channels_max = 2, |
225 | .buffer_bytes_max = ((65536 - 64) * 8), | 225 | .buffer_bytes_max = ((65536 - 64) * 8), |
@@ -607,6 +607,61 @@ static int snd_ca0106_pcm_prepare_capture(snd_pcm_substream_t *substream) | |||
607 | snd_pcm_runtime_t *runtime = substream->runtime; | 607 | snd_pcm_runtime_t *runtime = substream->runtime; |
608 | ca0106_pcm_t *epcm = runtime->private_data; | 608 | ca0106_pcm_t *epcm = runtime->private_data; |
609 | int channel = epcm->channel_id; | 609 | int channel = epcm->channel_id; |
610 | u32 hcfg_mask = HCFG_CAPTURE_S32_LE; | ||
611 | u32 hcfg_set = 0x00000000; | ||
612 | u32 hcfg; | ||
613 | u32 over_sampling=0x2; | ||
614 | u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */ | ||
615 | u32 reg71_set = 0; | ||
616 | u32 reg71; | ||
617 | |||
618 | //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1)); | ||
619 | //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base); | ||
620 | //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes); | ||
621 | /* reg71 controls ADC rate. */ | ||
622 | switch (runtime->rate) { | ||
623 | case 44100: | ||
624 | reg71_set = 0x00004000; | ||
625 | break; | ||
626 | case 48000: | ||
627 | reg71_set = 0; | ||
628 | break; | ||
629 | case 96000: | ||
630 | reg71_set = 0x00008000; | ||
631 | over_sampling=0xa; | ||
632 | break; | ||
633 | case 192000: | ||
634 | reg71_set = 0x0000c000; | ||
635 | over_sampling=0xa; | ||
636 | break; | ||
637 | default: | ||
638 | reg71_set = 0; | ||
639 | break; | ||
640 | } | ||
641 | /* Format is a global setting */ | ||
642 | /* FIXME: Only let the first channel accessed set this. */ | ||
643 | switch (runtime->format) { | ||
644 | case SNDRV_PCM_FORMAT_S16_LE: | ||
645 | hcfg_set = 0; | ||
646 | break; | ||
647 | case SNDRV_PCM_FORMAT_S32_LE: | ||
648 | hcfg_set = HCFG_CAPTURE_S32_LE; | ||
649 | break; | ||
650 | default: | ||
651 | hcfg_set = 0; | ||
652 | break; | ||
653 | } | ||
654 | hcfg = inl(emu->port + HCFG) ; | ||
655 | hcfg = (hcfg & ~hcfg_mask) | hcfg_set; | ||
656 | outl(hcfg, emu->port + HCFG); | ||
657 | reg71 = snd_ca0106_ptr_read(emu, 0x71, 0); | ||
658 | reg71 = (reg71 & ~reg71_mask) | reg71_set; | ||
659 | snd_ca0106_ptr_write(emu, 0x71, 0, reg71); | ||
660 | if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ | ||
661 | snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */ | ||
662 | } | ||
663 | |||
664 | |||
610 | //printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1)); | 665 | //printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1)); |
611 | snd_ca0106_ptr_write(emu, 0x13, channel, 0); | 666 | snd_ca0106_ptr_write(emu, 0x13, channel, 0); |
612 | snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); | 667 | snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); |