aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2008-07-31 15:09:32 -0400
committerJaroslav Kysela <perex@perex.cz>2008-08-06 09:39:56 -0400
commitead893c0deeec165524cc8a06e7e739d7d84b4c4 (patch)
tree86881775a9f4e7052eded95747fd8854d043fdda
parent5664daa1c1fa250dd7f6b336278b0402638e8edc (diff)
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: Krzysztof Helt <krzysztof.h1@wp.pl> Reviewed-by: Rene Herman <rene.herman@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r--include/sound/ad1848.h8
-rw-r--r--include/sound/wss.h7
-rw-r--r--sound/isa/Kconfig5
-rw-r--r--sound/isa/ad1848/ad1848.c2
-rw-r--r--sound/isa/ad1848/ad1848_lib.c544
-rw-r--r--sound/isa/cmi8330.c2
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c7
-rw-r--r--sound/isa/sc6000.c4
-rw-r--r--sound/isa/sgalaxy.c5
-rw-r--r--sound/isa/wss/wss_lib.c126
10 files changed, 129 insertions, 581 deletions
diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h
index 03e2abf64a7c..7ff484f55b02 100644
--- a/include/sound/ad1848.h
+++ b/include/sound/ad1848.h
@@ -97,11 +97,6 @@
97#define AD1848_CALIB_IN_PROGRESS 0x20 /* auto calibrate in progress */ 97#define AD1848_CALIB_IN_PROGRESS 0x20 /* auto calibrate in progress */
98#define AD1848_DMA_REQUEST 0x10 /* DMA request in progress */ 98#define AD1848_DMA_REQUEST 0x10 /* DMA request in progress */
99 99
100/* IBM Thinkpad specific stuff */
101#define AD1848_THINKPAD_CTL_PORT1 0x15e8
102#define AD1848_THINKPAD_CTL_PORT2 0x15e9
103#define AD1848_THINKPAD_CS4248_ENABLE_BIT 0x02
104
105/* exported functions */ 100/* exported functions */
106 101
107void snd_ad1848_out(struct snd_wss *chip, unsigned char reg, 102void snd_ad1848_out(struct snd_wss *chip, unsigned char reg,
@@ -113,7 +108,4 @@ int snd_ad1848_create(struct snd_card *card,
113 unsigned short hardware, 108 unsigned short hardware,
114 struct snd_wss **chip); 109 struct snd_wss **chip);
115 110
116int snd_ad1848_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm);
117const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction);
118
119#endif /* __SOUND_AD1848_H */ 111#endif /* __SOUND_AD1848_H */
diff --git a/include/sound/wss.h b/include/sound/wss.h
index c896f6e1f937..fd01f22825cd 100644
--- a/include/sound/wss.h
+++ b/include/sound/wss.h
@@ -71,6 +71,11 @@
71#define WSS_HWSHARE_DMA1 (1<<1) 71#define WSS_HWSHARE_DMA1 (1<<1)
72#define WSS_HWSHARE_DMA2 (1<<2) 72#define WSS_HWSHARE_DMA2 (1<<2)
73 73
74/* IBM Thinkpad specific stuff */
75#define AD1848_THINKPAD_CTL_PORT1 0x15e8
76#define AD1848_THINKPAD_CTL_PORT2 0x15e9
77#define AD1848_THINKPAD_CS4248_ENABLE_BIT 0x02
78
74struct snd_wss { 79struct snd_wss {
75 unsigned long port; /* base i/o port */ 80 unsigned long port; /* base i/o port */
76 struct resource *res_port; 81 struct resource *res_port;
@@ -153,6 +158,8 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm);
153int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer); 158int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer);
154int snd_wss_mixer(struct snd_wss *chip); 159int snd_wss_mixer(struct snd_wss *chip);
155 160
161const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction);
162
156int snd_cs4236_create(struct snd_card *card, 163int snd_cs4236_create(struct snd_card *card,
157 unsigned long port, 164 unsigned long port,
158 unsigned long cport, 165 unsigned long cport,
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 87055568ccd4..cca11d5dc33b 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -1,12 +1,13 @@
1# ALSA ISA drivers 1# ALSA ISA drivers
2 2
3config SND_AD1848_LIB 3config SND_WSS_LIB
4 tristate 4 tristate
5 select SND_PCM 5 select SND_PCM
6 6
7config SND_WSS_LIB 7config SND_AD1848_LIB
8 tristate 8 tristate
9 select SND_PCM 9 select SND_PCM
10 select SND_WSS_LIB
10 11
11config SND_SB_COMMON 12config SND_SB_COMMON
12 tristate 13 tristate
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index d5a96631587c..17970c2f27e7 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -102,7 +102,7 @@ static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n)
102 102
103 card->private_data = chip; 103 card->private_data = chip;
104 104
105 error = snd_ad1848_pcm(chip, 0, &pcm); 105 error = snd_wss_pcm(chip, 0, &pcm);
106 if (error < 0) 106 if (error < 0)
107 goto out; 107 goto out;
108 108
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
index 5de046014337..aa803d38a8ad 100644
--- a/sound/isa/ad1848/ad1848_lib.c
+++ b/sound/isa/ad1848/ad1848_lib.c
@@ -46,34 +46,6 @@ MODULE_LICENSE("GPL");
46 * Some variables 46 * Some variables
47 */ 47 */
48 48
49static unsigned char freq_bits[14] = {
50 /* 5510 */ 0x00 | AD1848_XTAL2,
51 /* 6620 */ 0x0E | AD1848_XTAL2,
52 /* 8000 */ 0x00 | AD1848_XTAL1,
53 /* 9600 */ 0x0E | AD1848_XTAL1,
54 /* 11025 */ 0x02 | AD1848_XTAL2,
55 /* 16000 */ 0x02 | AD1848_XTAL1,
56 /* 18900 */ 0x04 | AD1848_XTAL2,
57 /* 22050 */ 0x06 | AD1848_XTAL2,
58 /* 27042 */ 0x04 | AD1848_XTAL1,
59 /* 32000 */ 0x06 | AD1848_XTAL1,
60 /* 33075 */ 0x0C | AD1848_XTAL2,
61 /* 37800 */ 0x08 | AD1848_XTAL2,
62 /* 44100 */ 0x0A | AD1848_XTAL2,
63 /* 48000 */ 0x0C | AD1848_XTAL1
64};
65
66static unsigned int rates[14] = {
67 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050,
68 27042, 32000, 33075, 37800, 44100, 48000
69};
70
71static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
72 .count = ARRAY_SIZE(rates),
73 .list = rates,
74 .mask = 0,
75};
76
77static unsigned char snd_ad1848_original_image[16] = 49static unsigned char snd_ad1848_original_image[16] =
78{ 50{
79 0x00, /* 00 - lic */ 51 0x00, /* 00 - lic */
@@ -128,15 +100,6 @@ void snd_ad1848_out(struct snd_wss *chip,
128 100
129EXPORT_SYMBOL(snd_ad1848_out); 101EXPORT_SYMBOL(snd_ad1848_out);
130 102
131static void snd_ad1848_dout(struct snd_wss *chip,
132 unsigned char reg, unsigned char value)
133{
134 snd_ad1848_wait(chip);
135 outb(chip->mce_bit | reg, chip->port + CS4231P(REGSEL));
136 outb(value, chip->port + CS4231P(REG));
137 mb();
138}
139
140static unsigned char snd_ad1848_in(struct snd_wss *chip, unsigned char reg) 103static unsigned char snd_ad1848_in(struct snd_wss *chip, unsigned char reg)
141{ 104{
142 snd_ad1848_wait(chip); 105 snd_ad1848_wait(chip);
@@ -261,315 +224,6 @@ static void snd_ad1848_mce_down(struct snd_wss *chip)
261 inb(chip->port + CS4231P(REGSEL))); 224 inb(chip->port + CS4231P(REGSEL)));
262} 225}
263 226
264static unsigned int snd_ad1848_get_count(unsigned char format,
265 unsigned int size)
266{
267 switch (format & 0xe0) {
268 case AD1848_LINEAR_16:
269 size >>= 1;
270 break;
271 }
272 if (format & AD1848_STEREO)
273 size >>= 1;
274 return size;
275}
276
277static int snd_ad1848_trigger(struct snd_wss *chip, unsigned char what,
278 int channel, int cmd)
279{
280 int result = 0;
281
282#if 0
283 printk("codec trigger!!! - what = %i, enable = %i, status = 0x%x\n", what, enable, inb(AD1848P(card, STATUS)));
284#endif
285 spin_lock(&chip->reg_lock);
286 if (cmd == SNDRV_PCM_TRIGGER_START) {
287 if (chip->image[AD1848_IFACE_CTRL] & what) {
288 spin_unlock(&chip->reg_lock);
289 return 0;
290 }
291 snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL] |= what);
292 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
293 if (!(chip->image[AD1848_IFACE_CTRL] & what)) {
294 spin_unlock(&chip->reg_lock);
295 return 0;
296 }
297 snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL] &= ~what);
298 } else {
299 result = -EINVAL;
300 }
301 spin_unlock(&chip->reg_lock);
302 return result;
303}
304
305/*
306 * CODEC I/O
307 */
308
309static unsigned char snd_ad1848_get_rate(unsigned int rate)
310{
311 int i;
312
313 for (i = 0; i < ARRAY_SIZE(rates); i++)
314 if (rate == rates[i])
315 return freq_bits[i];
316 snd_BUG();
317 return freq_bits[ARRAY_SIZE(rates) - 1];
318}
319
320static int snd_ad1848_ioctl(struct snd_pcm_substream *substream,
321 unsigned int cmd, void *arg)
322{
323 return snd_pcm_lib_ioctl(substream, cmd, arg);
324}
325
326static unsigned char snd_ad1848_get_format(int format, int channels)
327{
328 unsigned char rformat;
329
330 rformat = AD1848_LINEAR_8;
331 switch (format) {
332 case SNDRV_PCM_FORMAT_A_LAW: rformat = AD1848_ALAW_8; break;
333 case SNDRV_PCM_FORMAT_MU_LAW: rformat = AD1848_ULAW_8; break;
334 case SNDRV_PCM_FORMAT_S16_LE: rformat = AD1848_LINEAR_16; break;
335 }
336 if (channels > 1)
337 rformat |= AD1848_STEREO;
338#if 0
339 snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
340#endif
341 return rformat;
342}
343
344static void snd_ad1848_calibrate_mute(struct snd_wss *chip, int mute)
345{
346 unsigned long flags;
347
348 mute = mute ? 1 : 0;
349 spin_lock_irqsave(&chip->reg_lock, flags);
350 if (chip->calibrate_mute == mute) {
351 spin_unlock_irqrestore(&chip->reg_lock, flags);
352 return;
353 }
354 if (!mute) {
355 snd_ad1848_dout(chip, AD1848_LEFT_INPUT, chip->image[AD1848_LEFT_INPUT]);
356 snd_ad1848_dout(chip, AD1848_RIGHT_INPUT, chip->image[AD1848_RIGHT_INPUT]);
357 }
358 snd_ad1848_dout(chip, AD1848_AUX1_LEFT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX1_LEFT_INPUT]);
359 snd_ad1848_dout(chip, AD1848_AUX1_RIGHT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX1_RIGHT_INPUT]);
360 snd_ad1848_dout(chip, AD1848_AUX2_LEFT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX2_LEFT_INPUT]);
361 snd_ad1848_dout(chip, AD1848_AUX2_RIGHT_INPUT, mute ? 0x80 : chip->image[AD1848_AUX2_RIGHT_INPUT]);
362 snd_ad1848_dout(chip, AD1848_LEFT_OUTPUT, mute ? 0x80 : chip->image[AD1848_LEFT_OUTPUT]);
363 snd_ad1848_dout(chip, AD1848_RIGHT_OUTPUT, mute ? 0x80 : chip->image[AD1848_RIGHT_OUTPUT]);
364 chip->calibrate_mute = mute;
365 spin_unlock_irqrestore(&chip->reg_lock, flags);
366}
367
368static void snd_ad1848_set_data_format(struct snd_wss *chip,
369 struct snd_pcm_hw_params *hw_params)
370{
371 if (hw_params == NULL) {
372 chip->image[AD1848_DATA_FORMAT] = 0x20;
373 } else {
374 chip->image[AD1848_DATA_FORMAT] =
375 snd_ad1848_get_format(params_format(hw_params), params_channels(hw_params)) |
376 snd_ad1848_get_rate(params_rate(hw_params));
377 }
378 // snd_printk(">>> pmode = 0x%x, dfr = 0x%x\n", pstr->mode, chip->image[AD1848_DATA_FORMAT]);
379}
380
381static int snd_ad1848_open(struct snd_wss *chip, unsigned int mode)
382{
383 unsigned long flags;
384
385 if (chip->mode & WSS_MODE_OPEN)
386 return -EAGAIN;
387
388 snd_ad1848_mce_down(chip);
389
390#ifdef SNDRV_DEBUG_MCE
391 snd_printk("open: (1)\n");
392#endif
393 snd_ad1848_mce_up(chip);
394 spin_lock_irqsave(&chip->reg_lock, flags);
395 chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO |
396 AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO |
397 AD1848_CALIB_MODE);
398 chip->image[AD1848_IFACE_CTRL] |= AD1848_AUTOCALIB;
399 snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]);
400 spin_unlock_irqrestore(&chip->reg_lock, flags);
401 snd_ad1848_mce_down(chip);
402
403#ifdef SNDRV_DEBUG_MCE
404 snd_printk("open: (2)\n");
405#endif
406
407 snd_ad1848_set_data_format(chip, NULL);
408
409 snd_ad1848_mce_up(chip);
410 spin_lock_irqsave(&chip->reg_lock, flags);
411 snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]);
412 spin_unlock_irqrestore(&chip->reg_lock, flags);
413 snd_ad1848_mce_down(chip);
414
415#ifdef SNDRV_DEBUG_MCE
416 snd_printk("open: (3)\n");
417#endif
418
419 /* ok. now enable and ack CODEC IRQ */
420 spin_lock_irqsave(&chip->reg_lock, flags);
421 outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */
422 outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */
423 chip->image[AD1848_PIN_CTRL] |= AD1848_IRQ_ENABLE;
424 snd_ad1848_out(chip, AD1848_PIN_CTRL, chip->image[AD1848_PIN_CTRL]);
425 spin_unlock_irqrestore(&chip->reg_lock, flags);
426
427 chip->mode = mode;
428
429 return 0;
430}
431
432static void snd_ad1848_close(struct snd_wss *chip)
433{
434 unsigned long flags;
435
436 if (!chip->mode)
437 return;
438 /* disable IRQ */
439 spin_lock_irqsave(&chip->reg_lock, flags);
440 outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */
441 outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */
442 chip->image[AD1848_PIN_CTRL] &= ~AD1848_IRQ_ENABLE;
443 snd_ad1848_out(chip, AD1848_PIN_CTRL, chip->image[AD1848_PIN_CTRL]);
444 spin_unlock_irqrestore(&chip->reg_lock, flags);
445
446 /* now disable capture & playback */
447
448 snd_ad1848_mce_up(chip);
449 spin_lock_irqsave(&chip->reg_lock, flags);
450 chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO |
451 AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO);
452 snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]);
453 spin_unlock_irqrestore(&chip->reg_lock, flags);
454 snd_ad1848_mce_down(chip);
455
456 /* clear IRQ again */
457 spin_lock_irqsave(&chip->reg_lock, flags);
458 outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */
459 outb(0, chip->port + CS4231P(STATUS)); /* clear IRQ */
460 spin_unlock_irqrestore(&chip->reg_lock, flags);
461
462 chip->mode = 0;
463}
464
465/*
466 * ok.. exported functions..
467 */
468
469static int snd_ad1848_playback_trigger(struct snd_pcm_substream *substream,
470 int cmd)
471{
472 struct snd_wss *chip = snd_pcm_substream_chip(substream);
473 return snd_ad1848_trigger(chip, AD1848_PLAYBACK_ENABLE, SNDRV_PCM_STREAM_PLAYBACK, cmd);
474}
475
476static int snd_ad1848_capture_trigger(struct snd_pcm_substream *substream,
477 int cmd)
478{
479 struct snd_wss *chip = snd_pcm_substream_chip(substream);
480 return snd_ad1848_trigger(chip, AD1848_CAPTURE_ENABLE, SNDRV_PCM_STREAM_CAPTURE, cmd);
481}
482
483static int snd_ad1848_playback_hw_params(struct snd_pcm_substream *substream,
484 struct snd_pcm_hw_params *hw_params)
485{
486 struct snd_wss *chip = snd_pcm_substream_chip(substream);
487 unsigned long flags;
488 int err;
489
490 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
491 return err;
492 snd_ad1848_calibrate_mute(chip, 1);
493 snd_ad1848_set_data_format(chip, hw_params);
494 snd_ad1848_mce_up(chip);
495 spin_lock_irqsave(&chip->reg_lock, flags);
496 snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]);
497 spin_unlock_irqrestore(&chip->reg_lock, flags);
498 snd_ad1848_mce_down(chip);
499 snd_ad1848_calibrate_mute(chip, 0);
500 return 0;
501}
502
503static int snd_ad1848_playback_hw_free(struct snd_pcm_substream *substream)
504{
505 return snd_pcm_lib_free_pages(substream);
506}
507
508static int snd_ad1848_playback_prepare(struct snd_pcm_substream *substream)
509{
510 struct snd_wss *chip = snd_pcm_substream_chip(substream);
511 struct snd_pcm_runtime *runtime = substream->runtime;
512 unsigned long flags;
513 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
514 unsigned int count = snd_pcm_lib_period_bytes(substream);
515
516 chip->p_dma_size = size;
517 chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO);
518 snd_dma_program(chip->dma1, runtime->dma_addr, size,
519 DMA_MODE_WRITE | DMA_AUTOINIT);
520 count = snd_ad1848_get_count(chip->image[AD1848_DATA_FORMAT], count) - 1;
521 spin_lock_irqsave(&chip->reg_lock, flags);
522 snd_ad1848_out(chip, AD1848_DATA_LWR_CNT, (unsigned char) count);
523 snd_ad1848_out(chip, AD1848_DATA_UPR_CNT, (unsigned char) (count >> 8));
524 spin_unlock_irqrestore(&chip->reg_lock, flags);
525 return 0;
526}
527
528static int snd_ad1848_capture_hw_params(struct snd_pcm_substream *substream,
529 struct snd_pcm_hw_params *hw_params)
530{
531 struct snd_wss *chip = snd_pcm_substream_chip(substream);
532 unsigned long flags;
533 int err;
534
535 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
536 return err;
537 snd_ad1848_calibrate_mute(chip, 1);
538 snd_ad1848_set_data_format(chip, hw_params);
539 snd_ad1848_mce_up(chip);
540 spin_lock_irqsave(&chip->reg_lock, flags);
541 snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]);
542 spin_unlock_irqrestore(&chip->reg_lock, flags);
543 snd_ad1848_mce_down(chip);
544 snd_ad1848_calibrate_mute(chip, 0);
545 return 0;
546}
547
548static int snd_ad1848_capture_hw_free(struct snd_pcm_substream *substream)
549{
550 return snd_pcm_lib_free_pages(substream);
551}
552
553static int snd_ad1848_capture_prepare(struct snd_pcm_substream *substream)
554{
555 struct snd_wss *chip = snd_pcm_substream_chip(substream);
556 struct snd_pcm_runtime *runtime = substream->runtime;
557 unsigned long flags;
558 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
559 unsigned int count = snd_pcm_lib_period_bytes(substream);
560
561 chip->c_dma_size = size;
562 chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO);
563 snd_dma_program(chip->dma2, runtime->dma_addr, size,
564 DMA_MODE_READ | DMA_AUTOINIT);
565 count = snd_ad1848_get_count(chip->image[AD1848_DATA_FORMAT], count) - 1;
566 spin_lock_irqsave(&chip->reg_lock, flags);
567 snd_ad1848_out(chip, AD1848_DATA_LWR_CNT, (unsigned char) count);
568 snd_ad1848_out(chip, AD1848_DATA_UPR_CNT, (unsigned char) (count >> 8));
569 spin_unlock_irqrestore(&chip->reg_lock, flags);
570 return 0;
571}
572
573static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id) 227static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id)
574{ 228{
575 struct snd_wss *chip = dev_id; 229 struct snd_wss *chip = dev_id;
@@ -582,28 +236,6 @@ static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id)
582 return IRQ_HANDLED; 236 return IRQ_HANDLED;
583} 237}
584 238
585static snd_pcm_uframes_t snd_ad1848_playback_pointer(struct snd_pcm_substream *substream)
586{
587 struct snd_wss *chip = snd_pcm_substream_chip(substream);
588 size_t ptr;
589
590 if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_PLAYBACK_ENABLE))
591 return 0;
592 ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size);
593 return bytes_to_frames(substream->runtime, ptr);
594}
595
596static snd_pcm_uframes_t snd_ad1848_capture_pointer(struct snd_pcm_substream *substream)
597{
598 struct snd_wss *chip = snd_pcm_substream_chip(substream);
599 size_t ptr;
600
601 if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_CAPTURE_ENABLE))
602 return 0;
603 ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);
604 return bytes_to_frames(substream->runtime, ptr);
605}
606
607/* 239/*
608 240
609 */ 241 */
@@ -728,6 +360,16 @@ static int snd_ad1848_probe(struct snd_wss *chip)
728 snd_ad1848_out(chip, i, *ptr++); 360 snd_ad1848_out(chip, i, *ptr++);
729 spin_unlock_irqrestore(&chip->reg_lock, flags); 361 spin_unlock_irqrestore(&chip->reg_lock, flags);
730 snd_ad1848_mce_up(chip); 362 snd_ad1848_mce_up(chip);
363 /* init needed for WSS pcm */
364 spin_lock_irqsave(&chip->reg_lock, flags);
365 chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE |
366 AD1848_PLAYBACK_PIO |
367 AD1848_CAPTURE_ENABLE |
368 AD1848_CAPTURE_PIO |
369 AD1848_CALIB_MODE);
370 chip->image[AD1848_IFACE_CTRL] |= AD1848_AUTOCALIB;
371 snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]);
372 spin_unlock_irqrestore(&chip->reg_lock, flags);
731 snd_ad1848_mce_down(chip); 373 snd_ad1848_mce_down(chip);
732 return 0; /* all things are ok.. */ 374 return 0; /* all things are ok.. */
733} 375}
@@ -736,102 +378,6 @@ static int snd_ad1848_probe(struct snd_wss *chip)
736 378
737 */ 379 */
738 380
739static struct snd_pcm_hardware snd_ad1848_playback =
740{
741 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
742 SNDRV_PCM_INFO_MMAP_VALID),
743 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
744 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE),
745 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
746 .rate_min = 5510,
747 .rate_max = 48000,
748 .channels_min = 1,
749 .channels_max = 2,
750 .buffer_bytes_max = (128*1024),
751 .period_bytes_min = 64,
752 .period_bytes_max = (128*1024),
753 .periods_min = 1,
754 .periods_max = 1024,
755 .fifo_size = 0,
756};
757
758static struct snd_pcm_hardware snd_ad1848_capture =
759{
760 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
761 SNDRV_PCM_INFO_MMAP_VALID),
762 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
763 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE),
764 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
765 .rate_min = 5510,
766 .rate_max = 48000,
767 .channels_min = 1,
768 .channels_max = 2,
769 .buffer_bytes_max = (128*1024),
770 .period_bytes_min = 64,
771 .period_bytes_max = (128*1024),
772 .periods_min = 1,
773 .periods_max = 1024,
774 .fifo_size = 0,
775};
776
777/*
778
779 */
780
781static int snd_ad1848_playback_open(struct snd_pcm_substream *substream)
782{
783 struct snd_wss *chip = snd_pcm_substream_chip(substream);
784 struct snd_pcm_runtime *runtime = substream->runtime;
785 int err;
786
787 err = snd_ad1848_open(chip, WSS_MODE_PLAY);
788 if (err < 0)
789 return err;
790 chip->playback_substream = substream;
791 runtime->hw = snd_ad1848_playback;
792 snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
793 snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
794 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
795 return 0;
796}
797
798static int snd_ad1848_capture_open(struct snd_pcm_substream *substream)
799{
800 struct snd_wss *chip = snd_pcm_substream_chip(substream);
801 struct snd_pcm_runtime *runtime = substream->runtime;
802 int err;
803
804 err = snd_ad1848_open(chip, WSS_MODE_RECORD);
805 if (err < 0)
806 return err;
807 chip->capture_substream = substream;
808 runtime->hw = snd_ad1848_capture;
809 snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
810 snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
811 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
812 return 0;
813}
814
815static int snd_ad1848_playback_close(struct snd_pcm_substream *substream)
816{
817 struct snd_wss *chip = snd_pcm_substream_chip(substream);
818
819 chip->mode &= ~WSS_MODE_PLAY;
820 chip->playback_substream = NULL;
821 snd_ad1848_close(chip);
822 return 0;
823}
824
825static int snd_ad1848_capture_close(struct snd_pcm_substream *substream)
826{
827 struct snd_wss *chip = snd_pcm_substream_chip(substream);
828
829 chip->mode &= ~WSS_MODE_RECORD;
830 chip->capture_substream = NULL;
831 snd_ad1848_close(chip);
832 return 0;
833}
834
835static int snd_ad1848_free(struct snd_wss *chip) 381static int snd_ad1848_free(struct snd_wss *chip)
836{ 382{
837 release_and_free_resource(chip->res_port); 383 release_and_free_resource(chip->res_port);
@@ -851,17 +397,6 @@ static int snd_ad1848_dev_free(struct snd_device *device)
851 return snd_ad1848_free(chip); 397 return snd_ad1848_free(chip);
852} 398}
853 399
854static const char *snd_ad1848_chip_id(struct snd_wss *chip)
855{
856 switch (chip->hardware) {
857 case AD1848_HW_AD1847: return "AD1847";
858 case AD1848_HW_AD1848: return "AD1848";
859 case AD1848_HW_CS4248: return "CS4248";
860 case AD1848_HW_CMI8330: return "CMI8330/C3D";
861 default: return "???";
862 }
863}
864
865int snd_ad1848_create(struct snd_card *card, 400int snd_ad1848_create(struct snd_card *card,
866 unsigned long port, 401 unsigned long port,
867 int irq, int dma, 402 int irq, int dma,
@@ -935,65 +470,6 @@ int snd_ad1848_create(struct snd_card *card,
935 470
936EXPORT_SYMBOL(snd_ad1848_create); 471EXPORT_SYMBOL(snd_ad1848_create);
937 472
938static struct snd_pcm_ops snd_ad1848_playback_ops = {
939 .open = snd_ad1848_playback_open,
940 .close = snd_ad1848_playback_close,
941 .ioctl = snd_ad1848_ioctl,
942 .hw_params = snd_ad1848_playback_hw_params,
943 .hw_free = snd_ad1848_playback_hw_free,
944 .prepare = snd_ad1848_playback_prepare,
945 .trigger = snd_ad1848_playback_trigger,
946 .pointer = snd_ad1848_playback_pointer,
947};
948
949static struct snd_pcm_ops snd_ad1848_capture_ops = {
950 .open = snd_ad1848_capture_open,
951 .close = snd_ad1848_capture_close,
952 .ioctl = snd_ad1848_ioctl,
953 .hw_params = snd_ad1848_capture_hw_params,
954 .hw_free = snd_ad1848_capture_hw_free,
955 .prepare = snd_ad1848_capture_prepare,
956 .trigger = snd_ad1848_capture_trigger,
957 .pointer = snd_ad1848_capture_pointer,
958};
959
960int snd_ad1848_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
961{
962 struct snd_pcm *pcm;
963 int err;
964
965 if ((err = snd_pcm_new(chip->card, "AD1848", device, 1, 1, &pcm)) < 0)
966 return err;
967
968 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ad1848_playback_ops);
969 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ad1848_capture_ops);
970
971 pcm->private_data = chip;
972 pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
973 strcpy(pcm->name, snd_ad1848_chip_id(chip));
974
975 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
976 snd_dma_isa_data(),
977 64 * 1024,
978 chip->dma1 > 3 ?
979 128 * 1024 : 64 * 1024);
980
981 chip->pcm = pcm;
982 if (rpcm)
983 *rpcm = pcm;
984 return 0;
985}
986
987EXPORT_SYMBOL(snd_ad1848_pcm);
988
989const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction)
990{
991 return direction == SNDRV_PCM_STREAM_PLAYBACK ?
992 &snd_ad1848_playback_ops : &snd_ad1848_capture_ops;
993}
994
995EXPORT_SYMBOL(snd_ad1848_get_pcm_ops);
996
997/* 473/*
998 * INIT part 474 * INIT part
999 */ 475 */
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index ca6f602f15c2..6f7e8bb6ae60 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -413,7 +413,7 @@ static int __devinit snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *
413 chip->streams[CMI_SB_STREAM].private_data = chip->sb; 413 chip->streams[CMI_SB_STREAM].private_data = chip->sb;
414 414
415 /* AD1848 */ 415 /* AD1848 */
416 ops = snd_ad1848_get_pcm_ops(CMI_AD_STREAM); 416 ops = snd_wss_get_pcm_ops(CMI_AD_STREAM);
417 chip->streams[CMI_AD_STREAM].ops = *ops; 417 chip->streams[CMI_AD_STREAM].ops = *ops;
418 chip->streams[CMI_AD_STREAM].open = ops->open; 418 chip->streams[CMI_AD_STREAM].open = ops->open;
419 chip->streams[CMI_AD_STREAM].ops.open = cmi_open_callbacks[CMI_AD_STREAM]; 419 chip->streams[CMI_AD_STREAM].ops.open = cmi_open_callbacks[CMI_AD_STREAM];
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 4f172a219244..561d4b3ed098 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -754,18 +754,15 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
754#ifdef OPTi93X 754#ifdef OPTi93X
755 chip->codec = codec; 755 chip->codec = codec;
756#endif 756#endif
757 error = snd_wss_pcm(codec, 0, &pcm);
758 if (error < 0)
759 return error;
760#else 757#else
761 error = snd_ad1848_create(card, chip->wss_base + 4, chip->irq, 758 error = snd_ad1848_create(card, chip->wss_base + 4, chip->irq,
762 chip->dma1, WSS_HW_DETECT, &codec); 759 chip->dma1, WSS_HW_DETECT, &codec);
763 if (error < 0) 760 if (error < 0)
764 return error; 761 return error;
765 error = snd_ad1848_pcm(codec, 0, &pcm); 762#endif
763 error = snd_wss_pcm(codec, 0, &pcm);
766 if (error < 0) 764 if (error < 0)
767 return error; 765 return error;
768#endif
769 error = snd_wss_mixer(codec); 766 error = snd_wss_mixer(codec);
770 if (error < 0) 767 if (error < 0)
771 return error; 768 return error;
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c
index ef98fe7dced8..2f89ecb95ded 100644
--- a/sound/isa/sc6000.c
+++ b/sound/isa/sc6000.c
@@ -554,10 +554,10 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
554 goto err_unmap2; 554 goto err_unmap2;
555 card->private_data = chip; 555 card->private_data = chip;
556 556
557 err = snd_ad1848_pcm(chip, 0, NULL); 557 err = snd_wss_pcm(chip, 0, NULL);
558 if (err < 0) { 558 if (err < 0) {
559 snd_printk(KERN_ERR PFX 559 snd_printk(KERN_ERR PFX
560 "error creating new ad1848 PCM device\n"); 560 "error creating new WSS PCM device\n");
561 goto err_unmap2; 561 goto err_unmap2;
562 } 562 }
563 err = snd_wss_mixer(chip); 563 err = snd_wss_mixer(chip);
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
index e4f06de3480c..b43d6678ba20 100644
--- a/sound/isa/sgalaxy.c
+++ b/sound/isa/sgalaxy.c
@@ -273,8 +273,9 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev)
273 goto _err; 273 goto _err;
274 card->private_data = chip; 274 card->private_data = chip;
275 275
276 if ((err = snd_ad1848_pcm(chip, 0, NULL)) < 0) { 276 err = snd_wss_pcm(chip, 0, NULL);
277 snd_printdd(PFX "error creating new ad1848 PCM device\n"); 277 if (err < 0) {
278 snd_printdd(PFX "error creating new WSS PCM device\n");
278 goto _err; 279 goto _err;
279 } 280 }
280 err = snd_wss_mixer(chip); 281 err = snd_wss_mixer(chip);
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
index 1688f07a14b0..57d1e8ee6bbb 100644
--- a/sound/isa/wss/wss_lib.c
+++ b/sound/isa/wss/wss_lib.c
@@ -380,7 +380,7 @@ static void snd_wss_busy_wait(struct snd_wss *chip)
380 for (timeout = 5; timeout > 0; timeout--) 380 for (timeout = 5; timeout > 0; timeout--)
381 wss_inb(chip, CS4231P(REGSEL)); 381 wss_inb(chip, CS4231P(REGSEL));
382 /* end of cleanup sequence */ 382 /* end of cleanup sequence */
383 for (timeout = 250; 383 for (timeout = 25000;
384 timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT); 384 timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
385 timeout--) 385 timeout--)
386 udelay(10); 386 udelay(10);
@@ -413,6 +413,7 @@ void snd_wss_mce_down(struct snd_wss *chip)
413 unsigned long flags; 413 unsigned long flags;
414 unsigned long end_time; 414 unsigned long end_time;
415 int timeout; 415 int timeout;
416 int hw_mask = WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK | WSS_HW_AD1848;
416 417
417 snd_wss_busy_wait(chip); 418 snd_wss_busy_wait(chip);
418 419
@@ -427,10 +428,8 @@ void snd_wss_mce_down(struct snd_wss *chip)
427 spin_unlock_irqrestore(&chip->reg_lock, flags); 428 spin_unlock_irqrestore(&chip->reg_lock, flags);
428 if (timeout == 0x80) 429 if (timeout == 0x80)
429 snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port); 430 snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
430 if ((timeout & CS4231_MCE) == 0 || 431 if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask))
431 !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) {
432 return; 432 return;
433 }
434 433
435 /* 434 /*
436 * Wait for (possible -- during init auto-calibration may not be set) 435 * 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)
601 mute ? 0x80 : chip->image[CS4231_LEFT_OUTPUT]); 600 mute ? 0x80 : chip->image[CS4231_LEFT_OUTPUT]);
602 snd_wss_dout(chip, CS4231_RIGHT_OUTPUT, 601 snd_wss_dout(chip, CS4231_RIGHT_OUTPUT,
603 mute ? 0x80 : chip->image[CS4231_RIGHT_OUTPUT]); 602 mute ? 0x80 : chip->image[CS4231_RIGHT_OUTPUT]);
604 snd_wss_dout(chip, CS4231_LEFT_LINE_IN, 603 if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
605 mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]); 604 snd_wss_dout(chip, CS4231_LEFT_LINE_IN,
606 snd_wss_dout(chip, CS4231_RIGHT_LINE_IN, 605 mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]);
607 mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]); 606 snd_wss_dout(chip, CS4231_RIGHT_LINE_IN,
608 snd_wss_dout(chip, CS4231_MONO_CTRL, 607 mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]);
609 mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]); 608 snd_wss_dout(chip, CS4231_MONO_CTRL,
609 mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]);
610 }
610 if (chip->hardware == WSS_HW_INTERWAVE) { 611 if (chip->hardware == WSS_HW_INTERWAVE) {
611 snd_wss_dout(chip, CS4231_LEFT_MIC_INPUT, 612 snd_wss_dout(chip, CS4231_LEFT_MIC_INPUT,
612 mute ? 0x80 : chip->image[CS4231_LEFT_MIC_INPUT]); 613 mute ? 0x80 : chip->image[CS4231_LEFT_MIC_INPUT]);
@@ -706,7 +707,10 @@ static void snd_wss_capture_format(struct snd_wss *chip,
706 snd_wss_mce_up(chip); 707 snd_wss_mce_up(chip);
707 spin_lock_irqsave(&chip->reg_lock, flags); 708 spin_lock_irqsave(&chip->reg_lock, flags);
708 } 709 }
709 snd_wss_out(chip, CS4231_REC_FORMAT, cdfr); 710 if (chip->hardware & WSS_HW_AD1848_MASK)
711 snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr);
712 else
713 snd_wss_out(chip, CS4231_REC_FORMAT, cdfr);
710 spin_unlock_irqrestore(&chip->reg_lock, flags); 714 spin_unlock_irqrestore(&chip->reg_lock, flags);
711 snd_wss_mce_down(chip); 715 snd_wss_mce_down(chip);
712 } 716 }
@@ -818,7 +822,9 @@ static void snd_wss_init(struct snd_wss *chip)
818 822
819 snd_wss_mce_up(chip); 823 snd_wss_mce_up(chip);
820 spin_lock_irqsave(&chip->reg_lock, flags); 824 spin_lock_irqsave(&chip->reg_lock, flags);
821 snd_wss_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT]); 825 if (!(chip->hardware & WSS_HW_AD1848_MASK))
826 snd_wss_out(chip, CS4231_REC_FORMAT,
827 chip->image[CS4231_REC_FORMAT]);
822 spin_unlock_irqrestore(&chip->reg_lock, flags); 828 spin_unlock_irqrestore(&chip->reg_lock, flags);
823 snd_wss_mce_down(chip); 829 snd_wss_mce_down(chip);
824 830
@@ -844,20 +850,24 @@ static int snd_wss_open(struct snd_wss *chip, unsigned int mode)
844 } 850 }
845 /* ok. now enable and ack CODEC IRQ */ 851 /* ok. now enable and ack CODEC IRQ */
846 spin_lock_irqsave(&chip->reg_lock, flags); 852 spin_lock_irqsave(&chip->reg_lock, flags);
847 snd_wss_out(chip, CS4231_IRQ_STATUS, 853 if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
848 CS4231_PLAYBACK_IRQ | 854 snd_wss_out(chip, CS4231_IRQ_STATUS,
849 CS4231_RECORD_IRQ | 855 CS4231_PLAYBACK_IRQ |
850 CS4231_TIMER_IRQ); 856 CS4231_RECORD_IRQ |
851 snd_wss_out(chip, CS4231_IRQ_STATUS, 0); 857 CS4231_TIMER_IRQ);
858 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
859 }
852 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ 860 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
853 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ 861 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
854 chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE; 862 chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE;
855 snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]); 863 snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
856 snd_wss_out(chip, CS4231_IRQ_STATUS, 864 if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
857 CS4231_PLAYBACK_IRQ | 865 snd_wss_out(chip, CS4231_IRQ_STATUS,
858 CS4231_RECORD_IRQ | 866 CS4231_PLAYBACK_IRQ |
859 CS4231_TIMER_IRQ); 867 CS4231_RECORD_IRQ |
860 snd_wss_out(chip, CS4231_IRQ_STATUS, 0); 868 CS4231_TIMER_IRQ);
869 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
870 }
861 spin_unlock_irqrestore(&chip->reg_lock, flags); 871 spin_unlock_irqrestore(&chip->reg_lock, flags);
862 872
863 chip->mode = mode; 873 chip->mode = mode;
@@ -879,7 +889,8 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode)
879 889
880 /* disable IRQ */ 890 /* disable IRQ */
881 spin_lock_irqsave(&chip->reg_lock, flags); 891 spin_lock_irqsave(&chip->reg_lock, flags);
882 snd_wss_out(chip, CS4231_IRQ_STATUS, 0); 892 if (!(chip->hardware & WSS_HW_AD1848_MASK))
893 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
883 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ 894 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
884 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ 895 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
885 chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE; 896 chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE;
@@ -902,7 +913,8 @@ static void snd_wss_close(struct snd_wss *chip, unsigned int mode)
902 } 913 }
903 914
904 /* clear IRQ again */ 915 /* clear IRQ again */
905 snd_wss_out(chip, CS4231_IRQ_STATUS, 0); 916 if (!(chip->hardware & WSS_HW_AD1848_MASK))
917 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
906 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ 918 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
907 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */ 919 wss_outb(chip, CS4231P(STATUS), 0); /* clear IRQ */
908 spin_unlock_irqrestore(&chip->reg_lock, flags); 920 spin_unlock_irqrestore(&chip->reg_lock, flags);
@@ -1023,7 +1035,13 @@ static int snd_wss_capture_prepare(struct snd_pcm_substream *substream)
1023 chip->c_dma_size = size; 1035 chip->c_dma_size = size;
1024 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); 1036 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
1025 snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT); 1037 snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
1026 count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT], count) - 1; 1038 if (chip->hardware & WSS_HW_AD1848_MASK)
1039 count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT],
1040 count);
1041 else
1042 count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT],
1043 count);
1044 count--;
1027 if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) { 1045 if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) {
1028 snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count); 1046 snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
1029 snd_wss_out(chip, CS4231_PLY_UPR_CNT, 1047 snd_wss_out(chip, CS4231_PLY_UPR_CNT,
@@ -1341,6 +1359,11 @@ static int snd_wss_playback_open(struct snd_pcm_substream *substream)
1341 1359
1342 runtime->hw = snd_wss_playback; 1360 runtime->hw = snd_wss_playback;
1343 1361
1362 /* hardware limitation of older chipsets */
1363 if (chip->hardware & WSS_HW_AD1848_MASK)
1364 runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
1365 SNDRV_PCM_FMTBIT_S16_BE);
1366
1344 /* hardware bug in InterWave chipset */ 1367 /* hardware bug in InterWave chipset */
1345 if (chip->hardware == WSS_HW_INTERWAVE && chip->dma1 > 3) 1368 if (chip->hardware == WSS_HW_INTERWAVE && chip->dma1 > 3)
1346 runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW; 1369 runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW;
@@ -1379,6 +1402,11 @@ static int snd_wss_capture_open(struct snd_pcm_substream *substream)
1379 1402
1380 runtime->hw = snd_wss_capture; 1403 runtime->hw = snd_wss_capture;
1381 1404
1405 /* hardware limitation of older chipsets */
1406 if (chip->hardware & WSS_HW_AD1848_MASK)
1407 runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
1408 SNDRV_PCM_FMTBIT_S16_BE);
1409
1382 /* hardware limitation of cheap chips */ 1410 /* hardware limitation of cheap chips */
1383 if (chip->hardware == WSS_HW_CS4235 || 1411 if (chip->hardware == WSS_HW_CS4235 ||
1384 chip->hardware == WSS_HW_CS4239) 1412 chip->hardware == WSS_HW_CS4239)
@@ -1423,6 +1451,26 @@ static int snd_wss_capture_close(struct snd_pcm_substream *substream)
1423 return 0; 1451 return 0;
1424} 1452}
1425 1453
1454static void snd_wss_thinkpad_twiddle(struct snd_wss *chip, int on)
1455{
1456 int tmp;
1457
1458 if (!chip->thinkpad_flag)
1459 return;
1460
1461 outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
1462 tmp = inb(AD1848_THINKPAD_CTL_PORT2);
1463
1464 if (on)
1465 /* turn it on */
1466 tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
1467 else
1468 /* turn it off */
1469 tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
1470
1471 outb(tmp, AD1848_THINKPAD_CTL_PORT2);
1472}
1473
1426#ifdef CONFIG_PM 1474#ifdef CONFIG_PM
1427 1475
1428/* lowlevel suspend callback for CS4231 */ 1476/* lowlevel suspend callback for CS4231 */
@@ -1436,6 +1484,8 @@ static void snd_wss_suspend(struct snd_wss *chip)
1436 for (reg = 0; reg < 32; reg++) 1484 for (reg = 0; reg < 32; reg++)
1437 chip->image[reg] = snd_wss_in(chip, reg); 1485 chip->image[reg] = snd_wss_in(chip, reg);
1438 spin_unlock_irqrestore(&chip->reg_lock, flags); 1486 spin_unlock_irqrestore(&chip->reg_lock, flags);
1487 if (chip->thinkpad_flag)
1488 snd_wss_thinkpad_twiddle(chip, 0);
1439} 1489}
1440 1490
1441/* lowlevel resume callback for CS4231 */ 1491/* lowlevel resume callback for CS4231 */
@@ -1445,6 +1495,8 @@ static void snd_wss_resume(struct snd_wss *chip)
1445 unsigned long flags; 1495 unsigned long flags;
1446 /* int timeout; */ 1496 /* int timeout; */
1447 1497
1498 if (chip->thinkpad_flag)
1499 snd_wss_thinkpad_twiddle(chip, 1);
1448 snd_wss_mce_up(chip); 1500 snd_wss_mce_up(chip);
1449 spin_lock_irqsave(&chip->reg_lock, flags); 1501 spin_lock_irqsave(&chip->reg_lock, flags);
1450 for (reg = 0; reg < 32; reg++) { 1502 for (reg = 0; reg < 32; reg++) {
@@ -1542,6 +1594,14 @@ const char *snd_wss_chip_id(struct snd_wss *chip)
1542 return "AD1845"; 1594 return "AD1845";
1543 case WSS_HW_OPTI93X: 1595 case WSS_HW_OPTI93X:
1544 return "OPTi 93x"; 1596 return "OPTi 93x";
1597 case WSS_HW_AD1847:
1598 return "AD1847";
1599 case WSS_HW_AD1848:
1600 return "AD1848";
1601 case WSS_HW_CS4248:
1602 return "CS4248";
1603 case WSS_HW_CMI8330:
1604 return "CMI8330/C3D";
1545 default: 1605 default:
1546 return "???"; 1606 return "???";
1547 } 1607 }
@@ -1704,7 +1764,8 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
1704 struct snd_pcm *pcm; 1764 struct snd_pcm *pcm;
1705 int err; 1765 int err;
1706 1766
1707 if ((err = snd_pcm_new(chip->card, "CS4231", device, 1, 1, &pcm)) < 0) 1767 err = snd_pcm_new(chip->card, "WSS", device, 1, 1, &pcm);
1768 if (err < 0)
1708 return err; 1769 return err;
1709 1770
1710 spin_lock_init(&chip->reg_lock); 1771 spin_lock_init(&chip->reg_lock);
@@ -1714,6 +1775,12 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
1714 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops); 1775 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops);
1715 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops); 1776 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops);
1716 1777
1778 /* temporary */
1779 if (chip->hardware & WSS_HW_AD1848_MASK) {
1780 chip->rate_constraint = snd_wss_xrate;
1781 chip->set_playback_format = snd_wss_playback_format;
1782 chip->set_capture_format = snd_wss_capture_format;
1783 }
1717 /* global setup */ 1784 /* global setup */
1718 pcm->private_data = chip; 1785 pcm->private_data = chip;
1719 pcm->info_flags = 0; 1786 pcm->info_flags = 0;
@@ -2134,6 +2201,13 @@ int snd_wss_mixer(struct snd_wss *chip)
2134} 2201}
2135EXPORT_SYMBOL(snd_wss_mixer); 2202EXPORT_SYMBOL(snd_wss_mixer);
2136 2203
2204const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction)
2205{
2206 return direction == SNDRV_PCM_STREAM_PLAYBACK ?
2207 &snd_wss_playback_ops : &snd_wss_capture_ops;
2208}
2209EXPORT_SYMBOL(snd_wss_get_pcm_ops);
2210
2137/* 2211/*
2138 * INIT part 2212 * INIT part
2139 */ 2213 */