diff options
Diffstat (limited to 'sound/isa/ad1848/ad1848_lib.c')
-rw-r--r-- | sound/isa/ad1848/ad1848_lib.c | 544 |
1 files changed, 10 insertions, 534 deletions
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 | */ |