From: Takashi Iwai Date: Mon, 23 Mar 2009 23:36:21 +0000 (+0100) Subject: Merge branch 'topic/sscape-fix' into for-linus X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=d0807323345f1cd8ab578b09aab04d10862e9414;hp=-c;p=mv-sheeva.git Merge branch 'topic/sscape-fix' into for-linus --- d0807323345f1cd8ab578b09aab04d10862e9414 diff --combined sound/isa/Kconfig index 2df20e403f2,542c1ead14b..c5c9a9218ff --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@@ -56,8 -56,8 +56,8 @@@ config SND_AD184 Say Y here to include support for AD1848 (Analog Devices) or CS4248 (Cirrus Logic - Crystal Semiconductors) chips. - For newer chips from Cirrus Logic, use the CS4231, CS4232 or - CS4236+ drivers. + For newer chips from Cirrus Logic, use the CS4231 or CS4232+ + drivers. To compile this driver as a module, choose M here: the module will be called snd-ad1848. @@@ -94,8 -94,6 +94,8 @@@ config SND_CMI833 tristate "C-Media CMI8330" select SND_WSS_LIB select SND_SB16_DSP + select SND_OPL3_LIB + select SND_MPU401_UART help Say Y here to include support for soundcards based on the C-Media CMI8330 chip. @@@ -114,15 -112,26 +114,15 @@@ config SND_CS423 To compile this driver as a module, choose M here: the module will be called snd-cs4231. -config SND_CS4232 - tristate "Generic Cirrus Logic CS4232 driver" - select SND_OPL3_LIB - select SND_MPU401_UART - select SND_WSS_LIB - help - Say Y here to include support for CS4232 chips from Cirrus - Logic - Crystal Semiconductors. - - To compile this driver as a module, choose M here: the module - will be called snd-cs4232. - config SND_CS4236 - tristate "Generic Cirrus Logic CS4236+ driver" + tristate "Generic Cirrus Logic CS4232/CS4236+ driver" select SND_OPL3_LIB select SND_MPU401_UART select SND_WSS_LIB help - Say Y to include support for CS4235,CS4236,CS4237B,CS4238B, - CS4239 chips from Cirrus Logic - Crystal Semiconductors. + Say Y to include support for CS4232,CS4235,CS4236,CS4237B, + CS4238B,CS4239 chips from Cirrus Logic - Crystal + Semiconductors. To compile this driver as a module, choose M here: the module will be called snd-cs4236. @@@ -368,14 -377,17 +368,17 @@@ config SND_SGALAX 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. @@@ -402,36 -414,5 +405,36 @@@ config SND_WAVEFRONT_FIRMWARE_IN_KERNE you need to install the firmware files from the alsa-firmware package. +config SND_MSND_PINNACLE + tristate "Turtle Beach MultiSound Pinnacle/Fiji driver" + depends on X86 && EXPERIMENTAL + select FW_LOADER + select SND_MPU401_UART + select SND_PCM + help + Say Y to include support for Turtle Beach MultiSound Pinnacle/ + Fiji soundcards. + + To compile this driver as a module, choose M here: the module + will be called snd-msnd-pinnacle. + +config SND_MSND_CLASSIC + tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey" + depends on X86 && EXPERIMENTAL + select FW_LOADER + select SND_MPU401_UART + select SND_PCM + help + Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or + Monterey (not for the Pinnacle or Fiji). + + See for important information + about this driver. Note that it has been discontinued, but the + Voyetra Turtle Beach knowledge base entry for it is still available + at . + + To compile this driver as a module, choose M here: the module + will be called snd-msnd-classic. + endif # SND_ISA diff --combined sound/isa/sscape.c index 4025fb558c5,33c1258029f..66187122377 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@@ -89,9 -89,6 +89,6 @@@ MODULE_DEVICE_TABLE(pnp_card, sscape_pn #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) @@@ -129,9 -126,6 +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, @@@ -141,8 -135,6 +135,6 @@@ 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; @@@ -330,7 -322,7 +322,7 @@@ static int host_write_ctrl_unsafe(unsig */ 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); } /* @@@ -338,7 -330,7 +330,7 @@@ */ static inline void initialise_mpu401(const struct snd_mpu401 * mpu) { - outb(0, MIDI_DATA_IO(mpu->port)); + outb(0, MPU401D(mpu)); } /* @@@ -396,20 -388,20 +388,20 @@@ static int sscape_wait_dma_unsafe(unsig */ 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; } @@@ -423,20 -415,20 +415,20 @@@ */ 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; } @@@ -532,10 -524,10 +524,10 @@@ static int upload_dma_data(struct sound * 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; } @@@ -732,13 -724,7 +724,7 @@@ static int sscape_midi_get(struct snd_k 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; } @@@ -773,6 -759,7 +759,7 @@@ static int sscape_midi_put(struct snd_k 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: /* @@@ -815,12 -802,11 +802,11 @@@ static unsigned __devinit get_irq_confi * 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); @@@ -836,13 -822,11 +822,11 @@@ 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)); @@@ -862,10 -846,10 +846,10 @@@ 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); @@@ -954,82 -938,6 +938,6 @@@ static int __devinit create_mpu401(stru } - /* - * 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 @@@ -1055,11 -963,6 +963,6 @@@ static int __devinit create_ad1845(stru 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 ... @@@ -1074,7 -977,6 +977,6 @@@ */ 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 @@@ -1082,22 -984,10 +984,10 @@@ */ 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); @@@ -1113,11 -1003,13 +1003,13 @@@ "for AD1845 chip\n"); goto _error; } - 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 (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) { @@@ -1128,8 -1020,6 +1020,6 @@@ "MIDI mixer control\n"); goto _error; } - chip->set_playback_format = ad1845_playback_format; - chip->set_capture_format = ad1845_capture_format; } strcpy(card->driver, "SoundScape"); @@@ -1157,7 -1047,6 +1047,6 @@@ static int __devinit create_sscape(int unsigned dma_cfg; unsigned irq_cfg; unsigned mpu_irq_cfg; - unsigned xport; struct resource *io_res; struct resource *wss_res; unsigned long flags; @@@ -1177,15 -1066,15 +1066,15 @@@ 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; @@@ -1212,10 -1101,9 +1101,9 @@@ 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; @@@ -1288,12 -1176,11 +1176,11 @@@ } #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; } @@@ -1357,10 -1244,10 +1244,10 @@@ static int __devinit snd_sscape_probe(s struct soundscape *sscape; int ret; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, - sizeof(struct soundscape)); - if (!card) - return -ENOMEM; + ret = snd_card_create(index[dev], id[dev], THIS_MODULE, + sizeof(struct soundscape), &card); + if (ret < 0) + return ret; sscape = get_card_soundscape(card); sscape->type = SSCAPE; @@@ -1462,10 -1349,10 +1349,10 @@@ static int __devinit sscape_pnp_detect( * Create a new ALSA sound card entry, in anticipation * of detecting our hardware ... */ - card = snd_card_new(index[idx], id[idx], THIS_MODULE, - sizeof(struct soundscape)); - if (!card) - return -ENOMEM; + ret = snd_card_create(index[idx], id[idx], THIS_MODULE, + sizeof(struct soundscape), &card); + if (ret < 0) + return ret; sscape = get_card_soundscape(card); diff --combined sound/isa/wss/wss_lib.c index ac27832b2c6,f0c0be5bb68..5d2ba1b749a --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@@ -181,25 -181,6 +181,6 @@@ static void snd_wss_wait(struct snd_ws 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) { @@@ -219,8 -200,7 +200,8 @@@ void snd_wss_out(struct snd_wss *chip, snd_wss_wait(chip); #ifdef CONFIG_SND_DEBUG if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); + snd_printk(KERN_DEBUG "out: auto calibration time out " + "- reg = 0x%x, value = 0x%x\n", reg, value); #endif wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); wss_outb(chip, CS4231P(REG), value); @@@ -236,8 -216,7 +217,8 @@@ unsigned char snd_wss_in(struct snd_ws snd_wss_wait(chip); #ifdef CONFIG_SND_DEBUG if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk("in: auto calibration time out - reg = 0x%x\n", reg); + snd_printk(KERN_DEBUG "in: auto calibration time out " + "- reg = 0x%x\n", reg); #endif wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg); mb(); @@@ -254,7 -233,7 +235,7 @@@ void snd_cs4236_ext_out(struct snd_wss wss_outb(chip, CS4231P(REG), val); chip->eimage[CS4236_REG(reg)] = val; #if 0 - printk("ext out : reg = 0x%x, val = 0x%x\n", reg, val); + printk(KERN_DEBUG "ext out : reg = 0x%x, val = 0x%x\n", reg, val); #endif } EXPORT_SYMBOL(snd_cs4236_ext_out); @@@ -270,8 -249,7 +251,8 @@@ unsigned char snd_cs4236_ext_in(struct { unsigned char res; res = wss_inb(chip, CS4231P(REG)); - printk("ext in : reg = 0x%x, val = 0x%x\n", reg, res); + printk(KERN_DEBUG "ext in : reg = 0x%x, val = 0x%x\n", + reg, res); return res; } #endif @@@ -397,16 -375,13 +378,16 @@@ void snd_wss_mce_up(struct snd_wss *chi snd_wss_wait(chip); #ifdef CONFIG_SND_DEBUG if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk("mce_up - auto calibration time out (0)\n"); + snd_printk(KERN_DEBUG + "mce_up - auto calibration time out (0)\n"); #endif spin_lock_irqsave(&chip->reg_lock, flags); chip->mce_bit |= CS4231_MCE; timeout = wss_inb(chip, CS4231P(REGSEL)); if (timeout == 0x80) - snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port); + snd_printk(KERN_DEBUG "mce_up [0x%lx]: " + "serious init problem - codec still busy\n", + chip->port); if (!(timeout & CS4231_MCE)) wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); @@@ -425,9 -400,7 +406,9 @@@ void snd_wss_mce_down(struct snd_wss *c #ifdef CONFIG_SND_DEBUG if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) - snd_printk("mce_down [0x%lx] - auto calibration time out (0)\n", (long)CS4231P(REGSEL)); + snd_printk(KERN_DEBUG "mce_down [0x%lx] - " + "auto calibration time out (0)\n", + (long)CS4231P(REGSEL)); #endif spin_lock_irqsave(&chip->reg_lock, flags); chip->mce_bit &= ~CS4231_MCE; @@@ -435,9 -408,7 +416,9 @@@ wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); spin_unlock_irqrestore(&chip->reg_lock, flags); if (timeout == 0x80) - snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); + snd_printk(KERN_DEBUG "mce_down [0x%lx]: " + "serious init problem - codec still busy\n", + chip->port); if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask)) return; @@@ -575,7 -546,7 +556,7 @@@ static unsigned char snd_wss_get_format if (channels > 1) rformat |= CS4231_STEREO; #if 0 - snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode); + snd_printk(KERN_DEBUG "get_format: 0x%x (mode=0x%x)\n", format, mode); #endif return rformat; } @@@ -597,7 -568,15 +578,15 @@@ static void snd_wss_calibrate_mute(stru 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, @@@ -640,7 -619,6 +629,6 @@@ static void snd_wss_playback_format(str 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); @@@ -656,6 -634,24 +644,24 @@@ 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); @@@ -673,7 -669,6 +679,6 @@@ udelay(100); /* this seems to help */ snd_wss_mce_down(chip); } - snd_wss_calibrate_mute(chip, 0); mutex_unlock(&chip->mce_mutex); } @@@ -685,7 -680,6 +690,6 @@@ static void snd_wss_capture_format(stru 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); @@@ -700,6 -694,24 +704,24 @@@ 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); @@@ -724,7 -736,6 +746,6 @@@ spin_unlock_irqrestore(&chip->reg_lock, flags); snd_wss_mce_down(chip); } - snd_wss_calibrate_mute(chip, 0); mutex_unlock(&chip->mce_mutex); } @@@ -781,10 -792,11 +802,11 @@@ static void snd_wss_init(struct snd_ws { unsigned long flags; + snd_wss_calibrate_mute(chip, 1); snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk("init: (1)\n"); + snd_printk(KERN_DEBUG "init: (1)\n"); #endif snd_wss_mce_up(chip); spin_lock_irqsave(&chip->reg_lock, flags); @@@ -799,18 -811,20 +821,20 @@@ snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk("init: (2)\n"); + snd_printk(KERN_DEBUG "init: (2)\n"); #endif 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); snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk("init: (3) - afei = 0x%x\n", + snd_printk(KERN_DEBUG "init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]); #endif @@@ -827,7 -841,7 +851,7 @@@ snd_wss_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printk("init: (4)\n"); + snd_printk(KERN_DEBUG "init: (4)\n"); #endif snd_wss_mce_up(chip); @@@ -837,9 -851,10 +861,10 @@@ 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("init: (5)\n"); + snd_printk(KERN_DEBUG "init: (5)\n"); #endif } @@@ -895,8 -910,6 +920,6 @@@ static void snd_wss_close(struct snd_ws 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)) @@@ -929,8 -942,6 +952,6 @@@ 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); } @@@ -1123,7 -1134,7 +1144,7 @@@ irqreturn_t snd_wss_interrupt(int irq, 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; } @@@ -1288,8 -1299,7 +1309,8 @@@ static int snd_wss_probe(struct snd_ws } else if (rev == 0x03) { chip->hardware = WSS_HW_CS4236B; } else { - snd_printk("unknown CS chip with version 0x%x\n", rev); + snd_printk(KERN_ERR + "unknown CS chip with version 0x%x\n", rev); return -ENODEV; /* unknown CS4231 chip? */ } } @@@ -1325,6 -1335,10 +1346,10 @@@ 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); @@@ -1353,10 -1367,7 +1378,10 @@@ case 6: break; default: - snd_printk("unknown CS4235 chip (enhanced version = 0x%x)\n", id); + snd_printk(KERN_WARNING + "unknown CS4235 chip " + "(enhanced version = 0x%x)\n", + id); } } else if ((id & 0x1f) == 0x0b) { /* CS4236/B */ switch (id >> 5) { @@@ -1367,10 -1378,7 +1392,10 @@@ chip->hardware = WSS_HW_CS4236B; break; default: - snd_printk("unknown CS4236 chip (enhanced version = 0x%x)\n", id); + snd_printk(KERN_WARNING + "unknown CS4236 chip " + "(enhanced version = 0x%x)\n", + id); } } else if ((id & 0x1f) == 0x08) { /* CS4237B */ chip->hardware = WSS_HW_CS4237B; @@@ -1381,10 -1389,7 +1406,10 @@@ case 7: break; default: - snd_printk("unknown CS4237B chip (enhanced version = 0x%x)\n", id); + snd_printk(KERN_WARNING + "unknown CS4237B chip " + "(enhanced version = 0x%x)\n", + id); } } else if ((id & 0x1f) == 0x09) { /* CS4238B */ chip->hardware = WSS_HW_CS4238B; @@@ -1394,10 -1399,7 +1419,10 @@@ case 7: break; default: - snd_printk("unknown CS4238B chip (enhanced version = 0x%x)\n", id); + snd_printk(KERN_WARNING + "unknown CS4238B chip " + "(enhanced version = 0x%x)\n", + id); } } else if ((id & 0x1f) == 0x1e) { /* CS4239 */ chip->hardware = WSS_HW_CS4239; @@@ -1407,15 -1409,10 +1432,15 @@@ case 6: break; default: - snd_printk("unknown CS4239 chip (enhanced version = 0x%x)\n", id); + snd_printk(KERN_WARNING + "unknown CS4239 chip " + "(enhanced version = 0x%x)\n", + id); } } else { - snd_printk("unknown CS4236/CS423xB chip (enhanced version = 0x%x)\n", id); + snd_printk(KERN_WARNING + "unknown CS4236/CS423xB chip " + "(enhanced version = 0x%x)\n", id); } } } @@@ -1646,8 -1643,7 +1671,8 @@@ static void snd_wss_resume(struct snd_w wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f)); spin_unlock_irqrestore(&chip->reg_lock, flags); if (timeout == 0x80) - snd_printk("down [0x%lx]: serious init problem - codec still busy\n", chip->port); + snd_printk(KERN_ERR "down [0x%lx]: serious init problem " + "- codec still busy\n", chip->port); if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) { return; @@@ -1657,7 -1653,7 +1682,7 @@@ } #endif /* CONFIG_PM */ -static int snd_wss_free(struct snd_wss *chip) +int snd_wss_free(struct snd_wss *chip) { release_and_free_resource(chip->res_port); release_and_free_resource(chip->res_cport); @@@ -1680,7 -1676,6 +1705,7 @@@ kfree(chip); return 0; } +EXPORT_SYMBOL(snd_wss_free); static int snd_wss_dev_free(struct snd_device *device) { @@@ -1850,8 -1845,7 +1875,8 @@@ int snd_wss_create(struct snd_card *car #if 0 if (chip->hardware & WSS_HW_CS4232_MASK) { if (chip->res_cport == NULL) - snd_printk("CS4232 control port features are not accessible\n"); + snd_printk(KERN_ERR "CS4232 control port features are " + "not accessible\n"); } #endif