Merge branch 'topic/sscape-fix' into for-linus
This commit is contained in:
Коммит
d080732334
|
@ -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.
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 ...
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -1113,11 +1003,13 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
|
|||
"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 @@ 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");
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче