]> err.no Git - linux-2.6/blobdiff - sound/pci/ca0106/ca0106_main.c
[ALSA] sound/pci/ca0106: Use the DMA_32BIT_MASK constant
[linux-2.6] / sound / pci / ca0106 / ca0106_main.c
index 58d9026c8ca686b5dc222540862c5d36478d9dab..85caf1bbcc11e544dd3b13d0cd95f631751f9815 100644 (file)
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/pcm.h>
@@ -216,10 +217,10 @@ static snd_pcm_hardware_t snd_ca0106_capture_hw = {
                                 SNDRV_PCM_INFO_INTERLEAVED |
                                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
                                 SNDRV_PCM_INFO_MMAP_VALID),
-       .formats =              SNDRV_PCM_FMTBIT_S16_LE,
-       .rates =                SNDRV_PCM_RATE_48000,
-       .rate_min =             48000,
-       .rate_max =             48000,
+       .formats =              SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
+       .rates =                SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
+       .rate_min =             44100,
+       .rate_max =             192000,
        .channels_min =         2,
        .channels_max =         2,
        .buffer_bytes_max =     ((65536 - 64) * 8),
@@ -277,7 +278,10 @@ int snd_ca0106_i2c_write(ca0106_t *emu,
        }
 
        tmp = reg << 25 | value << 16;
-       snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp);
+       /* Not sure what this I2C channel controls. */
+       /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
+
+       /* This controls the I2C connected to the WM8775 ADC Codec */
        snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp);
 
        for(retry=0;retry<10;retry++)
@@ -607,6 +611,61 @@ static int snd_ca0106_pcm_prepare_capture(snd_pcm_substream_t *substream)
        snd_pcm_runtime_t *runtime = substream->runtime;
        ca0106_pcm_t *epcm = runtime->private_data;
        int channel = epcm->channel_id;
+       u32 hcfg_mask = HCFG_CAPTURE_S32_LE;
+       u32 hcfg_set = 0x00000000;
+       u32 hcfg;
+       u32 over_sampling=0x2;
+       u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */
+       u32 reg71_set = 0;
+       u32 reg71;
+       
+        //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));
+        //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
+       //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
+       /* reg71 controls ADC rate. */
+       switch (runtime->rate) {
+       case 44100:
+               reg71_set = 0x00004000;
+               break;
+        case 48000:
+               reg71_set = 0; 
+               break;
+       case 96000:
+               reg71_set = 0x00008000;
+               over_sampling=0xa;
+               break;
+       case 192000:
+               reg71_set = 0x0000c000; 
+               over_sampling=0xa;
+               break;
+       default:
+               reg71_set = 0; 
+               break;
+       }
+       /* Format is a global setting */
+       /* FIXME: Only let the first channel accessed set this. */
+       switch (runtime->format) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               hcfg_set = 0;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               hcfg_set = HCFG_CAPTURE_S32_LE;
+               break;
+       default:
+               hcfg_set = 0;
+               break;
+       }
+       hcfg = inl(emu->port + HCFG) ;
+       hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
+       outl(hcfg, emu->port + HCFG);
+       reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
+       reg71 = (reg71 & ~reg71_mask) | reg71_set;
+       snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
+        if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
+               snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */
+       }
+
+
         //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));
        snd_ca0106_ptr_write(emu, 0x13, channel, 0);
        snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
@@ -1074,8 +1133,8 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
   
        if ((err = pci_enable_device(pci)) < 0)
                return err;
-       if (pci_set_dma_mask(pci, 0xffffffffUL) < 0 ||
-           pci_set_consistent_dma_mask(pci, 0xffffffffUL) < 0) {
+       if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
+           pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
                printk(KERN_ERR "error to set 32bit mask DMA\n");
                pci_disable_device(pci);
                return -ENXIO;