Loading sound/isa/Kconfig +5 −2 Original line number Diff line number Diff line Loading @@ -368,14 +368,17 @@ config SND_SGALAXY will be called snd-sgalaxy. config SND_SSCAPE tristate "Ensoniq SoundScape PnP driver" tristate "Ensoniq SoundScape driver" select SND_HWDEP select SND_MPU401_UART select SND_WSS_LIB help Say Y here to include support for Ensoniq SoundScape PnP Say Y here to include support for Ensoniq SoundScape soundcards. The PCM audio is supported on SoundScape Classic, Elite, PnP and VIVO cards. The MIDI support is very experimental. To compile this driver as a module, choose M here: the module will be called snd-sscape. Loading sound/isa/sscape.c +38 −151 Original line number Diff line number Diff line Loading @@ -89,9 +89,6 @@ MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids); #endif #define MPU401_IO(i) ((i) + 0) #define MIDI_DATA_IO(i) ((i) + 0) #define MIDI_CTRL_IO(i) ((i) + 1) #define HOST_CTRL_IO(i) ((i) + 2) #define HOST_DATA_IO(i) ((i) + 3) #define ODIE_ADDR_IO(i) ((i) + 4) Loading Loading @@ -129,9 +126,6 @@ enum GA_REG { #define DMA_8BIT 0x80 #define AD1845_FREQ_SEL_MSB 0x16 #define AD1845_FREQ_SEL_LSB 0x17 enum card_type { SSCAPE, SSCAPE_PNP, Loading @@ -141,8 +135,6 @@ enum card_type { struct soundscape { spinlock_t lock; unsigned io_base; unsigned wss_base; int codec_type; int ic_type; enum card_type type; struct resource *io_res; Loading Loading @@ -330,7 +322,7 @@ static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data, */ static inline int verify_mpu401(const struct snd_mpu401 * mpu) { return ((inb(MIDI_CTRL_IO(mpu->port)) & 0xc0) == 0x80); return ((inb(MPU401C(mpu)) & 0xc0) == 0x80); } /* Loading @@ -338,7 +330,7 @@ static inline int verify_mpu401(const struct snd_mpu401 * mpu) */ static inline void initialise_mpu401(const struct snd_mpu401 * mpu) { outb(0, MIDI_DATA_IO(mpu->port)); outb(0, MPU401D(mpu)); } /* Loading Loading @@ -396,20 +388,20 @@ static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg, unsigned ti */ static int obp_startup_ack(struct soundscape *s, unsigned timeout) { while (timeout != 0) { unsigned long end_time = jiffies + msecs_to_jiffies(timeout); do { unsigned long flags; unsigned char x; schedule_timeout_uninterruptible(1); spin_lock_irqsave(&s->lock, flags); x = inb(HOST_DATA_IO(s->io_base)); spin_unlock_irqrestore(&s->lock, flags); if ((x & 0xfe) == 0xfe) return 1; --timeout; } /* while */ msleep(10); } while (time_before(jiffies, end_time)); return 0; } Loading @@ -423,20 +415,20 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout) */ static int host_startup_ack(struct soundscape *s, unsigned timeout) { while (timeout != 0) { unsigned long end_time = jiffies + msecs_to_jiffies(timeout); do { unsigned long flags; unsigned char x; schedule_timeout_uninterruptible(1); spin_lock_irqsave(&s->lock, flags); x = inb(HOST_DATA_IO(s->io_base)); spin_unlock_irqrestore(&s->lock, flags); if (x == 0xfe) return 1; --timeout; } /* while */ msleep(10); } while (time_before(jiffies, end_time)); return 0; } Loading Loading @@ -532,10 +524,10 @@ static int upload_dma_data(struct soundscape *s, * give it 5 seconds (max) ... */ ret = 0; if (!obp_startup_ack(s, 5)) { if (!obp_startup_ack(s, 5000)) { snd_printk(KERN_ERR "sscape: No response from on-board processor after upload\n"); ret = -EAGAIN; } else if (!host_startup_ack(s, 5)) { } else if (!host_startup_ack(s, 5000)) { snd_printk(KERN_ERR "sscape: SoundScape failed to initialise\n"); ret = -EAGAIN; } Loading Loading @@ -732,13 +724,7 @@ static int sscape_midi_get(struct snd_kcontrol *kctl, unsigned long flags; spin_lock_irqsave(&s->lock, flags); set_host_mode_unsafe(s->io_base); if (host_write_ctrl_unsafe(s->io_base, CMD_GET_MIDI_VOL, 100)) { uctl->value.integer.value[0] = host_read_ctrl_unsafe(s->io_base, 100); } set_midi_mode_unsafe(s->io_base); uctl->value.integer.value[0] = s->midi_vol; spin_unlock_irqrestore(&s->lock, flags); return 0; } Loading Loading @@ -773,6 +759,7 @@ static int sscape_midi_put(struct snd_kcontrol *kctl, change = (host_write_ctrl_unsafe(s->io_base, CMD_SET_MIDI_VOL, 100) && host_write_ctrl_unsafe(s->io_base, ((unsigned char) uctl->value.integer. value[0]) & 127, 100) && host_write_ctrl_unsafe(s->io_base, CMD_XXX_MIDI_VOL, 100)); s->midi_vol = (unsigned char) uctl->value.integer.value[0] & 127; __skip_change: /* Loading Loading @@ -815,12 +802,11 @@ static unsigned __devinit get_irq_config(int irq) * Perform certain arcane port-checks to see whether there * is a SoundScape board lurking behind the given ports. */ static int __devinit detect_sscape(struct soundscape *s) static int __devinit detect_sscape(struct soundscape *s, long wss_io) { unsigned long flags; unsigned d; int retval = 0; int codec = s->wss_base; spin_lock_irqsave(&s->lock, flags); Loading @@ -836,13 +822,11 @@ static int __devinit detect_sscape(struct soundscape *s) if ((d & 0x80) != 0) goto _done; if (d == 0) { s->codec_type = 1; if (d == 0) s->ic_type = IC_ODIE; } else if ((d & 0x60) != 0) { s->codec_type = 2; else if ((d & 0x60) != 0) s->ic_type = IC_OPUS; } else else goto _done; outb(0xfa, ODIE_ADDR_IO(s->io_base)); Loading @@ -862,10 +846,10 @@ static int __devinit detect_sscape(struct soundscape *s) sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0); if (s->type == SSCAPE_VIVO) codec += 4; wss_io += 4; /* wait for WSS codec */ for (d = 0; d < 500; d++) { if ((inb(codec) & 0x80) == 0) if ((inb(wss_io) & 0x80) == 0) break; spin_unlock_irqrestore(&s->lock, flags); msleep(1); Loading Loading @@ -954,82 +938,6 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned l } /* * Override for the CS4231 playback format function. * The AD1845 has much simpler format and rate selection. */ static void ad1845_playback_format(struct snd_wss *chip, struct snd_pcm_hw_params *params, unsigned char format) { unsigned long flags; unsigned rate = params_rate(params); /* * The AD1845 can't handle sample frequencies * outside of 4 kHZ to 50 kHZ */ if (rate > 50000) rate = 50000; else if (rate < 4000) rate = 4000; spin_lock_irqsave(&chip->reg_lock, flags); /* * Program the AD1845 correctly for the playback stream. * Note that we do NOT need to toggle the MCE bit because * the PLAYBACK_ENABLE bit of the Interface Configuration * register is set. * * NOTE: We seem to need to write to the MSB before the LSB * to get the correct sample frequency. */ snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (format & 0xf0)); snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8)); snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate); spin_unlock_irqrestore(&chip->reg_lock, flags); } /* * Override for the CS4231 capture format function. * The AD1845 has much simpler format and rate selection. */ static void ad1845_capture_format(struct snd_wss *chip, struct snd_pcm_hw_params *params, unsigned char format) { unsigned long flags; unsigned rate = params_rate(params); /* * The AD1845 can't handle sample frequencies * outside of 4 kHZ to 50 kHZ */ if (rate > 50000) rate = 50000; else if (rate < 4000) rate = 4000; spin_lock_irqsave(&chip->reg_lock, flags); /* * Program the AD1845 correctly for the playback stream. * Note that we do NOT need to toggle the MCE bit because * the CAPTURE_ENABLE bit of the Interface Configuration * register is set. * * NOTE: We seem to need to write to the MSB before the LSB * to get the correct sample frequency. */ snd_wss_out(chip, CS4231_REC_FORMAT, (format & 0xf0)); snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8)); snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate); spin_unlock_irqrestore(&chip->reg_lock, flags); } /* * Create an AD1845 PCM subdevice on the SoundScape. The AD1845 * is very much like a CS4231, with a few extra bits. We will Loading @@ -1055,11 +963,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, unsigned long flags; struct snd_pcm *pcm; #define AD1845_FREQ_SEL_ENABLE 0x08 #define AD1845_PWR_DOWN_CTRL 0x1b #define AD1845_CRYS_CLOCK_SEL 0x1d /* * It turns out that the PLAYBACK_ENABLE bit is set * by the lowlevel driver ... Loading @@ -1074,7 +977,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, */ if (sscape->type != SSCAPE_VIVO) { int val; /* * The input clock frequency on the SoundScape must * be 14.31818 MHz, because we must set this register Loading @@ -1082,22 +984,10 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, */ snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); snd_wss_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20); snd_wss_out(chip, AD1845_CLOCK, 0x20); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_mce_down(chip); /* * More custom configuration: * a) select "mode 2" and provide a current drive of 8mA * b) enable frequency selection (for capture/playback) */ spin_lock_irqsave(&chip->reg_lock, flags); snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2 | 0x10); val = snd_wss_in(chip, AD1845_PWR_DOWN_CTRL); snd_wss_out(chip, AD1845_PWR_DOWN_CTRL, val | AD1845_FREQ_SEL_ENABLE); spin_unlock_irqrestore(&chip->reg_lock, flags); } err = snd_wss_pcm(chip, 0, &pcm); Loading @@ -1113,12 +1003,14 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, "for AD1845 chip\n"); goto _error; } if (chip->hardware != WSS_HW_AD1848) { err = snd_wss_timer(chip, 0, NULL); if (err < 0) { snd_printk(KERN_ERR "sscape: No timer device " "for AD1845 chip\n"); goto _error; } } if (sscape->type != SSCAPE_VIVO) { err = snd_ctl_add(card, Loading @@ -1128,8 +1020,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, "MIDI mixer control\n"); goto _error; } chip->set_playback_format = ad1845_playback_format; chip->set_capture_format = ad1845_capture_format; } strcpy(card->driver, "SoundScape"); Loading Loading @@ -1157,7 +1047,6 @@ static int __devinit create_sscape(int dev, struct snd_card *card) unsigned dma_cfg; unsigned irq_cfg; unsigned mpu_irq_cfg; unsigned xport; struct resource *io_res; struct resource *wss_res; unsigned long flags; Loading @@ -1177,15 +1066,15 @@ static int __devinit create_sscape(int dev, struct snd_card *card) printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]); return -ENXIO; } xport = port[dev]; /* * Grab IO ports that we will need to probe so that we * can detect and control this hardware ... */ io_res = request_region(xport, 8, "SoundScape"); io_res = request_region(port[dev], 8, "SoundScape"); if (!io_res) { snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport); snd_printk(KERN_ERR "sscape: can't grab port 0x%lx\n", port[dev]); return -EBUSY; } wss_res = NULL; Loading @@ -1212,10 +1101,9 @@ static int __devinit create_sscape(int dev, struct snd_card *card) spin_lock_init(&sscape->fwlock); sscape->io_res = io_res; sscape->wss_res = wss_res; sscape->io_base = xport; sscape->wss_base = wss_port[dev]; sscape->io_base = port[dev]; if (!detect_sscape(sscape)) { if (!detect_sscape(sscape, wss_port[dev])) { printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base); err = -ENODEV; goto _release_dma; Loading Loading @@ -1288,12 +1176,11 @@ static int __devinit create_sscape(int dev, struct snd_card *card) } #define MIDI_DEVNUM 0 if (sscape->type != SSCAPE_VIVO) { err = create_mpu401(card, MIDI_DEVNUM, MPU401_IO(xport), mpu_irq[dev]); err = create_mpu401(card, MIDI_DEVNUM, port[dev], mpu_irq[dev]); if (err < 0) { printk(KERN_ERR "sscape: Failed to create " "MPU-401 device at 0x%x\n", MPU401_IO(xport)); "MPU-401 device at 0x%lx\n", port[dev]); goto _release_dma; } Loading sound/isa/wss/wss_lib.c +53 −28 Original line number Diff line number Diff line Loading @@ -181,25 +181,6 @@ static void snd_wss_wait(struct snd_wss *chip) udelay(100); } static void snd_wss_outm(struct snd_wss *chip, unsigned char reg, unsigned char mask, unsigned char value) { unsigned char tmp = (chip->image[reg] & mask) | value; snd_wss_wait(chip); #ifdef CONFIG_SND_DEBUG if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); #endif chip->image[reg] = tmp; if (!chip->calibrate_mute) { wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); wmb(); wss_outb(chip, CS4231P(REG), tmp); mb(); } } static void snd_wss_dout(struct snd_wss *chip, unsigned char reg, unsigned char value) { Loading Loading @@ -597,7 +578,15 @@ static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute) chip->image[CS4231_RIGHT_INPUT]); snd_wss_dout(chip, CS4231_LOOPBACK, chip->image[CS4231_LOOPBACK]); } else { snd_wss_dout(chip, CS4231_LEFT_INPUT, 0); snd_wss_dout(chip, CS4231_RIGHT_INPUT, 0); snd_wss_dout(chip, CS4231_LOOPBACK, 0xfd); } snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT, mute | chip->image[CS4231_AUX1_LEFT_INPUT]); snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT, Loading Loading @@ -640,7 +629,6 @@ static void snd_wss_playback_format(struct snd_wss *chip, int full_calib = 1; mutex_lock(&chip->mce_mutex); snd_wss_calibrate_mute(chip, 1); if (chip->hardware == WSS_HW_CS4231A || (chip->hardware & WSS_HW_CS4232_MASK)) { spin_lock_irqsave(&chip->reg_lock, flags); Loading @@ -656,6 +644,24 @@ static void snd_wss_playback_format(struct snd_wss *chip, full_calib = 0; } spin_unlock_irqrestore(&chip->reg_lock, flags); } else if (chip->hardware == WSS_HW_AD1845) { unsigned rate = params_rate(params); /* * Program the AD1845 correctly for the playback stream. * Note that we do NOT need to toggle the MCE bit because * the PLAYBACK_ENABLE bit of the Interface Configuration * register is set. * * NOTE: We seem to need to write to the MSB before the LSB * to get the correct sample frequency. */ spin_lock_irqsave(&chip->reg_lock, flags); snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (pdfr & 0xf0)); snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); full_calib = 0; spin_unlock_irqrestore(&chip->reg_lock, flags); } if (full_calib) { snd_wss_mce_up(chip); Loading @@ -673,7 +679,6 @@ static void snd_wss_playback_format(struct snd_wss *chip, udelay(100); /* this seems to help */ snd_wss_mce_down(chip); } snd_wss_calibrate_mute(chip, 0); mutex_unlock(&chip->mce_mutex); } Loading @@ -685,7 +690,6 @@ static void snd_wss_capture_format(struct snd_wss *chip, int full_calib = 1; mutex_lock(&chip->mce_mutex); snd_wss_calibrate_mute(chip, 1); if (chip->hardware == WSS_HW_CS4231A || (chip->hardware & WSS_HW_CS4232_MASK)) { spin_lock_irqsave(&chip->reg_lock, flags); Loading @@ -700,6 +704,24 @@ static void snd_wss_capture_format(struct snd_wss *chip, full_calib = 0; } spin_unlock_irqrestore(&chip->reg_lock, flags); } else if (chip->hardware == WSS_HW_AD1845) { unsigned rate = params_rate(params); /* * Program the AD1845 correctly for the capture stream. * Note that we do NOT need to toggle the MCE bit because * the PLAYBACK_ENABLE bit of the Interface Configuration * register is set. * * NOTE: We seem to need to write to the MSB before the LSB * to get the correct sample frequency. */ spin_lock_irqsave(&chip->reg_lock, flags); snd_wss_out(chip, CS4231_REC_FORMAT, (cdfr & 0xf0)); snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); full_calib = 0; spin_unlock_irqrestore(&chip->reg_lock, flags); } if (full_calib) { snd_wss_mce_up(chip); Loading @@ -724,7 +746,6 @@ static void snd_wss_capture_format(struct snd_wss *chip, spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_mce_down(chip); } snd_wss_calibrate_mute(chip, 0); mutex_unlock(&chip->mce_mutex); } Loading Loading @@ -781,6 +802,7 @@ static void snd_wss_init(struct snd_wss *chip) { unsigned long flags; snd_wss_calibrate_mute(chip, 1); snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE Loading @@ -804,6 +826,8 @@ static void snd_wss_init(struct snd_wss *chip) snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); chip->image[CS4231_IFACE_CTRL] &= ~CS4231_AUTOCALIB; snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); snd_wss_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); spin_unlock_irqrestore(&chip->reg_lock, flags); Loading Loading @@ -837,6 +861,7 @@ static void snd_wss_init(struct snd_wss *chip) chip->image[CS4231_REC_FORMAT]); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_mce_down(chip); snd_wss_calibrate_mute(chip, 0); #ifdef SNDRV_DEBUG_MCE snd_printk(KERN_DEBUG "init: (5)\n"); Loading Loading @@ -895,8 +920,6 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode) mutex_unlock(&chip->open_mutex); return; } snd_wss_calibrate_mute(chip, 1); /* disable IRQ */ spin_lock_irqsave(&chip->reg_lock, flags); if (!(chip->hardware & WSS_HW_AD1848_MASK)) Loading Loading @@ -929,8 +952,6 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode) wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_calibrate_mute(chip, 0); chip->mode = 0; mutex_unlock(&chip->open_mutex); } Loading Loading @@ -1123,7 +1144,7 @@ irqreturn_t snd_wss_interrupt(int irq, void *dev_id) if (chip->hardware & WSS_HW_AD1848_MASK) wss_outb(chip, CS4231P(STATUS), 0); else snd_wss_outm(chip, CS4231_IRQ_STATUS, status, 0); snd_wss_out(chip, CS4231_IRQ_STATUS, status); spin_unlock(&chip->reg_lock); return IRQ_HANDLED; } Loading Loading @@ -1325,6 +1346,10 @@ static int snd_wss_probe(struct snd_wss *chip) chip->image[CS4231_ALT_FEATURE_2] = chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01; } /* enable fine grained frequency selection */ if (chip->hardware == WSS_HW_AD1845) chip->image[AD1845_PWR_DOWN] = 8; ptr = (unsigned char *) &chip->image; regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32; snd_wss_mce_down(chip); Loading Loading
sound/isa/Kconfig +5 −2 Original line number Diff line number Diff line Loading @@ -368,14 +368,17 @@ config SND_SGALAXY will be called snd-sgalaxy. config SND_SSCAPE tristate "Ensoniq SoundScape PnP driver" tristate "Ensoniq SoundScape driver" select SND_HWDEP select SND_MPU401_UART select SND_WSS_LIB help Say Y here to include support for Ensoniq SoundScape PnP Say Y here to include support for Ensoniq SoundScape soundcards. The PCM audio is supported on SoundScape Classic, Elite, PnP and VIVO cards. The MIDI support is very experimental. To compile this driver as a module, choose M here: the module will be called snd-sscape. Loading
sound/isa/sscape.c +38 −151 Original line number Diff line number Diff line Loading @@ -89,9 +89,6 @@ MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids); #endif #define MPU401_IO(i) ((i) + 0) #define MIDI_DATA_IO(i) ((i) + 0) #define MIDI_CTRL_IO(i) ((i) + 1) #define HOST_CTRL_IO(i) ((i) + 2) #define HOST_DATA_IO(i) ((i) + 3) #define ODIE_ADDR_IO(i) ((i) + 4) Loading Loading @@ -129,9 +126,6 @@ enum GA_REG { #define DMA_8BIT 0x80 #define AD1845_FREQ_SEL_MSB 0x16 #define AD1845_FREQ_SEL_LSB 0x17 enum card_type { SSCAPE, SSCAPE_PNP, Loading @@ -141,8 +135,6 @@ enum card_type { struct soundscape { spinlock_t lock; unsigned io_base; unsigned wss_base; int codec_type; int ic_type; enum card_type type; struct resource *io_res; Loading Loading @@ -330,7 +322,7 @@ static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data, */ static inline int verify_mpu401(const struct snd_mpu401 * mpu) { return ((inb(MIDI_CTRL_IO(mpu->port)) & 0xc0) == 0x80); return ((inb(MPU401C(mpu)) & 0xc0) == 0x80); } /* Loading @@ -338,7 +330,7 @@ static inline int verify_mpu401(const struct snd_mpu401 * mpu) */ static inline void initialise_mpu401(const struct snd_mpu401 * mpu) { outb(0, MIDI_DATA_IO(mpu->port)); outb(0, MPU401D(mpu)); } /* Loading Loading @@ -396,20 +388,20 @@ static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg, unsigned ti */ static int obp_startup_ack(struct soundscape *s, unsigned timeout) { while (timeout != 0) { unsigned long end_time = jiffies + msecs_to_jiffies(timeout); do { unsigned long flags; unsigned char x; schedule_timeout_uninterruptible(1); spin_lock_irqsave(&s->lock, flags); x = inb(HOST_DATA_IO(s->io_base)); spin_unlock_irqrestore(&s->lock, flags); if ((x & 0xfe) == 0xfe) return 1; --timeout; } /* while */ msleep(10); } while (time_before(jiffies, end_time)); return 0; } Loading @@ -423,20 +415,20 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout) */ static int host_startup_ack(struct soundscape *s, unsigned timeout) { while (timeout != 0) { unsigned long end_time = jiffies + msecs_to_jiffies(timeout); do { unsigned long flags; unsigned char x; schedule_timeout_uninterruptible(1); spin_lock_irqsave(&s->lock, flags); x = inb(HOST_DATA_IO(s->io_base)); spin_unlock_irqrestore(&s->lock, flags); if (x == 0xfe) return 1; --timeout; } /* while */ msleep(10); } while (time_before(jiffies, end_time)); return 0; } Loading Loading @@ -532,10 +524,10 @@ static int upload_dma_data(struct soundscape *s, * give it 5 seconds (max) ... */ ret = 0; if (!obp_startup_ack(s, 5)) { if (!obp_startup_ack(s, 5000)) { snd_printk(KERN_ERR "sscape: No response from on-board processor after upload\n"); ret = -EAGAIN; } else if (!host_startup_ack(s, 5)) { } else if (!host_startup_ack(s, 5000)) { snd_printk(KERN_ERR "sscape: SoundScape failed to initialise\n"); ret = -EAGAIN; } Loading Loading @@ -732,13 +724,7 @@ static int sscape_midi_get(struct snd_kcontrol *kctl, unsigned long flags; spin_lock_irqsave(&s->lock, flags); set_host_mode_unsafe(s->io_base); if (host_write_ctrl_unsafe(s->io_base, CMD_GET_MIDI_VOL, 100)) { uctl->value.integer.value[0] = host_read_ctrl_unsafe(s->io_base, 100); } set_midi_mode_unsafe(s->io_base); uctl->value.integer.value[0] = s->midi_vol; spin_unlock_irqrestore(&s->lock, flags); return 0; } Loading Loading @@ -773,6 +759,7 @@ static int sscape_midi_put(struct snd_kcontrol *kctl, change = (host_write_ctrl_unsafe(s->io_base, CMD_SET_MIDI_VOL, 100) && host_write_ctrl_unsafe(s->io_base, ((unsigned char) uctl->value.integer. value[0]) & 127, 100) && host_write_ctrl_unsafe(s->io_base, CMD_XXX_MIDI_VOL, 100)); s->midi_vol = (unsigned char) uctl->value.integer.value[0] & 127; __skip_change: /* Loading Loading @@ -815,12 +802,11 @@ static unsigned __devinit get_irq_config(int irq) * Perform certain arcane port-checks to see whether there * is a SoundScape board lurking behind the given ports. */ static int __devinit detect_sscape(struct soundscape *s) static int __devinit detect_sscape(struct soundscape *s, long wss_io) { unsigned long flags; unsigned d; int retval = 0; int codec = s->wss_base; spin_lock_irqsave(&s->lock, flags); Loading @@ -836,13 +822,11 @@ static int __devinit detect_sscape(struct soundscape *s) if ((d & 0x80) != 0) goto _done; if (d == 0) { s->codec_type = 1; if (d == 0) s->ic_type = IC_ODIE; } else if ((d & 0x60) != 0) { s->codec_type = 2; else if ((d & 0x60) != 0) s->ic_type = IC_OPUS; } else else goto _done; outb(0xfa, ODIE_ADDR_IO(s->io_base)); Loading @@ -862,10 +846,10 @@ static int __devinit detect_sscape(struct soundscape *s) sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0); if (s->type == SSCAPE_VIVO) codec += 4; wss_io += 4; /* wait for WSS codec */ for (d = 0; d < 500; d++) { if ((inb(codec) & 0x80) == 0) if ((inb(wss_io) & 0x80) == 0) break; spin_unlock_irqrestore(&s->lock, flags); msleep(1); Loading Loading @@ -954,82 +938,6 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned l } /* * Override for the CS4231 playback format function. * The AD1845 has much simpler format and rate selection. */ static void ad1845_playback_format(struct snd_wss *chip, struct snd_pcm_hw_params *params, unsigned char format) { unsigned long flags; unsigned rate = params_rate(params); /* * The AD1845 can't handle sample frequencies * outside of 4 kHZ to 50 kHZ */ if (rate > 50000) rate = 50000; else if (rate < 4000) rate = 4000; spin_lock_irqsave(&chip->reg_lock, flags); /* * Program the AD1845 correctly for the playback stream. * Note that we do NOT need to toggle the MCE bit because * the PLAYBACK_ENABLE bit of the Interface Configuration * register is set. * * NOTE: We seem to need to write to the MSB before the LSB * to get the correct sample frequency. */ snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (format & 0xf0)); snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8)); snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate); spin_unlock_irqrestore(&chip->reg_lock, flags); } /* * Override for the CS4231 capture format function. * The AD1845 has much simpler format and rate selection. */ static void ad1845_capture_format(struct snd_wss *chip, struct snd_pcm_hw_params *params, unsigned char format) { unsigned long flags; unsigned rate = params_rate(params); /* * The AD1845 can't handle sample frequencies * outside of 4 kHZ to 50 kHZ */ if (rate > 50000) rate = 50000; else if (rate < 4000) rate = 4000; spin_lock_irqsave(&chip->reg_lock, flags); /* * Program the AD1845 correctly for the playback stream. * Note that we do NOT need to toggle the MCE bit because * the CAPTURE_ENABLE bit of the Interface Configuration * register is set. * * NOTE: We seem to need to write to the MSB before the LSB * to get the correct sample frequency. */ snd_wss_out(chip, CS4231_REC_FORMAT, (format & 0xf0)); snd_wss_out(chip, AD1845_FREQ_SEL_MSB, (unsigned char) (rate >> 8)); snd_wss_out(chip, AD1845_FREQ_SEL_LSB, (unsigned char) rate); spin_unlock_irqrestore(&chip->reg_lock, flags); } /* * Create an AD1845 PCM subdevice on the SoundScape. The AD1845 * is very much like a CS4231, with a few extra bits. We will Loading @@ -1055,11 +963,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, unsigned long flags; struct snd_pcm *pcm; #define AD1845_FREQ_SEL_ENABLE 0x08 #define AD1845_PWR_DOWN_CTRL 0x1b #define AD1845_CRYS_CLOCK_SEL 0x1d /* * It turns out that the PLAYBACK_ENABLE bit is set * by the lowlevel driver ... Loading @@ -1074,7 +977,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, */ if (sscape->type != SSCAPE_VIVO) { int val; /* * The input clock frequency on the SoundScape must * be 14.31818 MHz, because we must set this register Loading @@ -1082,22 +984,10 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, */ snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); snd_wss_out(chip, AD1845_CRYS_CLOCK_SEL, 0x20); snd_wss_out(chip, AD1845_CLOCK, 0x20); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_mce_down(chip); /* * More custom configuration: * a) select "mode 2" and provide a current drive of 8mA * b) enable frequency selection (for capture/playback) */ spin_lock_irqsave(&chip->reg_lock, flags); snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2 | 0x10); val = snd_wss_in(chip, AD1845_PWR_DOWN_CTRL); snd_wss_out(chip, AD1845_PWR_DOWN_CTRL, val | AD1845_FREQ_SEL_ENABLE); spin_unlock_irqrestore(&chip->reg_lock, flags); } err = snd_wss_pcm(chip, 0, &pcm); Loading @@ -1113,12 +1003,14 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, "for AD1845 chip\n"); goto _error; } if (chip->hardware != WSS_HW_AD1848) { err = snd_wss_timer(chip, 0, NULL); if (err < 0) { snd_printk(KERN_ERR "sscape: No timer device " "for AD1845 chip\n"); goto _error; } } if (sscape->type != SSCAPE_VIVO) { err = snd_ctl_add(card, Loading @@ -1128,8 +1020,6 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, "MIDI mixer control\n"); goto _error; } chip->set_playback_format = ad1845_playback_format; chip->set_capture_format = ad1845_capture_format; } strcpy(card->driver, "SoundScape"); Loading Loading @@ -1157,7 +1047,6 @@ static int __devinit create_sscape(int dev, struct snd_card *card) unsigned dma_cfg; unsigned irq_cfg; unsigned mpu_irq_cfg; unsigned xport; struct resource *io_res; struct resource *wss_res; unsigned long flags; Loading @@ -1177,15 +1066,15 @@ static int __devinit create_sscape(int dev, struct snd_card *card) printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]); return -ENXIO; } xport = port[dev]; /* * Grab IO ports that we will need to probe so that we * can detect and control this hardware ... */ io_res = request_region(xport, 8, "SoundScape"); io_res = request_region(port[dev], 8, "SoundScape"); if (!io_res) { snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport); snd_printk(KERN_ERR "sscape: can't grab port 0x%lx\n", port[dev]); return -EBUSY; } wss_res = NULL; Loading @@ -1212,10 +1101,9 @@ static int __devinit create_sscape(int dev, struct snd_card *card) spin_lock_init(&sscape->fwlock); sscape->io_res = io_res; sscape->wss_res = wss_res; sscape->io_base = xport; sscape->wss_base = wss_port[dev]; sscape->io_base = port[dev]; if (!detect_sscape(sscape)) { if (!detect_sscape(sscape, wss_port[dev])) { printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base); err = -ENODEV; goto _release_dma; Loading Loading @@ -1288,12 +1176,11 @@ static int __devinit create_sscape(int dev, struct snd_card *card) } #define MIDI_DEVNUM 0 if (sscape->type != SSCAPE_VIVO) { err = create_mpu401(card, MIDI_DEVNUM, MPU401_IO(xport), mpu_irq[dev]); err = create_mpu401(card, MIDI_DEVNUM, port[dev], mpu_irq[dev]); if (err < 0) { printk(KERN_ERR "sscape: Failed to create " "MPU-401 device at 0x%x\n", MPU401_IO(xport)); "MPU-401 device at 0x%lx\n", port[dev]); goto _release_dma; } Loading
sound/isa/wss/wss_lib.c +53 −28 Original line number Diff line number Diff line Loading @@ -181,25 +181,6 @@ static void snd_wss_wait(struct snd_wss *chip) udelay(100); } static void snd_wss_outm(struct snd_wss *chip, unsigned char reg, unsigned char mask, unsigned char value) { unsigned char tmp = (chip->image[reg] & mask) | value; snd_wss_wait(chip); #ifdef CONFIG_SND_DEBUG if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); #endif chip->image[reg] = tmp; if (!chip->calibrate_mute) { wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); wmb(); wss_outb(chip, CS4231P(REG), tmp); mb(); } } static void snd_wss_dout(struct snd_wss *chip, unsigned char reg, unsigned char value) { Loading Loading @@ -597,7 +578,15 @@ static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute) chip->image[CS4231_RIGHT_INPUT]); snd_wss_dout(chip, CS4231_LOOPBACK, chip->image[CS4231_LOOPBACK]); } else { snd_wss_dout(chip, CS4231_LEFT_INPUT, 0); snd_wss_dout(chip, CS4231_RIGHT_INPUT, 0); snd_wss_dout(chip, CS4231_LOOPBACK, 0xfd); } snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT, mute | chip->image[CS4231_AUX1_LEFT_INPUT]); snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT, Loading Loading @@ -640,7 +629,6 @@ static void snd_wss_playback_format(struct snd_wss *chip, int full_calib = 1; mutex_lock(&chip->mce_mutex); snd_wss_calibrate_mute(chip, 1); if (chip->hardware == WSS_HW_CS4231A || (chip->hardware & WSS_HW_CS4232_MASK)) { spin_lock_irqsave(&chip->reg_lock, flags); Loading @@ -656,6 +644,24 @@ static void snd_wss_playback_format(struct snd_wss *chip, full_calib = 0; } spin_unlock_irqrestore(&chip->reg_lock, flags); } else if (chip->hardware == WSS_HW_AD1845) { unsigned rate = params_rate(params); /* * Program the AD1845 correctly for the playback stream. * Note that we do NOT need to toggle the MCE bit because * the PLAYBACK_ENABLE bit of the Interface Configuration * register is set. * * NOTE: We seem to need to write to the MSB before the LSB * to get the correct sample frequency. */ spin_lock_irqsave(&chip->reg_lock, flags); snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (pdfr & 0xf0)); snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); full_calib = 0; spin_unlock_irqrestore(&chip->reg_lock, flags); } if (full_calib) { snd_wss_mce_up(chip); Loading @@ -673,7 +679,6 @@ static void snd_wss_playback_format(struct snd_wss *chip, udelay(100); /* this seems to help */ snd_wss_mce_down(chip); } snd_wss_calibrate_mute(chip, 0); mutex_unlock(&chip->mce_mutex); } Loading @@ -685,7 +690,6 @@ static void snd_wss_capture_format(struct snd_wss *chip, int full_calib = 1; mutex_lock(&chip->mce_mutex); snd_wss_calibrate_mute(chip, 1); if (chip->hardware == WSS_HW_CS4231A || (chip->hardware & WSS_HW_CS4232_MASK)) { spin_lock_irqsave(&chip->reg_lock, flags); Loading @@ -700,6 +704,24 @@ static void snd_wss_capture_format(struct snd_wss *chip, full_calib = 0; } spin_unlock_irqrestore(&chip->reg_lock, flags); } else if (chip->hardware == WSS_HW_AD1845) { unsigned rate = params_rate(params); /* * Program the AD1845 correctly for the capture stream. * Note that we do NOT need to toggle the MCE bit because * the PLAYBACK_ENABLE bit of the Interface Configuration * register is set. * * NOTE: We seem to need to write to the MSB before the LSB * to get the correct sample frequency. */ spin_lock_irqsave(&chip->reg_lock, flags); snd_wss_out(chip, CS4231_REC_FORMAT, (cdfr & 0xf0)); snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff); snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff); full_calib = 0; spin_unlock_irqrestore(&chip->reg_lock, flags); } if (full_calib) { snd_wss_mce_up(chip); Loading @@ -724,7 +746,6 @@ static void snd_wss_capture_format(struct snd_wss *chip, spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_mce_down(chip); } snd_wss_calibrate_mute(chip, 0); mutex_unlock(&chip->mce_mutex); } Loading Loading @@ -781,6 +802,7 @@ static void snd_wss_init(struct snd_wss *chip) { unsigned long flags; snd_wss_calibrate_mute(chip, 1); snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE Loading @@ -804,6 +826,8 @@ static void snd_wss_init(struct snd_wss *chip) snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); chip->image[CS4231_IFACE_CTRL] &= ~CS4231_AUTOCALIB; snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); snd_wss_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); spin_unlock_irqrestore(&chip->reg_lock, flags); Loading Loading @@ -837,6 +861,7 @@ static void snd_wss_init(struct snd_wss *chip) chip->image[CS4231_REC_FORMAT]); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_mce_down(chip); snd_wss_calibrate_mute(chip, 0); #ifdef SNDRV_DEBUG_MCE snd_printk(KERN_DEBUG "init: (5)\n"); Loading Loading @@ -895,8 +920,6 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode) mutex_unlock(&chip->open_mutex); return; } snd_wss_calibrate_mute(chip, 1); /* disable IRQ */ spin_lock_irqsave(&chip->reg_lock, flags); if (!(chip->hardware & WSS_HW_AD1848_MASK)) Loading Loading @@ -929,8 +952,6 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode) wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_calibrate_mute(chip, 0); chip->mode = 0; mutex_unlock(&chip->open_mutex); } Loading Loading @@ -1123,7 +1144,7 @@ irqreturn_t snd_wss_interrupt(int irq, void *dev_id) if (chip->hardware & WSS_HW_AD1848_MASK) wss_outb(chip, CS4231P(STATUS), 0); else snd_wss_outm(chip, CS4231_IRQ_STATUS, status, 0); snd_wss_out(chip, CS4231_IRQ_STATUS, status); spin_unlock(&chip->reg_lock); return IRQ_HANDLED; } Loading Loading @@ -1325,6 +1346,10 @@ static int snd_wss_probe(struct snd_wss *chip) chip->image[CS4231_ALT_FEATURE_2] = chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01; } /* enable fine grained frequency selection */ if (chip->hardware == WSS_HW_AD1845) chip->image[AD1845_PWR_DOWN] = 8; ptr = (unsigned char *) &chip->image; regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32; snd_wss_mce_down(chip); Loading