diff options
-rw-r--r-- | include/sound/ad1848.h | 8 | ||||
-rw-r--r-- | include/sound/wss.h | 7 | ||||
-rw-r--r-- | sound/isa/Kconfig | 5 | ||||
-rw-r--r-- | sound/isa/ad1848/ad1848.c | 2 | ||||
-rw-r--r-- | sound/isa/ad1848/ad1848_lib.c | 544 | ||||
-rw-r--r-- | sound/isa/cmi8330.c | 2 | ||||
-rw-r--r-- | sound/isa/opti9xx/opti92x-ad1848.c | 7 | ||||
-rw-r--r-- | sound/isa/sc6000.c | 4 | ||||
-rw-r--r-- | sound/isa/sgalaxy.c | 5 | ||||
-rw-r--r-- | sound/isa/wss/wss_lib.c | 126 |
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 | ||
107 | void snd_ad1848_out(struct snd_wss *chip, unsigned char reg, | 102 | void 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 | ||
116 | int snd_ad1848_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm); | ||
117 | const 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 | |||
74 | struct snd_wss { | 79 | struct 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); | |||
153 | int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer); | 158 | int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer); |
154 | int snd_wss_mixer(struct snd_wss *chip); | 159 | int snd_wss_mixer(struct snd_wss *chip); |
155 | 160 | ||
161 | const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction); | ||
162 | |||
156 | int snd_cs4236_create(struct snd_card *card, | 163 | int 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 | ||
3 | config SND_AD1848_LIB | 3 | config SND_WSS_LIB |
4 | tristate | 4 | tristate |
5 | select SND_PCM | 5 | select SND_PCM |
6 | 6 | ||
7 | config SND_WSS_LIB | 7 | config SND_AD1848_LIB |
8 | tristate | 8 | tristate |
9 | select SND_PCM | 9 | select SND_PCM |
10 | select SND_WSS_LIB | ||
10 | 11 | ||
11 | config SND_SB_COMMON | 12 | config 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 | ||
49 | static 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 | |||
66 | static unsigned int rates[14] = { | ||
67 | 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050, | ||
68 | 27042, 32000, 33075, 37800, 44100, 48000 | ||
69 | }; | ||
70 | |||
71 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | ||
72 | .count = ARRAY_SIZE(rates), | ||
73 | .list = rates, | ||
74 | .mask = 0, | ||
75 | }; | ||
76 | |||
77 | static unsigned char snd_ad1848_original_image[16] = | 49 | static 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 | ||
129 | EXPORT_SYMBOL(snd_ad1848_out); | 101 | EXPORT_SYMBOL(snd_ad1848_out); |
130 | 102 | ||
131 | static 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 | |||
140 | static unsigned char snd_ad1848_in(struct snd_wss *chip, unsigned char reg) | 103 | static 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 | ||
264 | static 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 | |||
277 | static 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 | |||
309 | static 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 | |||
320 | static 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 | |||
326 | static 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 | |||
344 | static 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 | |||
368 | static 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 | |||
381 | static 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 | |||
432 | static 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 | |||
469 | static 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 | |||
476 | static 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 | |||
483 | static 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 | |||
503 | static int snd_ad1848_playback_hw_free(struct snd_pcm_substream *substream) | ||
504 | { | ||
505 | return snd_pcm_lib_free_pages(substream); | ||
506 | } | ||
507 | |||
508 | static 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 | |||
528 | static 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 | |||
548 | static int snd_ad1848_capture_hw_free(struct snd_pcm_substream *substream) | ||
549 | { | ||
550 | return snd_pcm_lib_free_pages(substream); | ||
551 | } | ||
552 | |||
553 | static 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 | |||
573 | static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id) | 227 | static 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 | ||
585 | static 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 | |||
596 | static 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 | ||
739 | static 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 | |||
758 | static 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 | |||
781 | static 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 | |||
798 | static 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 | |||
815 | static 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 | |||
825 | static 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 | |||
835 | static int snd_ad1848_free(struct snd_wss *chip) | 381 | static 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 | ||
854 | static 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 | |||
865 | int snd_ad1848_create(struct snd_card *card, | 400 | int 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 | ||
936 | EXPORT_SYMBOL(snd_ad1848_create); | 471 | EXPORT_SYMBOL(snd_ad1848_create); |
937 | 472 | ||
938 | static 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 | |||
949 | static 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 | |||
960 | int 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 | |||
987 | EXPORT_SYMBOL(snd_ad1848_pcm); | ||
988 | |||
989 | const 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 | |||
995 | EXPORT_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 | ||
1454 | static 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 | } |
2135 | EXPORT_SYMBOL(snd_wss_mixer); | 2202 | EXPORT_SYMBOL(snd_wss_mixer); |
2136 | 2203 | ||
2204 | const 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 | } | ||
2209 | EXPORT_SYMBOL(snd_wss_get_pcm_ops); | ||
2210 | |||
2137 | /* | 2211 | /* |
2138 | * INIT part | 2212 | * INIT part |
2139 | */ | 2213 | */ |