Commit ead893c0 authored by Krzysztof Helt's avatar Krzysztof Helt Committed by Jaroslav Kysela

ALSA: wss_lib: use wss pcm code instead of ad1848 one

Use the wss pcm code and kill the ad1848 pcm code.

The AD1848 chip is much slower than CS4231 chips
so the waiting loop was increased 100x (10x is not
enough).
Signed-off-by: default avatarKrzysztof Helt <krzysztof.h1@wp.pl>
Reviewed-by: default avatarRene Herman <rene.herman@gmail.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@perex.cz>
parent 5664daa1
......@@ -97,11 +97,6 @@
#define AD1848_CALIB_IN_PROGRESS 0x20 /* auto calibrate in progress */
#define AD1848_DMA_REQUEST 0x10 /* DMA request in progress */
/* IBM Thinkpad specific stuff */
#define AD1848_THINKPAD_CTL_PORT1 0x15e8
#define AD1848_THINKPAD_CTL_PORT2 0x15e9
#define AD1848_THINKPAD_CS4248_ENABLE_BIT 0x02
/* exported functions */
void snd_ad1848_out(struct snd_wss *chip, unsigned char reg,
......@@ -113,7 +108,4 @@ int snd_ad1848_create(struct snd_card *card,
unsigned short hardware,
struct snd_wss **chip);
int snd_ad1848_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm);
const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction);
#endif /* __SOUND_AD1848_H */
......@@ -71,6 +71,11 @@
#define WSS_HWSHARE_DMA1 (1<<1)
#define WSS_HWSHARE_DMA2 (1<<2)
/* IBM Thinkpad specific stuff */
#define AD1848_THINKPAD_CTL_PORT1 0x15e8
#define AD1848_THINKPAD_CTL_PORT2 0x15e9
#define AD1848_THINKPAD_CS4248_ENABLE_BIT 0x02
struct snd_wss {
unsigned long port; /* base i/o port */
struct resource *res_port;
......@@ -153,6 +158,8 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm);
int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer);
int snd_wss_mixer(struct snd_wss *chip);
const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction);
int snd_cs4236_create(struct snd_card *card,
unsigned long port,
unsigned long cport,
......
# ALSA ISA drivers
config SND_AD1848_LIB
config SND_WSS_LIB
tristate
select SND_PCM
config SND_WSS_LIB
config SND_AD1848_LIB
tristate
select SND_PCM
select SND_WSS_LIB
config SND_SB_COMMON
tristate
......
......@@ -102,7 +102,7 @@ static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n)
card->private_data = chip;
error = snd_ad1848_pcm(chip, 0, &pcm);
error = snd_wss_pcm(chip, 0, &pcm);
if (error < 0)
goto out;
......
This diff is collapsed.
......@@ -413,7 +413,7 @@ static int __devinit snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *
chip->streams[CMI_SB_STREAM].private_data = chip->sb;
/* AD1848 */
ops = snd_ad1848_get_pcm_ops(CMI_AD_STREAM);
ops = snd_wss_get_pcm_ops(CMI_AD_STREAM);
chip->streams[CMI_AD_STREAM].ops = *ops;
chip->streams[CMI_AD_STREAM].open = ops->open;
chip->streams[CMI_AD_STREAM].ops.open = cmi_open_callbacks[CMI_AD_STREAM];
......
......@@ -754,18 +754,15 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
#ifdef OPTi93X
chip->codec = codec;
#endif
error = snd_wss_pcm(codec, 0, &pcm);
if (error < 0)
return error;
#else
error = snd_ad1848_create(card, chip->wss_base + 4, chip->irq,
chip->dma1, WSS_HW_DETECT, &codec);
if (error < 0)
return error;
error = snd_ad1848_pcm(codec, 0, &pcm);
#endif
error = snd_wss_pcm(codec, 0, &pcm);
if (error < 0)
return error;
#endif
error = snd_wss_mixer(codec);
if (error < 0)
return error;
......
......@@ -554,10 +554,10 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
goto err_unmap2;
card->private_data = chip;
err = snd_ad1848_pcm(chip, 0, NULL);
err = snd_wss_pcm(chip, 0, NULL);
if (err < 0) {
snd_printk(KERN_ERR PFX
"error creating new ad1848 PCM device\n");
"error creating new WSS PCM device\n");
goto err_unmap2;
}
err = snd_wss_mixer(chip);
......
......@@ -273,8 +273,9 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev)
goto _err;
card->private_data = chip;
if ((err = snd_ad1848_pcm(chip, 0, NULL)) < 0) {
snd_printdd(PFX "error creating new ad1848 PCM device\n");
err = snd_wss_pcm(chip, 0, NULL);
if (err < 0) {
snd_printdd(PFX "error creating new WSS PCM device\n");
goto _err;
}
err = snd_wss_mixer(chip);
......
......@@ -380,7 +380,7 @@ static void snd_wss_busy_wait(struct snd_wss *chip)
for (timeout = 5; timeout > 0; timeout--)
wss_inb(chip, CS4231P(REGSEL));
/* end of cleanup sequence */
for (timeout = 250;
for (timeout = 25000;
timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
timeout--)
udelay(10);
......@@ -413,6 +413,7 @@ void snd_wss_mce_down(struct snd_wss *chip)
unsigned long flags;
unsigned long end_time;
int timeout;
int hw_mask = WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK | WSS_HW_AD1848;
snd_wss_busy_wait(chip);
......@@ -427,10 +428,8 @@ void snd_wss_mce_down(struct snd_wss *chip)
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);
if ((timeout & CS4231_MCE) == 0 ||
!(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) {
if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask))
return;
}
/*
* Wait for (possible -- during init auto-calibration may not be set)
......@@ -601,12 +600,14 @@ static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute)
mute ? 0x80 : chip->image[CS4231_LEFT_OUTPUT]);
snd_wss_dout(chip, CS4231_RIGHT_OUTPUT,
mute ? 0x80 : chip->image[CS4231_RIGHT_OUTPUT]);
snd_wss_dout(chip, CS4231_LEFT_LINE_IN,
mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]);
snd_wss_dout(chip, CS4231_RIGHT_LINE_IN,
mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]);
snd_wss_dout(chip, CS4231_MONO_CTRL,
mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]);
if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
snd_wss_dout(chip, CS4231_LEFT_LINE_IN,
mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]);
snd_wss_dout(chip, CS4231_RIGHT_LINE_IN,
mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]);
snd_wss_dout(chip, CS4231_MONO_CTRL,
mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]);
}
if (chip->hardware == WSS_HW_INTERWAVE) {
snd_wss_dout(chip, CS4231_LEFT_MIC_INPUT,
mute ? 0x80 : chip->image[CS4231_LEFT_MIC_INPUT]);
......@@ -706,7 +707,10 @@ static void snd_wss_capture_format(struct snd_wss *chip,
snd_wss_mce_up(chip);
spin_lock_irqsave(&chip->reg_lock, flags);
}
snd_wss_out(chip, CS4231_REC_FORMAT, cdfr);
if (chip->hardware & WSS_HW_AD1848_MASK)
snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr);
else
snd_wss_out(chip, CS4231_REC_FORMAT, cdfr);
spin_unlock_irqrestore(&chip->reg_lock, flags);
snd_wss_mce_down(chip);
}
......@@ -818,7 +822,9 @@ static void snd_wss_init(struct snd_wss *chip)
snd_wss_mce_up(chip);
spin_lock_irqsave(&chip->reg_lock, flags);
snd_wss_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT]);
if (!(chip->hardware & WSS_HW_AD1848_MASK))
snd_wss_out(chip, CS4231_REC_FORMAT,
chip->image[CS4231_REC_FORMAT]);
spin_unlock_irqrestore(&chip->reg_lock, flags);
snd_wss_mce_down(chip);
......@@ -844,20 +850,24 @@ static int snd_wss_open(struct snd_wss *chip, unsigned int mode)
}
/* ok. now enable and ack CODEC IRQ */
spin_lock_irqsave(&chip->reg_lock, flags);
snd_wss_out(chip, CS4231_IRQ_STATUS,
CS4231_PLAYBACK_IRQ |
CS4231_RECORD_IRQ |
CS4231_TIMER_IRQ);
snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
snd_wss_out(chip, CS4231_IRQ_STATUS,
CS4231_PLAYBACK_IRQ |
CS4231_RECORD_IRQ |
CS4231_TIMER_IRQ);
snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
}
wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE;
snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
snd_wss_out(chip, CS4231_IRQ_STATUS,
CS4231_PLAYBACK_IRQ |
CS4231_RECORD_IRQ |
CS4231_TIMER_IRQ);
snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
snd_wss_out(chip, CS4231_IRQ_STATUS,
CS4231_PLAYBACK_IRQ |
CS4231_RECORD_IRQ |
CS4231_TIMER_IRQ);
snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
}
spin_unlock_irqrestore(&chip->reg_lock, flags);
chip->mode = mode;
......@@ -879,7 +889,8 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode)
/* disable IRQ */
spin_lock_irqsave(&chip->reg_lock, flags);
snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
if (!(chip->hardware & WSS_HW_AD1848_MASK))
snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE;
......@@ -902,7 +913,8 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode)
}
/* clear IRQ again */
snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
if (!(chip->hardware & WSS_HW_AD1848_MASK))
snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
spin_unlock_irqrestore(&chip->reg_lock, flags);
......@@ -1023,7 +1035,13 @@ static int snd_wss_capture_prepare(struct snd_pcm_substream *substream)
chip->c_dma_size = size;
chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT], count) - 1;
if (chip->hardware & WSS_HW_AD1848_MASK)
count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT],
count);
else
count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT],
count);
count--;
if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) {
snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
snd_wss_out(chip, CS4231_PLY_UPR_CNT,
......@@ -1341,6 +1359,11 @@ static int snd_wss_playback_open(struct snd_pcm_substream *substream)
runtime->hw = snd_wss_playback;
/* hardware limitation of older chipsets */
if (chip->hardware & WSS_HW_AD1848_MASK)
runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
SNDRV_PCM_FMTBIT_S16_BE);
/* hardware bug in InterWave chipset */
if (chip->hardware == WSS_HW_INTERWAVE && chip->dma1 > 3)
runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW;
......@@ -1379,6 +1402,11 @@ static int snd_wss_capture_open(struct snd_pcm_substream *substream)
runtime->hw = snd_wss_capture;
/* hardware limitation of older chipsets */
if (chip->hardware & WSS_HW_AD1848_MASK)
runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
SNDRV_PCM_FMTBIT_S16_BE);
/* hardware limitation of cheap chips */
if (chip->hardware == WSS_HW_CS4235 ||
chip->hardware == WSS_HW_CS4239)
......@@ -1423,6 +1451,26 @@ static int snd_wss_capture_close(struct snd_pcm_substream *substream)
return 0;
}
static void snd_wss_thinkpad_twiddle(struct snd_wss *chip, int on)
{
int tmp;
if (!chip->thinkpad_flag)
return;
outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
tmp = inb(AD1848_THINKPAD_CTL_PORT2);
if (on)
/* turn it on */
tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
else
/* turn it off */
tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
outb(tmp, AD1848_THINKPAD_CTL_PORT2);
}
#ifdef CONFIG_PM
/* lowlevel suspend callback for CS4231 */
......@@ -1436,6 +1484,8 @@ static void snd_wss_suspend(struct snd_wss *chip)
for (reg = 0; reg < 32; reg++)
chip->image[reg] = snd_wss_in(chip, reg);
spin_unlock_irqrestore(&chip->reg_lock, flags);
if (chip->thinkpad_flag)
snd_wss_thinkpad_twiddle(chip, 0);
}
/* lowlevel resume callback for CS4231 */
......@@ -1445,6 +1495,8 @@ static void snd_wss_resume(struct snd_wss *chip)
unsigned long flags;
/* int timeout; */
if (chip->thinkpad_flag)
snd_wss_thinkpad_twiddle(chip, 1);
snd_wss_mce_up(chip);
spin_lock_irqsave(&chip->reg_lock, flags);
for (reg = 0; reg < 32; reg++) {
......@@ -1542,6 +1594,14 @@ const char *snd_wss_chip_id(struct snd_wss *chip)
return "AD1845";
case WSS_HW_OPTI93X:
return "OPTi 93x";
case WSS_HW_AD1847:
return "AD1847";
case WSS_HW_AD1848:
return "AD1848";
case WSS_HW_CS4248:
return "CS4248";
case WSS_HW_CMI8330:
return "CMI8330/C3D";
default:
return "???";
}
......@@ -1704,7 +1764,8 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
struct snd_pcm *pcm;
int err;
if ((err = snd_pcm_new(chip->card, "CS4231", device, 1, 1, &pcm)) < 0)
err = snd_pcm_new(chip->card, "WSS", device, 1, 1, &pcm);
if (err < 0)
return err;
spin_lock_init(&chip->reg_lock);
......@@ -1714,6 +1775,12 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops);
/* temporary */
if (chip->hardware & WSS_HW_AD1848_MASK) {
chip->rate_constraint = snd_wss_xrate;
chip->set_playback_format = snd_wss_playback_format;
chip->set_capture_format = snd_wss_capture_format;
}
/* global setup */
pcm->private_data = chip;
pcm->info_flags = 0;
......@@ -2134,6 +2201,13 @@ int snd_wss_mixer(struct snd_wss *chip)
}
EXPORT_SYMBOL(snd_wss_mixer);
const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction)
{
return direction == SNDRV_PCM_STREAM_PLAYBACK ?
&snd_wss_playback_ops : &snd_wss_capture_ops;
}
EXPORT_SYMBOL(snd_wss_get_pcm_ops);
/*
* INIT part
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment