aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */