X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fpci%2Fens1370.c;h=900069b69af9db4eee6dad74cac919005ed16cfb;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=ef32537a111d83051597bae1191e594106713e74;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index ef32537a1..900069b69 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -83,20 +83,19 @@ static int joystick_port[SNDRV_CARDS]; static int joystick[SNDRV_CARDS]; #endif #endif -static int boot_devs; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Ensoniq AudioPCI soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for Ensoniq AudioPCI soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Ensoniq AudioPCI soundcard."); #ifdef SUPPORT_JOYSTICK #ifdef CHIP1371 -module_param_array(joystick_port, int, boot_devs, 0444); +module_param_array(joystick_port, int, NULL, 0444); MODULE_PARM_DESC(joystick_port, "Joystick port address."); #else -module_param_array(joystick, bool, boot_devs, 0444); +module_param_array(joystick, bool, NULL, 0444); MODULE_PARM_DESC(joystick, "Enable joystick."); #endif #endif /* SUPPORT_JOYSTICK */ @@ -372,6 +371,7 @@ typedef struct _snd_ensoniq ensoniq_t; struct _snd_ensoniq { spinlock_t reg_lock; + struct semaphore src_mutex; int irq; @@ -513,6 +513,7 @@ static unsigned int snd_es1371_wait_src_ready(ensoniq_t * ensoniq) r = inl(ES_REG(ensoniq, 1371_SMPRATE)); if ((r & ES_1371_SRC_RAM_BUSY) == 0) return r; + cond_resched(); } snd_printk("wait source ready timeout 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_SMPRATE), r); return 0; @@ -572,24 +573,18 @@ static void snd_es1370_codec_write(ak4531_t *ak4531, unsigned short reg, unsigned short val) { ensoniq_t *ensoniq = ak4531->private_data; - unsigned long flags; unsigned long end_time = jiffies + HZ / 10; #if 0 printk("CODEC WRITE: reg = 0x%x, val = 0x%x (0x%x), creg = 0x%x\n", reg, val, ES_1370_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1370_CODEC)); #endif do { - spin_lock_irqsave(&ensoniq->reg_lock, flags); if (!(inl(ES_REG(ensoniq, STATUS)) & ES_1370_CSTAT)) { outw(ES_1370_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1370_CODEC)); - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); return; } - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); -#if 0 set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); -#endif } while (time_after(end_time, jiffies)); snd_printk("codec write timeout, status = 0x%x\n", inl(ES_REG(ensoniq, STATUS))); } @@ -602,11 +597,10 @@ static void snd_es1371_codec_write(ac97_t *ac97, unsigned short reg, unsigned short val) { ensoniq_t *ensoniq = ac97->private_data; - unsigned long flags; unsigned int t, x; + down(&ensoniq->src_mutex); for (t = 0; t < POLL_COUNT; t++) { - spin_lock_irqsave(&ensoniq->reg_lock, flags); if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) { /* save the current state for latter */ x = snd_es1371_wait_src_ready(ensoniq); @@ -628,11 +622,11 @@ static void snd_es1371_codec_write(ac97_t *ac97, /* restore SRC reg */ snd_es1371_wait_src_ready(ensoniq); outl(x, ES_REG(ensoniq, 1371_SMPRATE)); - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); + up(&ensoniq->src_mutex); return; } - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); } + up(&ensoniq->src_mutex); snd_printk("codec write timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); } @@ -640,12 +634,11 @@ static unsigned short snd_es1371_codec_read(ac97_t *ac97, unsigned short reg) { ensoniq_t *ensoniq = ac97->private_data; - unsigned long flags; unsigned int t, x, fail = 0; __again: + down(&ensoniq->src_mutex); for (t = 0; t < POLL_COUNT; t++) { - spin_lock_irqsave(&ensoniq->reg_lock, flags); if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) { /* save the current state for latter */ x = snd_es1371_wait_src_ready(ensoniq); @@ -675,19 +668,19 @@ static unsigned short snd_es1371_codec_read(ac97_t *ac97, /* now wait for the stinkin' data (RDY) */ for (t = 0; t < POLL_COUNT; t++) { if ((x = inl(ES_REG(ensoniq, 1371_CODEC))) & ES_1371_CODEC_RDY) { - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); + up(&ensoniq->src_mutex); return ES_1371_CODEC_READ(x); } } - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); + up(&ensoniq->src_mutex); if (++fail > 10) { snd_printk("codec read timeout (final) at 0x%lx, reg = 0x%x [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), reg, inl(ES_REG(ensoniq, 1371_CODEC))); return 0; } goto __again; } - spin_unlock_irqrestore(&ensoniq->reg_lock, flags); } + up(&ensoniq->src_mutex); snd_printk("es1371: codec read timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC))); return 0; } @@ -696,6 +689,7 @@ static void snd_es1371_adc_rate(ensoniq_t * ensoniq, unsigned int rate) { unsigned int n, truncm, freq, result; + down(&ensoniq->src_mutex); n = rate / 3000; if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9))) n--; @@ -719,12 +713,14 @@ static void snd_es1371_adc_rate(ensoniq_t * ensoniq, unsigned int rate) snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC, n << 8); snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC + 1, n << 8); + up(&ensoniq->src_mutex); } static void snd_es1371_dac1_rate(ensoniq_t * ensoniq, unsigned int rate) { unsigned int freq, r; + down(&ensoniq->src_mutex); freq = ((rate << 15) + 1500) / 3000; r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P2 | ES_1371_DIS_R1)) | ES_1371_DIS_P1; outl(r, ES_REG(ensoniq, 1371_SMPRATE)); @@ -734,12 +730,14 @@ static void snd_es1371_dac1_rate(ensoniq_t * ensoniq, unsigned int rate) snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P2 | ES_1371_DIS_R1)); outl(r, ES_REG(ensoniq, 1371_SMPRATE)); + up(&ensoniq->src_mutex); } static void snd_es1371_dac2_rate(ensoniq_t * ensoniq, unsigned int rate) { unsigned int freq, r; + down(&ensoniq->src_mutex); freq = ((rate << 15) + 1500) / 3000; r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | ES_1371_DIS_R1)) | ES_1371_DIS_P2; outl(r, ES_REG(ensoniq, 1371_SMPRATE)); @@ -749,6 +747,7 @@ static void snd_es1371_dac2_rate(ensoniq_t * ensoniq, unsigned int rate) snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff); r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 | ES_1371_DIS_R1)); outl(r, ES_REG(ensoniq, 1371_SMPRATE)); + up(&ensoniq->src_mutex); } #endif /* CHIP1371 */ @@ -846,6 +845,13 @@ static int snd_ensoniq_playback1_prepare(snd_pcm_substream_t * substream) mode |= 0x01; spin_lock_irq(&ensoniq->reg_lock); ensoniq->ctrl &= ~ES_DAC1_EN; +#ifdef CHIP1371 + /* 48k doesn't need SRC (it breaks AC3-passthru) */ + if (runtime->rate == 48000) + ensoniq->ctrl |= ES_1373_BYPASS_P1; + else + ensoniq->ctrl &= ~ES_1373_BYPASS_P1; +#endif outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE)); outl(runtime->dma_addr, ES_REG(ensoniq, DAC1_FRAME)); @@ -863,11 +869,12 @@ static int snd_ensoniq_playback1_prepare(snd_pcm_substream_t * substream) case 44100: ensoniq->ctrl |= ES_1370_WTSRSEL(3); break; default: snd_BUG(); } -#else - snd_es1371_dac1_rate(ensoniq, runtime->rate); #endif outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); spin_unlock_irq(&ensoniq->reg_lock); +#ifndef CHIP1370 + snd_es1371_dac1_rate(ensoniq, runtime->rate); +#endif return 0; } @@ -901,11 +908,12 @@ static int snd_ensoniq_playback2_prepare(snd_pcm_substream_t * substream) ensoniq->ctrl |= ES_1370_PCLKDIVO(ES_1370_SRTODIV(runtime->rate)); ensoniq->u.es1370.pclkdiv_lock |= ES_MODE_PLAY2; } -#else - snd_es1371_dac2_rate(ensoniq, runtime->rate); #endif outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); spin_unlock_irq(&ensoniq->reg_lock); +#ifndef CHIP1370 + snd_es1371_dac2_rate(ensoniq, runtime->rate); +#endif return 0; } @@ -937,11 +945,12 @@ static int snd_ensoniq_capture_prepare(snd_pcm_substream_t * substream) ensoniq->ctrl |= ES_1370_PCLKDIVO(ES_1370_SRTODIV(runtime->rate)); ensoniq->u.es1370.pclkdiv_lock |= ES_MODE_CAPTURE; } -#else - snd_es1371_adc_rate(ensoniq, runtime->rate); #endif outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); spin_unlock_irq(&ensoniq->reg_lock); +#ifndef CHIP1370 + snd_es1371_adc_rate(ensoniq, runtime->rate); +#endif return 0; } @@ -1618,8 +1627,10 @@ static int snd_ensoniq_1371_mixer(ensoniq_t * ensoniq) if (err < 0) return err; } - if ((ensoniq->subsystem_vendor_id == 0x1274) && - (ensoniq->subsystem_device_id == 0x2000)) { /* GA-7DXR */ + if (((ensoniq->subsystem_vendor_id == 0x1274) && + (ensoniq->subsystem_device_id == 0x2000)) || /* GA-7DXR */ + ((ensoniq->subsystem_vendor_id == 0x1458) && + (ensoniq->subsystem_device_id == 0xa000))) { /* GA-8IEXP */ err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_line, ensoniq)); if (err < 0) return err; @@ -1822,6 +1833,7 @@ static int snd_ensoniq_free(ensoniq_t *ensoniq) if (ensoniq->irq >= 0) free_irq(ensoniq->irq, (void *)ensoniq); pci_release_regions(ensoniq->pci); + pci_disable_device(ensoniq->pci); kfree(ensoniq); return 0; } @@ -1876,14 +1888,18 @@ static int __devinit snd_ensoniq_create(snd_card_t * card, if ((err = pci_enable_device(pci)) < 0) return err; ensoniq = kcalloc(1, sizeof(*ensoniq), GFP_KERNEL); - if (ensoniq == NULL) + if (ensoniq == NULL) { + pci_disable_device(pci); return -ENOMEM; + } spin_lock_init(&ensoniq->reg_lock); + init_MUTEX(&ensoniq->src_mutex); ensoniq->card = card; ensoniq->pci = pci; ensoniq->irq = -1; if ((err = pci_request_regions(pci, "Ensoniq AudioPCI")) < 0) { kfree(ensoniq); + pci_disable_device(pci); return err; } ensoniq->port = pci_resource_start(pci, 0); @@ -1908,7 +1924,6 @@ static int __devinit snd_ensoniq_create(snd_card_t * card, ensoniq->subsystem_vendor_id = cmdw; pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &cmdw); ensoniq->subsystem_device_id = cmdw; - snd_ensoniq_proc_init(ensoniq); #ifdef CHIP1370 #if 0 ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE | ES_1370_PCLKDIVO(ES_1370_SRTODIV(8000)); @@ -2001,6 +2016,8 @@ static int __devinit snd_ensoniq_create(snd_card_t * card, return err; } + snd_ensoniq_proc_init(ensoniq); + snd_card_set_dev(card, &pci->dev); *rensoniq = ensoniq;