| Linux kernel & device driver programming |
| [ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] |
1 /* 1
2 * Copyright (c) by Jaroslav Kysela <perex@su
3 * Routines for control of CS4231(A)/CS4232/I
4 *
5 * Bugs:
6 * - sometimes record brokes playback with
7 * Yamaha OPL3-SA3 chip
8 * - CS4231 (GUS MAX) - still trouble with
9 * - broken initializat
10 *
11 * This program is free software; you can re
12 * it under the terms of the GNU General Pub
13 * the Free Software Foundation; either vers
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope t
17 * but WITHOUT ANY WARRANTY; without even th
18 * MERCHANTABILITY or FITNESS FOR A PARTICUL
19 * GNU General Public License for more detai
20 *
21 * You should have received a copy of the GN
22 * along with this program; if not, write to
23 * Foundation, Inc., 59 Temple Place, Suite
24 *
25 */
26
27 #include <sound/driver.h>
28 #include <linux/delay.h>
29 #include <linux/pm.h>
30 #include <linux/init.h>
31 #include <linux/interrupt.h>
32 #include <linux/slab.h>
33 #include <linux/ioport.h>
34 #include <sound/core.h>
35 #include <sound/cs4231.h>
36 #include <sound/pcm_params.h>
37
38 #include <asm/io.h>
39 #include <asm/dma.h>
40 #include <asm/irq.h>
41
42 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>
43 MODULE_DESCRIPTION("Routines for control of CS
44 MODULE_LICENSE("GPL");
45
46 #if 0
47 #define SNDRV_DEBUG_MCE
48 #endif
49
50 /*
51 * Some variables
52 */
53
54 static unsigned char freq_bits[14] = {
55 /* 5510 */ 0x00 | CS4231_XTAL2,
56 /* 6620 */ 0x0E | CS4231_XTAL2,
57 /* 8000 */ 0x00 | CS4231_XTAL1,
58 /* 9600 */ 0x0E | CS4231_XTAL1,
59 /* 11025 */ 0x02 | CS4231_XTAL2,
60 /* 16000 */ 0x02 | CS4231_XTAL1,
61 /* 18900 */ 0x04 | CS4231_XTAL2,
62 /* 22050 */ 0x06 | CS4231_XTAL2,
63 /* 27042 */ 0x04 | CS4231_XTAL1,
64 /* 32000 */ 0x06 | CS4231_XTAL1,
65 /* 33075 */ 0x0C | CS4231_XTAL2,
66 /* 37800 */ 0x08 | CS4231_XTAL2,
67 /* 44100 */ 0x0A | CS4231_XTAL2,
68 /* 48000 */ 0x0C | CS4231_XTAL1
69 };
70
71 static unsigned int rates[14] = {
72 5510, 6620, 8000, 9600, 11025, 16000,
73 27042, 32000, 33075, 37800, 44100, 480
74 };
75
76 static snd_pcm_hw_constraint_list_t hw_constra
77 .count = 14,
78 .list = rates,
79 .mask = 0,
80 };
81
82 static int snd_cs4231_xrate(snd_pcm_runtime_t
83 {
84 return snd_pcm_hw_constraint_list(runt
85 }
86
87 static unsigned char snd_cs4231_original_image
88 {
89 0x00, /* 00/00 - lic
90 0x00, /* 01/01 - ric
91 0x9f, /* 02/02 - la1
92 0x9f, /* 03/03 - ra1
93 0x9f, /* 04/04 - la2
94 0x9f, /* 05/05 - ra2
95 0xbf, /* 06/06 - loc
96 0xbf, /* 07/07 - roc
97 0x20, /* 08/08 - pdf
98 CS4231_AUTOCALIB, /* 09/09 - ic
99 0x00, /* 0a/10 - pc
100 0x00, /* 0b/11 - ti
101 CS4231_MODE2, /* 0c/12 - mi
102 0xfc, /* 0d/13 - lbc
103 0x00, /* 0e/14 - pbr
104 0x00, /* 0f/15 - pbr
105 0x80, /* 10/16 - afe
106 0x01, /* 11/17 - afe
107 0x9f, /* 12/18 - lli
108 0x9f, /* 13/19 - rli
109 0x00, /* 14/20 - tlb
110 0x00, /* 15/21 - thb
111 0x00, /* 16/22 - la3
112 0x00, /* 17/23 - ra3
113 0x00, /* 18/24 - afs
114 0x00, /* 19/25 - lam
115 0xcf, /* 1a/26 - mio
116 0x00, /* 1b/27 - ram
117 0x20, /* 1c/28 - cdf
118 0x00, /* 1d/29 - res
119 0x00, /* 1e/30 - cbr
120 0x00, /* 1f/31 - cbr
121 };
122
123 /*
124 * Basic I/O functions
125 */
126
127 #if !defined(EBUS_SUPPORT) && !defined(SBUS_SU
128 #define __CS4231_INLINE__ inline
129 #else
130 #define __CS4231_INLINE__ /* nothing */
131 #endif
132
133 static __CS4231_INLINE__ void cs4231_outb(cs42
134 {
135 #ifdef EBUS_SUPPORT
136 if (chip->ebus->flag) {
137 writeb(val, chip->port + (offs
138 } else {
139 #endif
140 #ifdef SBUS_SUPPORT
141 sbus_writeb(val, chip->port +
142 #endif
143 #ifdef EBUS_SUPPORT
144 }
145 #endif
146 #ifdef LEGACY_SUPPORT
147 outb(val, chip->port + offset);
148 #endif
149 }
150
151 static __CS4231_INLINE__ u8 cs4231_inb(cs4231_
152 {
153 #ifdef EBUS_SUPPORT
154 if (chip->ebus_flag) {
155 return readb(chip->port + (off
156 } else {
157 #endif
158 #ifdef SBUS_SUPPORT
159 return sbus_readb(chip->port +
160 #endif
161 #ifdef EBUS_SUPPORT
162 }
163 #endif
164 #ifdef LEGACY_SUPPORT
165 return inb(chip->port + offset);
166 #endif
167 }
168
169 static void snd_cs4231_outm(cs4231_t *chip, un
170 unsigned char mask
171 {
172 int timeout;
173 unsigned char tmp;
174
175 for (timeout = 250;
176 timeout > 0 && (cs4231_inb(chip,
177 timeout--)
178 udelay(100);
179 #ifdef CONFIG_SND_DEBUG
180 if (cs4231_inb(chip, CS4231P(REGSEL))
181 snd_printk("outm: auto calibra
182 #endif
183 if (chip->calibrate_mute) {
184 chip->image[reg] &= mask;
185 chip->image[reg] |= value;
186 } else {
187 cs4231_outb(chip, CS4231P(REGS
188 mb();
189 tmp = (chip->image[reg] & mask
190 cs4231_outb(chip, CS4231P(REG)
191 chip->image[reg] = tmp;
192 mb();
193 }
194 }
195
196 static void snd_cs4231_dout(cs4231_t *chip, un
197 {
198 int timeout;
199
200 for (timeout = 250;
201 timeout > 0 && (cs4231_inb(chip,
202 timeout--)
203 udelay(10);
204 cs4231_outb(chip, CS4231P(REGSEL), chi
205 cs4231_outb(chip, CS4231P(REG), value)
206 mb();
207 }
208
209 void snd_cs4231_out(cs4231_t *chip, unsigned c
210 {
211 int timeout;
212
213 for (timeout = 250;
214 timeout > 0 && (cs4231_inb(chip,
215 timeout--)
216 udelay(100);
217 #ifdef CONFIG_SND_DEBUG
218 if (cs4231_inb(chip, CS4231P(REGSEL))
219 snd_printk("out: auto calibrat
220 #endif
221 cs4231_outb(chip, CS4231P(REGSEL), chi
222 cs4231_outb(chip, CS4231P(REG), value)
223 chip->image[reg] = value;
224 mb();
225 #if 0
226 printk("codec out - reg 0x%x = 0x%x\n"
227 #endif
228 }
229
230 unsigned char snd_cs4231_in(cs4231_t *chip, un
231 {
232 int timeout;
233
234 for (timeout = 250;
235 timeout > 0 && (cs4231_inb(chip,
236 timeout--)
237 udelay(100);
238 #ifdef CONFIG_SND_DEBUG
239 if (cs4231_inb(chip, CS4231P(REGSEL))
240 snd_printk("in: auto calibrati
241 #endif
242 cs4231_outb(chip, CS4231P(REGSEL), chi
243 mb();
244 return cs4231_inb(chip, CS4231P(REG));
245 }
246
247 void snd_cs4236_ext_out(cs4231_t *chip, unsign
248 {
249 cs4231_outb(chip, CS4231P(REGSEL), chi
250 cs4231_outb(chip, CS4231P(REG), reg |
251 cs4231_outb(chip, CS4231P(REG), val);
252 chip->eimage[CS4236_REG(reg)] = val;
253 #if 0
254 printk("ext out : reg = 0x%x, val = 0x
255 #endif
256 }
257
258 unsigned char snd_cs4236_ext_in(cs4231_t *chip
259 {
260 cs4231_outb(chip, CS4231P(REGSEL), chi
261 cs4231_outb(chip, CS4231P(REG), reg |
262 #if 1
263 return cs4231_inb(chip, CS4231P(REG));
264 #else
265 {
266 unsigned char res;
267 res = cs4231_inb(chip, CS4231P
268 printk("ext in : reg = 0x%x, v
269 return res;
270 }
271 #endif
272 }
273
274 #if 0
275
276 static void snd_cs4231_debug(cs4231_t *chip)
277 {
278 printk("CS4231 REGS: INDEX = 0x%0
279 printk(" STATUS = 0x%0
280 printk(" 0x00: left input = 0x%0
281 printk(" 0x10: alt 1 (CFIG 2) = 0x%0
282 printk(" 0x01: right input = 0x%0
283 printk(" 0x11: alt 2 (CFIG 3) = 0x%0
284 printk(" 0x02: GF1 left input = 0x%0
285 printk(" 0x12: left line in = 0x%0
286 printk(" 0x03: GF1 right input = 0x%0
287 printk(" 0x13: right line in = 0x%0
288 printk(" 0x04: CD left input = 0x%0
289 printk(" 0x14: timer low = 0x%0
290 printk(" 0x05: CD right input = 0x%0
291 printk(" 0x15: timer high = 0x%0
292 printk(" 0x06: left output = 0x%0
293 printk(" 0x16: left MIC (PnP) = 0x%0
294 printk(" 0x07: right output = 0x%0
295 printk(" 0x17: right MIC (PnP) = 0x%0
296 printk(" 0x08: playback format = 0x%0
297 printk(" 0x18: IRQ status = 0x%0
298 printk(" 0x09: iface (CFIG 1) = 0x%0
299 printk(" 0x19: left line out = 0x%0
300 printk(" 0x0a: pin control = 0x%0
301 printk(" 0x1a: mono control = 0x%0
302 printk(" 0x0b: init & status = 0x%0
303 printk(" 0x1b: right line out = 0x%0
304 printk(" 0x0c: revision & mode = 0x%0
305 printk(" 0x1c: record format = 0x%0
306 printk(" 0x0d: loopback = 0x%0
307 printk(" 0x1d: var freq (PnP) = 0x%0
308 printk(" 0x0e: ply upr count = 0x%0
309 printk(" 0x1e: ply lwr count = 0x%0
310 printk(" 0x0f: rec upr count = 0x%0
311 printk(" 0x1f: rec lwr count = 0x%0
312 }
313
314 #endif
315
316 /*
317 * CS4231 detection / MCE routines
318 */
319
320 static void snd_cs4231_busy_wait(cs4231_t *chi
321 {
322 int timeout;
323
324 /* huh.. looks like this sequence is p
325 for (timeout = 5; timeout > 0; timeout
326 cs4231_inb(chip, CS4231P(REGSE
327 /* end of cleanup sequence */
328 for (timeout = 250;
329 timeout > 0 && (cs4231_inb(chip,
330 timeout--)
331 udelay(10);
332 }
333
334 void snd_cs4231_mce_up(cs4231_t *chip)
335 {
336 unsigned long flags;
337 int timeout;
338
339 for (timeout = 250; timeout > 0 && (cs
340 udelay(100);
341 #ifdef CONFIG_SND_DEBUG
342 if (cs4231_inb(chip, CS4231P(REGSEL))
343 snd_printk("mce_up - auto cali
344 #endif
345 spin_lock_irqsave(&chip->reg_lock, fla
346 chip->mce_bit |= CS4231_MCE;
347 timeout = cs4231_inb(chip, CS4231P(REG
348 if (timeout == 0x80)
349 snd_printk("mce_up [0x%lx]: se
350 if (!(timeout & CS4231_MCE))
351 cs4231_outb(chip, CS4231P(REGS
352 spin_unlock_irqrestore(&chip->reg_lock
353 }
354
355 void snd_cs4231_mce_down(cs4231_t *chip)
356 {
357 unsigned long flags;
358 int timeout;
359
360 snd_cs4231_busy_wait(chip);
361 #if 0
362 printk("(1) timeout = %i\n", timeout);
363 #endif
364 #ifdef CONFIG_SND_DEBUG
365 if (cs4231_inb(chip, CS4231P(REGSEL))
366 snd_printk("mce_down [0x%lx] -
367 #endif
368 spin_lock_irqsave(&chip->reg_lock, fla
369 chip->mce_bit &= ~CS4231_MCE;
370 timeout = cs4231_inb(chip, CS4231P(REG
371 cs4231_outb(chip, CS4231P(REGSEL), chi
372 spin_unlock_irqrestore(&chip->reg_lock
373 if (timeout == 0x80)
374 snd_printk("mce_down [0x%lx]:
375 if ((timeout & CS4231_MCE) == 0 ||
376 !(chip->hardware & (CS4231_HW_CS42
377 return;
378 }
379 snd_cs4231_busy_wait(chip);
380
381 /* calibration process */
382
383 for (timeout = 500; timeout > 0 && (sn
384 udelay(10);
385 if ((snd_cs4231_in(chip, CS4231_TEST_I
386 snd_printd("cs4231_mce_down -
387 return;
388 }
389 #if 0
390 printk("(2) timeout = %i, jiffies = %l
391 #endif
392 /* in 10 ms increments, check conditio
393 timeout = 25;
394 while (snd_cs4231_in(chip, CS4231_TEST
395 if (--timeout < 0) {
396 snd_printk("mce_down -
397 return;
398 }
399 msleep(10);
400 }
401 #if 0
402 printk("(3) jiffies = %li\n", jiffies)
403 #endif
404 /* in 10 ms increments, check conditio
405 timeout = 10;
406 while (cs4231_inb(chip, CS4231P(REGSEL
407 if (--timeout < 0) {
408 snd_printk(KERN_ERR "m
409 return;
410 }
411 msleep(10);
412 }
413 #if 0
414 printk("(4) jiffies = %li\n", jiffies)
415 snd_printk("mce_down - exit = 0x%x\n",
416 #endif
417 }
418
419 static unsigned int snd_cs4231_get_count(unsig
420 {
421 switch (format & 0xe0) {
422 case CS4231_LINEAR_16:
423 case CS4231_LINEAR_16_BIG:
424 size >>= 1;
425 break;
426 case CS4231_ADPCM_16:
427 return size >> 2;
428 }
429 if (format & CS4231_STEREO)
430 size >>= 1;
431 return size;
432 }
433
434 static int snd_cs4231_trigger(snd_pcm_substrea
435 int cmd)
436 {
437 cs4231_t *chip = snd_pcm_substream_chi
438 int result = 0;
439 unsigned int what;
440 struct list_head *pos;
441 snd_pcm_substream_t *s;
442 int do_start;
443
444 #if 0
445 printk("codec trigger!!! - what = %i,
446 #endif
447
448 switch (cmd) {
449 case SNDRV_PCM_TRIGGER_START:
450 case SNDRV_PCM_TRIGGER_RESUME:
451 do_start = 1; break;
452 case SNDRV_PCM_TRIGGER_STOP:
453 case SNDRV_PCM_TRIGGER_SUSPEND:
454 do_start = 0; break;
455 default:
456 return -EINVAL;
457 }
458
459 what = 0;
460 snd_pcm_group_for_each(pos, substream)
461 s = snd_pcm_group_substream_en
462 if (s == chip->playback_substr
463 what |= CS4231_PLAYBAC
464 snd_pcm_trigger_done(s
465 } else if (s == chip->capture_
466 what |= CS4231_RECORD_
467 snd_pcm_trigger_done(s
468 }
469 }
470 spin_lock(&chip->reg_lock);
471 if (do_start) {
472 chip->image[CS4231_IFACE_CTRL]
473 if (chip->trigger)
474 chip->trigger(chip, wh
475 } else {
476 chip->image[CS4231_IFACE_CTRL]
477 if (chip->trigger)
478 chip->trigger(chip, wh
479 }
480 snd_cs4231_out(chip, CS4231_IFACE_CTRL
481 spin_unlock(&chip->reg_lock);
482 #if 0
483 snd_cs4231_debug(chip);
484 #endif
485 return result;
486 }
487
488 /*
489 * CODEC I/O
490 */
491
492 static unsigned char snd_cs4231_get_rate(unsig
493 {
494 int i;
495
496 for (i = 0; i < 14; i++)
497 if (rate == rates[i])
498 return freq_bits[i];
499 // snd_BUG();
500 return freq_bits[13];
501 }
502
503 static unsigned char snd_cs4231_get_format(cs4
504 int
505 int
506 {
507 unsigned char rformat;
508
509 rformat = CS4231_LINEAR_8;
510 switch (format) {
511 case SNDRV_PCM_FORMAT_MU_LAW: rforma
512 case SNDRV_PCM_FORMAT_A_LAW: rforma
513 case SNDRV_PCM_FORMAT_S16_LE: rforma
514 case SNDRV_PCM_FORMAT_S16_BE: rforma
515 case SNDRV_PCM_FORMAT_IMA_ADPCM:
516 }
517 if (channels > 1)
518 rformat |= CS4231_STEREO;
519 #if 0
520 snd_printk("get_format: 0x%x (mode=0x%
521 #endif
522 return rformat;
523 }
524
525 static void snd_cs4231_calibrate_mute(cs4231_t
526 {
527 unsigned long flags;
528
529 mute = mute ? 1 : 0;
530 spin_lock_irqsave(&chip->reg_lock, fla
531 if (chip->calibrate_mute == mute) {
532 spin_unlock_irqrestore(&chip->
533 return;
534 }
535 if (!mute) {
536 snd_cs4231_dout(chip, CS4231_L
537 snd_cs4231_dout(chip, CS4231_R
538 snd_cs4231_dout(chip, CS4231_L
539 }
540 snd_cs4231_dout(chip, CS4231_AUX1_LEFT
541 snd_cs4231_dout(chip, CS4231_AUX1_RIGH
542 snd_cs4231_dout(chip, CS4231_AUX2_LEFT
543 snd_cs4231_dout(chip, CS4231_AUX2_RIGH
544 snd_cs4231_dout(chip, CS4231_LEFT_OUTP
545 snd_cs4231_dout(chip, CS4231_RIGHT_OUT
546 snd_cs4231_dout(chip, CS4231_LEFT_LINE
547 snd_cs4231_dout(chip, CS4231_RIGHT_LIN
548 snd_cs4231_dout(chip, CS4231_MONO_CTRL
549 if (chip->hardware == CS4231_HW_INTERW
550 snd_cs4231_dout(chip, CS4231_L
551 snd_cs4231_dout(chip, CS4231_R
552 snd_cs4231_dout(chip, CS4231_L
553 snd_cs4231_dout(chip, CS4231_L
554 }
555 chip->calibrate_mute = mute;
556 spin_unlock_irqrestore(&chip->reg_lock
557 }
558
559 static void snd_cs4231_playback_format(cs4231_
560 snd_pcm
561 unsigne
562 {
563 unsigned long flags;
564 int full_calib = 1;
565
566 down(&chip->mce_mutex);
567 snd_cs4231_calibrate_mute(chip, 1);
568 if (chip->hardware == CS4231_HW_CS4231
569 (chip->hardware & CS4231_HW_CS4232
570 spin_lock_irqsave(&chip->reg_l
571 if ((chip->image[CS4231_PLAYBK
572 snd_cs4231_out(chip, C
573 snd_cs4231_out(chip, C
574 snd_cs4231_out(chip, C
575 udelay(100); /* Fixes
576 full_calib = 0;
577 }
578 spin_unlock_irqrestore(&chip->
579 }
580 if (full_calib) {
581 snd_cs4231_mce_up(chip);
582 spin_lock_irqsave(&chip->reg_l
583 if (chip->hardware != CS4231_H
584 snd_cs4231_out(chip, C
585 (chip-
586 (pdfr
587 pdfr);
588 } else {
589 snd_cs4231_out(chip, C
590 }
591 spin_unlock_irqrestore(&chip->
592 snd_cs4231_mce_down(chip);
593 }
594 snd_cs4231_calibrate_mute(chip, 0);
595 up(&chip->mce_mutex);
596 }
597
598 static void snd_cs4231_capture_format(cs4231_t
599 snd_pcm_
600 unsigned
601 {
602 unsigned long flags;
603 int full_calib = 1;
604
605 down(&chip->mce_mutex);
606 snd_cs4231_calibrate_mute(chip, 1);
607 if (chip->hardware == CS4231_HW_CS4231
608 (chip->hardware & CS4231_HW_CS4232
609 spin_lock_irqsave(&chip->reg_l
610 if ((chip->image[CS4231_PLAYBK
611 (chip->image[CS4231_IFACE_
612 snd_cs4231_out(chip, C
613 snd_cs4231_out(chip, C
614 snd_cs4231_out(chip, C
615 full_calib = 0;
616 }
617 spin_unlock_irqrestore(&chip->
618 }
619 if (full_calib) {
620 snd_cs4231_mce_up(chip);
621 spin_lock_irqsave(&chip->reg_l
622 if (chip->hardware != CS4231_H
623 if (!(chip->image[CS42
624 snd_cs4231_out
625
626
627 spin_unlock_ir
628 snd_cs4231_mce
629 snd_cs4231_mce
630 spin_lock_irqs
631 }
632 }
633 snd_cs4231_out(chip, CS4231_RE
634 spin_unlock_irqrestore(&chip->
635 snd_cs4231_mce_down(chip);
636 }
637 snd_cs4231_calibrate_mute(chip, 0);
638 up(&chip->mce_mutex);
639 }
640
641 /*
642 * Timer interface
643 */
644
645 static unsigned long snd_cs4231_timer_resoluti
646 {
647 cs4231_t *chip = snd_timer_chip(timer)
648 if (chip->hardware & CS4231_HW_CS4236B
649 return 14467;
650 else
651 return chip->image[CS4231_PLAY
652 }
653
654 static int snd_cs4231_timer_start(snd_timer_t
655 {
656 unsigned long flags;
657 unsigned int ticks;
658 cs4231_t *chip = snd_timer_chip(timer)
659 spin_lock_irqsave(&chip->reg_lock, fla
660 ticks = timer->sticks;
661 if ((chip->image[CS4231_ALT_FEATURE_1]
662 (unsigned char)(ticks >> 8) != chi
663 (unsigned char)ticks != chip->imag
664 snd_cs4231_out(chip, CS4231_TI
665 snd_cs4231_out(chip, CS4231_TI
666 snd_cs4231_out(chip, CS4231_AL
667 }
668 spin_unlock_irqrestore(&chip->reg_lock
669 return 0;
670 }
671
672 static int snd_cs4231_timer_stop(snd_timer_t *
673 {
674 unsigned long flags;
675 cs4231_t *chip = snd_timer_chip(timer)
676 spin_lock_irqsave(&chip->reg_lock, fla
677 snd_cs4231_out(chip, CS4231_ALT_FEATUR
678 spin_unlock_irqrestore(&chip->reg_lock
679 return 0;
680 }
681
682 static void snd_cs4231_init(cs4231_t *chip)
683 {
684 unsigned long flags;
685
686 snd_cs4231_mce_down(chip);
687
688 #ifdef SNDRV_DEBUG_MCE
689 snd_printk("init: (1)\n");
690 #endif
691 snd_cs4231_mce_up(chip);
692 spin_lock_irqsave(&chip->reg_lock, fla
693 chip->image[CS4231_IFACE_CTRL] &= ~(CS
694 CS4231_RECORD_ENA
695 CS4231_CALIB_MODE
696 chip->image[CS4231_IFACE_CTRL] |= CS42
697 snd_cs4231_out(chip, CS4231_IFACE_CTRL
698 spin_unlock_irqrestore(&chip->reg_lock
699 snd_cs4231_mce_down(chip);
700
701 #ifdef SNDRV_DEBUG_MCE
702 snd_printk("init: (2)\n");
703 #endif
704
705 snd_cs4231_mce_up(chip);
706 spin_lock_irqsave(&chip->reg_lock, fla
707 snd_cs4231_out(chip, CS4231_ALT_FEATUR
708 spin_unlock_irqrestore(&chip->reg_lock
709 snd_cs4231_mce_down(chip);
710
711 #ifdef SNDRV_DEBUG_MCE
712 snd_printk("init: (3) - afei = 0x%x\n"
713 #endif
714
715 spin_lock_irqsave(&chip->reg_lock, fla
716 snd_cs4231_out(chip, CS4231_ALT_FEATUR
717 spin_unlock_irqrestore(&chip->reg_lock
718
719 snd_cs4231_mce_up(chip);
720 spin_lock_irqsave(&chip->reg_lock, fla
721 snd_cs4231_out(chip, CS4231_PLAYBK_FOR
722 spin_unlock_irqrestore(&chip->reg_lock
723 snd_cs4231_mce_down(chip);
724
725 #ifdef SNDRV_DEBUG_MCE
726 snd_printk("init: (4)\n");
727 #endif
728
729 snd_cs4231_mce_up(chip);
730 spin_lock_irqsave(&chip->reg_lock, fla
731 snd_cs4231_out(chip, CS4231_REC_FORMAT
732 spin_unlock_irqrestore(&chip->reg_lock
733 snd_cs4231_mce_down(chip);
734
735 #ifdef SNDRV_DEBUG_MCE
736 snd_printk("init: (5)\n");
737 #endif
738 }
739
740 static int snd_cs4231_open(cs4231_t *chip, uns
741 {
742 unsigned long flags;
743
744 down(&chip->open_mutex);
745 if ((chip->mode & mode) ||
746 ((chip->mode & CS4231_MODE_OPEN) &
747 up(&chip->open_mutex);
748 return -EAGAIN;
749 }
750 if (chip->mode & CS4231_MODE_OPEN) {
751 chip->mode |= mode;
752 up(&chip->open_mutex);
753 return 0;
754 }
755 /* ok. now enable and ack CODEC IRQ */
756 spin_lock_irqsave(&chip->reg_lock, fla
757 snd_cs4231_out(chip, CS4231_IRQ_STATUS
758 CS4231_RECORD_IRQ |
759 CS4231_TIMER_IRQ);
760 snd_cs4231_out(chip, CS4231_IRQ_STATUS
761 cs4231_outb(chip, CS4231P(STATUS), 0);
762 cs4231_outb(chip, CS4231P(STATUS), 0);
763 chip->image[CS4231_PIN_CTRL] |= CS4231
764 snd_cs4231_out(chip, CS4231_PIN_CTRL,
765 snd_cs4231_out(chip, CS4231_IRQ_STATUS
766 CS4231_RECORD_IRQ |
767 CS4231_TIMER_IRQ);
768 snd_cs4231_out(chip, CS4231_IRQ_STATUS
769 spin_unlock_irqrestore(&chip->reg_lock
770
771 chip->mode = mode;
772 up(&chip->open_mutex);
773 return 0;
774 }
775
776 static void snd_cs4231_close(cs4231_t *chip, u
777 {
778 unsigned long flags;
779
780 down(&chip->open_mutex);
781 chip->mode &= ~mode;
782 if (chip->mode & CS4231_MODE_OPEN) {
783 up(&chip->open_mutex);
784 return;
785 }
786 snd_cs4231_calibrate_mute(chip, 1);
787
788 /* disable IRQ */
789 spin_lock_irqsave(&chip->reg_lock, fla
790 snd_cs4231_out(chip, CS4231_IRQ_STATUS
791 cs4231_outb(chip, CS4231P(STATUS), 0);
792 cs4231_outb(chip, CS4231P(STATUS), 0);
793 chip->image[CS4231_PIN_CTRL] &= ~CS423
794 snd_cs4231_out(chip, CS4231_PIN_CTRL,
795
796 /* now disable record & playback */
797
798 if (chip->image[CS4231_IFACE_CTRL] & (
799
800 spin_unlock_irqrestore(&chip->
801 snd_cs4231_mce_up(chip);
802 spin_lock_irqsave(&chip->reg_l
803 chip->image[CS4231_IFACE_CTRL]
804
805 snd_cs4231_out(chip, CS4231_IF
806 spin_unlock_irqrestore(&chip->
807 snd_cs4231_mce_down(chip);
808 spin_lock_irqsave(&chip->reg_l
809 }
810
811 /* clear IRQ again */
812 snd_cs4231_out(chip, CS4231_IRQ_STATUS
813 cs4231_outb(chip, CS4231P(STATUS), 0);
814 cs4231_outb(chip, CS4231P(STATUS), 0);
815 spin_unlock_irqrestore(&chip->reg_lock
816
817 snd_cs4231_calibrate_mute(chip, 0);
818
819 chip->mode = 0;
820 up(&chip->open_mutex);
821 }
822
823 /*
824 * timer open/close
825 */
826
827 static int snd_cs4231_timer_open(snd_timer_t *
828 {
829 cs4231_t *chip = snd_timer_chip(timer)
830 snd_cs4231_open(chip, CS4231_MODE_TIME
831 return 0;
832 }
833
834 static int snd_cs4231_timer_close(snd_timer_t
835 {
836 cs4231_t *chip = snd_timer_chip(timer)
837 snd_cs4231_close(chip, CS4231_MODE_TIM
838 return 0;
839 }
840
841 static struct _snd_timer_hardware snd_cs4231_t
842 {
843 .flags = SNDRV_TIMER_HW_AUTO,
844 .resolution = 9945,
845 .ticks = 65535,
846 .open = snd_cs4231_timer_open,
847 .close = snd_cs4231_timer_close
848 .c_resolution = snd_cs4231_timer_resol
849 .start = snd_cs4231_timer_start
850 .stop = snd_cs4231_timer_stop,
851 };
852
853 /*
854 * ok.. exported functions..
855 */
856
857 static int snd_cs4231_playback_hw_params(snd_p
858 snd_p
859 {
860 cs4231_t *chip = snd_pcm_substream_chi
861 unsigned char new_pdfr;
862 int err;
863
864 if ((err = snd_pcm_lib_malloc_pages(su
865 return err;
866 new_pdfr = snd_cs4231_get_format(chip,
867 snd_cs4231_get_rate(params_
868 chip->set_playback_format(chip, hw_par
869 return 0;
870 }
871
872 static int snd_cs4231_playback_hw_free(snd_pcm
873 {
874 return snd_pcm_lib_free_pages(substrea
875 }
876
877 #ifdef LEGACY_SUPPORT
878 static int snd_cs4231_playback_prepare(snd_pcm
879 {
880 cs4231_t *chip = snd_pcm_substream_chi
881 snd_pcm_runtime_t *runtime = substream
882 unsigned long flags;
883 unsigned int size = snd_pcm_lib_buffer
884 unsigned int count = snd_pcm_lib_perio
885
886 spin_lock_irqsave(&chip->reg_lock, fla
887 chip->p_dma_size = size;
888 chip->image[CS4231_IFACE_CTRL] &= ~(CS
889 snd_dma_program(chip->dma1, runtime->d
890 count = snd_cs4231_get_count(chip->ima
891 snd_cs4231_out(chip, CS4231_PLY_LWR_CN
892 snd_cs4231_out(chip, CS4231_PLY_UPR_CN
893 spin_unlock_irqrestore(&chip->reg_lock
894 #if 0
895 snd_cs4231_debug(chip);
896 #endif
897 return 0;
898 }
899 #endif /* LEGACY_SUPPORT */
900
901 static int snd_cs4231_capture_hw_params(snd_pc
902 snd_pc
903 {
904 cs4231_t *chip = snd_pcm_substream_chi
905 unsigned char new_cdfr;
906 int err;
907
908 if ((err = snd_pcm_lib_malloc_pages(su
909 return err;
910 new_cdfr = snd_cs4231_get_format(chip,
911 snd_cs4231_get_rate(params_
912 chip->set_capture_format(chip, hw_para
913 return 0;
914 }
915
916 static int snd_cs4231_capture_hw_free(snd_pcm_
917 {
918 return snd_pcm_lib_free_pages(substrea
919 }
920
921 #ifdef LEGACY_SUPPORT
922 static int snd_cs4231_capture_prepare(snd_pcm_
923 {
924 cs4231_t *chip = snd_pcm_substream_chi
925 snd_pcm_runtime_t *runtime = substream
926 unsigned long flags;
927 unsigned int size = snd_pcm_lib_buffer
928 unsigned int count = snd_pcm_lib_perio
929
930 spin_lock_irqsave(&chip->reg_lock, fla
931 chip->c_dma_size = size;
932 chip->image[CS4231_IFACE_CTRL] &= ~(CS
933 snd_dma_program(chip->dma2, runtime->d
934 count = snd_cs4231_get_count(chip->ima
935 if (chip->single_dma && chip->hardware
936 snd_cs4231_out(chip, CS4231_PL
937 snd_cs4231_out(chip, CS4231_PL
938 } else {
939 snd_cs4231_out(chip, CS4231_RE
940 snd_cs4231_out(chip, CS4231_RE
941 }
942 spin_unlock_irqrestore(&chip->reg_lock
943 return 0;
944 }
945 #endif
946
947 static void snd_cs4231_overrange(cs4231_t *chi
948 {
949 unsigned long flags;
950 unsigned char res;
951
952 spin_lock_irqsave(&chip->reg_lock, fla
953 res = snd_cs4231_in(chip, CS4231_TEST_
954 spin_unlock_irqrestore(&chip->reg_lock
955 if (res & (0x08 | 0x02)) /* det
956 chip->capture_substream->runti
957 }
958
959 irqreturn_t snd_cs4231_interrupt(int irq, void
960 {
961 cs4231_t *chip = dev_id;
962 unsigned char status;
963
964 status = snd_cs4231_in(chip, CS4231_IR
965 if (status & CS4231_TIMER_IRQ) {
966 if (chip->timer)
967 snd_timer_interrupt(ch
968 }
969 if (chip->single_dma && chip->hardware
970 if (status & CS4231_PLAYBACK_I
971 if (chip->mode & CS423
972 if (chip->play
973 snd_pc
974 }
975 if (chip->mode & CS423
976 if (chip->capt
977 snd_cs
978 snd_pc
979 }
980 }
981 }
982 } else {
983 if (status & CS4231_PLAYBACK_I
984 if (chip->playback_sub
985 snd_pcm_period
986 }
987 if (status & CS4231_RECORD_IRQ
988 if (chip->capture_subs
989 snd_cs4231_ove
990 snd_pcm_period
991 }
992 }
993 }
994
995 spin_lock(&chip->reg_lock);
996 snd_cs4231_outm(chip, CS4231_IRQ_STATU
997 spin_unlock(&chip->reg_lock);
998 return IRQ_HANDLED;
999 }
1000
1001 #ifdef LEGACY_SUPPORT
1002 static snd_pcm_uframes_t snd_cs4231_playback_
1003 {
1004 cs4231_t *chip = snd_pcm_substream_ch
1005 size_t ptr;
1006
1007 if (!(chip->image[CS4231_IFACE_CTRL]
1008 return 0;
1009 ptr = snd_dma_pointer(chip->dma1, chi
1010 return bytes_to_frames(substream->run
1011 }
1012
1013 static snd_pcm_uframes_t snd_cs4231_capture_p
1014 {
1015 cs4231_t *chip = snd_pcm_substream_ch
1016 size_t ptr;
1017
1018 if (!(chip->image[CS4231_IFACE_CTRL]
1019 return 0;
1020 ptr = snd_dma_pointer(chip->dma2, chi
1021 return bytes_to_frames(substream->run
1022 }
1023 #endif /* LEGACY_SUPPORT */
1024
1025 /*
1026
1027 */
1028
1029 static int snd_cs4231_probe(cs4231_t *chip)
1030 {
1031 unsigned long flags;
1032 int i, id, rev;
1033 unsigned char *ptr;
1034 unsigned int hw;
1035
1036 #if 0
1037 snd_cs4231_debug(chip);
1038 #endif
1039 id = 0;
1040 for (i = 0; i < 50; i++) {
1041 mb();
1042 if (cs4231_inb(chip, CS4231P(
1043 udelay(2000);
1044 else {
1045 spin_lock_irqsave(&ch
1046 snd_cs4231_out(chip,
1047 id = snd_cs4231_in(ch
1048 spin_unlock_irqrestor
1049 if (id == 0x0a)
1050 break; /* th
1051 }
1052 }
1053 snd_printdd("cs4231: port = 0x%lx, id
1054 if (id != 0x0a)
1055 return -ENODEV; /* no valid d
1056
1057 if (((hw = chip->hardware) & CS4231_H
1058 rev = snd_cs4231_in(chip, CS4
1059 snd_printdd("CS4231: VERSION
1060 if (rev == 0x80) {
1061 unsigned char tmp = s
1062 snd_cs4231_out(chip,
1063 if (snd_cs4231_in(chi
1064 chip->hardwar
1065 else
1066 chip->hardwar
1067 } else if (rev == 0xa0) {
1068 chip->hardware = CS42
1069 } else if (rev == 0xa2) {
1070 chip->hardware = CS42
1071 } else if (rev == 0xb2) {
1072 chip->hardware = CS42
1073 } else if (rev == 0x83) {
1074 chip->hardware = CS42
1075 } else if (rev == 0x03) {
1076 chip->hardware = CS42
1077 } else {
1078 snd_printk("unknown C
1079 return -ENODEV;
1080 }
1081 }
1082 spin_lock_irqsave(&chip->reg_lock, fl
1083 cs4231_inb(chip, CS4231P(STATUS));
1084 cs4231_outb(chip, CS4231P(STATUS), 0)
1085 mb();
1086 spin_unlock_irqrestore(&chip->reg_loc
1087
1088 chip->image[CS4231_MISC_INFO] = CS423
1089 switch (chip->hardware) {
1090 case CS4231_HW_INTERWAVE:
1091 chip->image[CS4231_MISC_INFO]
1092 break;
1093 case CS4231_HW_CS4235:
1094 case CS4231_HW_CS4236B:
1095 case CS4231_HW_CS4237B:
1096 case CS4231_HW_CS4238B:
1097 case CS4231_HW_CS4239:
1098 if (hw == CS4231_HW_DETECT3)
1099 chip->image[CS4231_MI
1100 else
1101 chip->hardware = CS42
1102 break;
1103 }
1104
1105 chip->image[CS4231_IFACE_CTRL] =
1106 (chip->image[CS4231_IFACE_CTRL] &
1107 (chip->single_dma ? CS4231_SINGLE
1108 chip->image[CS4231_ALT_FEATURE_1] = 0
1109 chip->image[CS4231_ALT_FEATURE_2] = c
1110 ptr = (unsigned char *) &chip->image;
1111 snd_cs4231_mce_down(chip);
1112 spin_lock_irqsave(&chip->reg_lock, fl
1113 for (i = 0; i < 32; i++) /* ok
1114 snd_cs4231_out(chip, i, *ptr+
1115 spin_unlock_irqrestore(&chip->reg_loc
1116 snd_cs4231_mce_up(chip);
1117 snd_cs4231_mce_down(chip);
1118
1119 mdelay(2);
1120
1121 /* ok.. try check hardware version fo
1122 if ((hw & CS4231_HW_TYPE_MASK) == CS4
1123 if (chip->hardware == CS4231_
1124 rev = snd_cs4236_ext_
1125 snd_cs4236_ext_out(ch
1126 id = snd_cs4236_ext_i
1127 snd_cs4236_ext_out(ch
1128 snd_printdd("CS4231:
1129 if ((id & 0x1f) == 0x
1130 chip->hardwar
1131 switch (id >>
1132 case 4:
1133 case 5:
1134 case 6:
1135 break
1136 default:
1137 snd_p
1138 }
1139 } else if ((id & 0x1f
1140 switch (id >>
1141 case 4:
1142 case 5:
1143 case 6:
1144 case 7:
1145 chip-
1146 break
1147 default:
1148 snd_p
1149 }
1150 } else if ((id & 0x1f
1151 chip->hardwar
1152 switch (id >>
1153 case 4:
1154 case 5:
1155 case 6:
1156 case 7:
1157 break
1158 default:
1159 snd_p
1160 }
1161 } else if ((id & 0x1f
1162 chip->hardwar
1163 switch (id >>
1164 case 5:
1165 case 6:
1166 case 7:
1167 break
1168 default:
1169 snd_p
1170 }
1171 } else if ((id & 0x1f
1172 chip->hardwar
1173 switch (id >>
1174 case 4:
1175 case 5:
1176 case 6:
1177 break
1178 default:
1179 snd_p
1180 }
1181 } else {
1182 snd_printk("u
1183 }
1184 }
1185 }
1186 return 0; /* all things
1187 }
1188
1189 /*
1190
1191 */
1192
1193 static snd_pcm_hardware_t snd_cs4231_playback
1194 {
1195 .info = (SNDRV_PCM_IN
1196 SNDRV_PCM_IN
1197 SNDRV_PCM_IN
1198 SNDRV_PCM_IN
1199 .formats = (SNDRV_PCM_FM
1200 SNDRV_PCM_FM
1201 .rates = SNDRV_PCM_RAT
1202 .rate_min = 5510,
1203 .rate_max = 48000,
1204 .channels_min = 1,
1205 .channels_max = 2,
1206 .buffer_bytes_max = (128*1024),
1207 .period_bytes_min = 64,
1208 .period_bytes_max = (128*1024),
1209 .periods_min = 1,
1210 .periods_max = 1024,
1211 .fifo_size = 0,
1212 };
1213
1214 static snd_pcm_hardware_t snd_cs4231_capture
1215 {
1216 .info = (SNDRV_PCM_IN
1217 SNDRV_PCM_IN
1218 SNDRV_PCM_IN
1219 SNDRV_PCM_IN
1220 .formats = (SNDRV_PCM_FM
1221 SNDRV_PCM_FM
1222 .rates = SNDRV_PCM_RAT
1223 .rate_min = 5510,
1224 .rate_max = 48000,
1225 .channels_min = 1,
1226 .channels_max = 2,
1227 .buffer_bytes_max = (128*1024),
1228 .period_bytes_min = 64,
1229 .period_bytes_max = (128*1024),
1230 .periods_min = 1,
1231 .periods_max = 1024,
1232 .fifo_size = 0,
1233 };
1234
1235 /*
1236
1237 */
1238
1239 static int snd_cs4231_playback_open(snd_pcm_s
1240 {
1241 cs4231_t *chip = snd_pcm_substream_ch
1242 snd_pcm_runtime_t *runtime = substrea
1243 int err;
1244
1245 runtime->hw = snd_cs4231_playback;
1246
1247 /* hardware bug in InterWave chipset
1248 if (chip->hardware == CS4231_HW_INTER
1249 runtime->hw.formats &= ~SNDRV
1250
1251 /* hardware limitation of cheap chips
1252 if (chip->hardware == CS4231_HW_CS423
1253 chip->hardware == CS4231_HW_CS423
1254 runtime->hw.formats = SNDRV_P
1255
1256 #ifdef LEGACY_SUPPORT
1257 snd_pcm_limit_isa_dma_size(chip->dma1
1258 snd_pcm_limit_isa_dma_size(chip->dma1
1259
1260 if (chip->claim_dma) {
1261 if ((err = chip->claim_dma(ch
1262 return err;
1263 }
1264 #endif
1265
1266 if ((err = snd_cs4231_open(chip, CS42
1267 #ifdef LEGACY_SUPPORT
1268 if (chip->release_dma)
1269 chip->release_dma(chi
1270 #endif
1271 snd_free_pages(runtime->dma_a
1272 return err;
1273 }
1274 chip->playback_substream = substream;
1275 #if defined(SBUS_SUPPORT) || defined(EBUS_SUP
1276 chip->p_periods_sent = 0;
1277 #endif
1278 snd_pcm_set_sync(substream);
1279 chip->rate_constraint(runtime);
1280 return 0;
1281 }
1282
1283 static int snd_cs4231_capture_open(snd_pcm_su
1284 {
1285 cs4231_t *chip = snd_pcm_substream_ch
1286 snd_pcm_runtime_t *runtime = substrea
1287 int err;
1288
1289 runtime->hw = snd_cs4231_capture;
1290
1291 /* hardware limitation of cheap chips
1292 if (chip->hardware == CS4231_HW_CS423
1293 chip->hardware == CS4231_HW_CS423
1294 runtime->hw.formats = SNDRV_P
1295
1296 #ifdef LEGACY_SUPPORT
1297 snd_pcm_limit_isa_dma_size(chip->dma2
1298 snd_pcm_limit_isa_dma_size(chip->dma2
1299
1300 if (chip->claim_dma) {
1301 if ((err = chip->claim_dma(ch
1302 return err;
1303 }
1304 #endif
1305
1306 if ((err = snd_cs4231_open(chip, CS42
1307 #ifdef LEGACY_SUPPORT
1308 if (chip->release_dma)
1309 chip->release_dma(chi
1310 #endif
1311 snd_free_pages(runtime->dma_a
1312 return err;
1313 }
1314 chip->capture_substream = substream;
1315 #if defined(SBUS_SUPPORT) || defined(EBUS_SUP
1316 chip->c_periods_sent = 0;
1317 #endif
1318 snd_pcm_set_sync(substream);
1319 chip->rate_constraint(runtime);
1320 return 0;
1321 }
1322
1323 static int snd_cs4231_playback_close(snd_pcm_
1324 {
1325 cs4231_t *chip = snd_pcm_substream_ch
1326
1327 chip->playback_substream = NULL;
1328 snd_cs4231_close(chip, CS4231_MODE_PL
1329 return 0;
1330 }
1331
1332 static int snd_cs4231_capture_close(snd_pcm_s
1333 {
1334 cs4231_t *chip = snd_pcm_substream_ch
1335
1336 chip->capture_substream = NULL;
1337 snd_cs4231_close(chip, CS4231_MODE_RE
1338 return 0;
1339 }
1340
1341 #ifdef CONFIG_PM
1342
1343 /* lowlevel suspend callback for CS4231 */
1344 static void snd_cs4231_suspend(cs4231_t *chip
1345 {
1346 int reg;
1347 unsigned long flags;
1348
1349 spin_lock_irqsave(&chip->reg_lock, fl
1350 for (reg = 0; reg < 32; reg++)
1351 chip->image[reg] = snd_cs4231
1352 spin_unlock_irqrestore(&chip->reg_loc
1353 }
1354
1355 /* lowlevel resume callback for CS4231 */
1356 static void snd_cs4231_resume(cs4231_t *chip)
1357 {
1358 int reg;
1359 unsigned long flags;
1360 int timeout;
1361
1362 snd_cs4231_mce_up(chip);
1363 spin_lock_irqsave(&chip->reg_lock, fl
1364 for (reg = 0; reg < 32; reg++) {
1365 switch (reg) {
1366 case CS4231_VERSION:
1367 break;
1368 default:
1369 snd_cs4231_out(chip,
1370 break;
1371 }
1372 }
1373 spin_unlock_irqrestore(&chip->reg_loc
1374 #if 0
1375 snd_cs4231_mce_down(chip);
1376 #else
1377 /* The following is a workaround to a
1378 This is the first half of copy of
1379 include rescheduling. -- iwai
1380 */
1381 snd_cs4231_busy_wait(chip);
1382 spin_lock_irqsave(&chip->reg_lock, fl
1383 chip->mce_bit &= ~CS4231_MCE;
1384 timeout = cs4231_inb(chip, CS4231P(RE
1385 cs4231_outb(chip, CS4231P(REGSEL), ch
1386 spin_unlock_irqrestore(&chip->reg_loc
1387 if (timeout == 0x80)
1388 snd_printk("down [0x%lx]: ser
1389 if ((timeout & CS4231_MCE) == 0 ||
1390 !(chip->hardware & (CS4231_HW_CS4
1391 return;
1392 }
1393 snd_cs4231_busy_wait(chip);
1394 #endif
1395 }
1396
1397 static int snd_cs4231_pm_suspend(snd_card_t *
1398 {
1399 cs4231_t *chip = card->pm_private_dat
1400 if (chip->suspend)
1401 chip->suspend(chip);
1402 return 0;
1403 }
1404
1405 static int snd_cs4231_pm_resume(snd_card_t *c
1406 {
1407 cs4231_t *chip = card->pm_private_dat
1408 if (chip->resume)
1409 chip->resume(chip);
1410 return 0;
1411 }
1412 #endif /* CONFIG_PM */
1413
1414 #ifdef LEGACY_SUPPORT
1415
1416 static int snd_cs4231_free(cs4231_t *chip)
1417 {
1418 if (chip->res_port) {
1419 release_resource(chip->res_po
1420 kfree_nocheck(chip->res_port)
1421 }
1422 if (chip->res_cport) {
1423 release_resource(chip->res_cp
1424 kfree_nocheck(chip->res_cport
1425 }
1426 if (chip->irq >= 0) {
1427 disable_irq(chip->irq);
1428 if (!(chip->hwshare & CS4231_
1429 free_irq(chip->irq, (
1430 }
1431 if (!(chip->hwshare & CS4231_HWSHARE_
1432 snd_dma_disable(chip->dma1);
1433 free_dma(chip->dma1);
1434 }
1435 if (!(chip->hwshare & CS4231_HWSHARE_
1436 snd_dma_disable(chip->dma2);
1437 free_dma(chip->dma2);
1438 }
1439 if (chip->timer)
1440 snd_device_free(chip->card, c
1441 kfree(chip);
1442 return 0;
1443 }
1444
1445 static int snd_cs4231_dev_free(snd_device_t *
1446 {
1447 cs4231_t *chip = device->device_data;
1448 return snd_cs4231_free(chip);
1449 }
1450
1451 #endif /* LEGACY_SUPPORT */
1452
1453 const char *snd_cs4231_chip_id(cs4231_t *chip
1454 {
1455 switch (chip->hardware) {
1456 case CS4231_HW_CS4231: return "CS423
1457 case CS4231_HW_CS4231A: return "CS423
1458 case CS4231_HW_CS4232: return "CS423
1459 case CS4231_HW_CS4232A: return "CS423
1460 case CS4231_HW_CS4235: return "CS423
1461 case CS4231_HW_CS4236: return "CS423
1462 case CS4231_HW_CS4236B: return "CS423
1463 case CS4231_HW_CS4237B: return "CS423
1464 case CS4231_HW_CS4238B: return "CS423
1465 case CS4231_HW_CS4239: return "CS423
1466 case CS4231_HW_INTERWAVE: return "AMD
1467 case CS4231_HW_OPL3SA2: return chip->
1468 case CS4231_HW_AD1845: return "AD1845
1469 default: return "???";
1470 }
1471 }
1472
1473 static int snd_cs4231_new(snd_card_t * card,
1474 unsigned short hard
1475 unsigned short hwsh
1476 cs4231_t ** rchip)
1477 {
1478 cs4231_t *chip;
1479
1480 *rchip = NULL;
1481 chip = kcalloc(1, sizeof(*chip), GFP_
1482 if (chip == NULL)
1483 return -ENOMEM;
1484 chip->hardware = hardware;
1485 chip->hwshare = hwshare;
1486
1487 spin_lock_init(&chip->reg_lock);
1488 init_MUTEX(&chip->mce_mutex);
1489 init_MUTEX(&chip->open_mutex);
1490 chip->card = card;
1491 chip->rate_constraint = snd_cs4231_xr
1492 chip->set_playback_format = snd_cs423
1493 chip->set_capture_format = snd_cs4231
1494 memcpy(&chip->image, &snd_cs4231_orig
1495
1496 *rchip = chip;
1497 return 0;
1498 }
1499
1500 #ifdef LEGACY_SUPPORT
1501
1502 int snd_cs4231_create(snd_card_t * card,
1503 unsigned long port,
1504 unsigned long cport,
1505 int irq, int dma1, int
1506 unsigned short hardware
1507 unsigned short hwshare,
1508 cs4231_t ** rchip)
1509 {
1510 static snd_device_ops_t ops = {
1511 .dev_free = snd_cs4231_de
1512 };
1513 cs4231_t *chip;
1514 int err;
1515
1516 err = snd_cs4231_new(card, hardware,
1517 if (err < 0)
1518 return err;
1519
1520 chip->irq = -1;
1521 chip->dma1 = -1;
1522 chip->dma2 = -1;
1523
1524 if ((chip->res_port = request_region(
1525 snd_printk(KERN_ERR "cs4231:
1526 snd_cs4231_free(chip);
1527 return -EBUSY;
1528 }
1529 chip->port = port;
1530 if ((long)cport >= 0 && (chip->res_cp
1531 snd_printk(KERN_ERR "cs4231:
1532 snd_cs4231_free(chip);
1533 return -ENODEV;
1534 }
1535 chip->cport = cport;
1536 if (!(hwshare & CS4231_HWSHARE_IRQ) &
1537 snd_printk(KERN_ERR "cs4231:
1538 snd_cs4231_free(chip);
1539 return -EBUSY;
1540 }
1541 chip->irq = irq;
1542 if (!(hwshare & CS4231_HWSHARE_DMA1)
1543 snd_printk(KERN_ERR "cs4231:
1544 snd_cs4231_free(chip);
1545 return -EBUSY;
1546 }
1547 chip->dma1 = dma1;
1548 if (!(hwshare & CS4231_HWSHARE_DMA2)
1549 snd_printk(KERN_ERR "cs4231:
1550 snd_cs4231_free(chip);
1551 return -EBUSY;
1552 }
1553 if (dma1 == dma2 || dma2 < 0) {
1554 chip->single_dma = 1;
1555 chip->dma2 = chip->dma1;
1556 } else
1557 chip->dma2 = dma2;
1558
1559 /* global setup */
1560 if (snd_cs4231_probe(chip) < 0) {
1561 snd_cs4231_free(chip);
1562 return -ENODEV;
1563 }
1564 snd_cs4231_init(chip);
1565
1566 if (chip->hardware & CS4231_HW_CS4232
1567 if (chip->res_cport == NULL)
1568 snd_printk("CS4232 co
1569 }
1570
1571 /* Register device */
1572 if ((err = snd_device_new(card, SNDRV
1573 snd_cs4231_free(chip);
1574 return err;
1575 }
1576
1577 #ifdef CONFIG_PM
1578 /* Power Management */
1579 chip->suspend = snd_cs4231_suspend;
1580 chip->resume = snd_cs4231_resume;
1581 snd_card_set_isa_pm_callback(card, sn
1582 #endif
1583
1584 *rchip = chip;
1585 return 0;
1586 }
1587
1588 #endif /* LEGACY_SUPPORT */
1589
1590 static snd_pcm_ops_t snd_cs4231_playback_ops
1591 .open = snd_cs4231_playback_o
1592 .close = snd_cs4231_playback_c
1593 .ioctl = snd_pcm_lib_ioctl,
1594 .hw_params = snd_cs4231_playback_h
1595 .hw_free = snd_cs4231_playback_h
1596 .prepare = snd_cs4231_playback_p
1597 .trigger = snd_cs4231_trigger,
1598 .pointer = snd_cs4231_playback_p
1599 };
1600
1601 static snd_pcm_ops_t snd_cs4231_capture_ops =
1602 .open = snd_cs4231_capture_op
1603 .close = snd_cs4231_capture_cl
1604 .ioctl = snd_pcm_lib_ioctl,
1605 .hw_params = snd_cs4231_capture_hw
1606 .hw_free = snd_cs4231_capture_hw
1607 .prepare = snd_cs4231_capture_pr
1608 .trigger = snd_cs4231_trigger,
1609 .pointer = snd_cs4231_capture_po
1610 };
1611
1612 static void snd_cs4231_pcm_free(snd_pcm_t *pc
1613 {
1614 cs4231_t *chip = pcm->private_data;
1615 chip->pcm = NULL;
1616 snd_pcm_lib_preallocate_free_for_all(
1617 }
1618
1619 int snd_cs4231_pcm(cs4231_t *chip, int device
1620 {
1621 snd_pcm_t *pcm;
1622 int err;
1623
1624 if ((err = snd_pcm_new(chip->card, "C
1625 return err;
1626
1627 spin_lock_init(&chip->reg_lock);
1628 init_MUTEX(&chip->mce_mutex);
1629 init_MUTEX(&chip->open_mutex);
1630
1631 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM
1632 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM
1633
1634 /* global setup */
1635 pcm->private_data = chip;
1636 pcm->private_free = snd_cs4231_pcm_fr
1637 pcm->info_flags = 0;
1638 if (chip->single_dma)
1639 pcm->info_flags |= SNDRV_PCM_
1640 if (chip->hardware != CS4231_HW_INTER
1641 pcm->info_flags |= SNDRV_PCM_
1642 strcpy(pcm->name, snd_cs4231_chip_id(
1643
1644 #ifdef LEGACY_SUPPORT
1645 snd_pcm_lib_preallocate_pages_for_all
1646
1647
1648 #else
1649 # ifdef EBUS_SUPPORT
1650 if (chip->ebus_flag) {
1651 snd_pcm_lib_preallocate_pages
1652
1653
1654 } else {
1655 # endif
1656 # ifdef SBUS_SUPPORT
1657 snd_pcm_lib_preallocate_pages
1658
1659
1660 # endif
1661 # ifdef EBUS_SUPPORT
1662 }
1663 # endif
1664 #endif
1665
1666 chip->pcm = pcm;
1667 if (rpcm)
1668 *rpcm = pcm;
1669 return 0;
1670 }
1671
1672 static void snd_cs4231_timer_free(snd_timer_t
1673 {
1674 cs4231_t *chip = timer->private_data;
1675 chip->timer = NULL;
1676 }
1677
1678 int snd_cs4231_timer(cs4231_t *chip, int devi
1679 {
1680 snd_timer_t *timer;
1681 snd_timer_id_t tid;
1682 int err;
1683
1684 /* Timer initialization */
1685 tid.dev_class = SNDRV_TIMER_CLASS_CAR
1686 tid.dev_sclass = SNDRV_TIMER_SCLASS_N
1687 tid.card = chip->card->number;
1688 tid.device = device;
1689 tid.subdevice = 0;
1690 if ((err = snd_timer_new(chip->card,
1691 return err;
1692 strcpy(timer->name, snd_cs4231_chip_i
1693 timer->private_data = chip;
1694 timer->private_free = snd_cs4231_time
1695 timer->hw = snd_cs4231_timer_table;
1696 chip->timer = timer;
1697 if (rtimer)
1698 *rtimer = timer;
1699 return 0;
1700 }
1701
1702 /*
1703 * MIXER part
1704 */
1705
1706 static int snd_cs4231_info_mux(snd_kcontrol_t
1707 {
1708 static char *texts[4] = {
1709 "Line", "Aux", "Mic", "Mix"
1710 };
1711 static char *opl3sa_texts[4] = {
1712 "Line", "CD", "Mic", "Mix"
1713 };
1714 static char *gusmax_texts[4] = {
1715 "Line", "Synth", "Mic", "Mix"
1716 };
1717 char **ptexts = texts;
1718 cs4231_t *chip = snd_kcontrol_chip(kc
1719
1720 snd_assert(chip->card != NULL, return
1721 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENU
1722 uinfo->count = 2;
1723 uinfo->value.enumerated.items = 4;
1724 if (uinfo->value.enumerated.item > 3)
1725 uinfo->value.enumerated.item
1726 if (!strcmp(chip->card->driver, "GUS
1727 ptexts = gusmax_texts;
1728 switch (chip->hardware) {
1729 case CS4231_HW_INTERWAVE: ptexts = gu
1730 case CS4231_HW_OPL3SA2: ptexts = opl3
1731 }
1732 strcpy(uinfo->value.enumerated.name,
1733 return 0;
1734 }
1735
1736 static int snd_cs4231_get_mux(snd_kcontrol_t
1737 {
1738 cs4231_t *chip = snd_kcontrol_chip(kc
1739 unsigned long flags;
1740
1741 spin_lock_irqsave(&chip->reg_lock, fl
1742 ucontrol->value.enumerated.item[0] =
1743 ucontrol->value.enumerated.item[1] =
1744 spin_unlock_irqrestore(&chip->reg_loc
1745 return 0;
1746 }
1747
1748 static int snd_cs4231_put_mux(snd_kcontrol_t
1749 {
1750 cs4231_t *chip = snd_kcontrol_chip(kc
1751 unsigned long flags;
1752 unsigned short left, right;
1753 int change;
1754
1755 if (ucontrol->value.enumerated.item[0
1756 ucontrol->value.enumerated.item[1
1757 return -EINVAL;
1758 left = ucontrol->value.enumerated.ite
1759 right = ucontrol->value.enumerated.it
1760 spin_lock_irqsave(&chip->reg_lock, fl
1761 left = (chip->image[CS4231_LEFT_INPUT
1762 right = (chip->image[CS4231_RIGHT_INP
1763 change = left != chip->image[CS4231_L
1764 right != chip->image[CS4231_
1765 snd_cs4231_out(chip, CS4231_LEFT_INPU
1766 snd_cs4231_out(chip, CS4231_RIGHT_INP
1767 spin_unlock_irqrestore(&chip->reg_loc
1768 return change;
1769 }
1770
1771 int snd_cs4231_info_single(snd_kcontrol_t *kc
1772 {
1773 int mask = (kcontrol->private_value >
1774
1775 uinfo->type = mask == 1 ? SNDRV_CTL_E
1776 uinfo->count = 1;
1777 uinfo->value.integer.min = 0;
1778 uinfo->value.integer.max = mask;
1779 return 0;
1780 }
1781
1782 int snd_cs4231_get_single(snd_kcontrol_t * kc
1783 {
1784 cs4231_t *chip = snd_kcontrol_chip(kc
1785 unsigned long flags;
1786 int reg = kcontrol->private_value & 0
1787 int shift = (kcontrol->private_value
1788 int mask = (kcontrol->private_value >
1789 int invert = (kcontrol->private_value
1790
1791 spin_lock_irqsave(&chip->reg_lock, fl
1792 ucontrol->value.integer.value[0] = (c
1793 spin_unlock_irqrestore(&chip->reg_loc
1794 if (invert)
1795 ucontrol->value.integer.value
1796 return 0;
1797 }
1798
1799 int snd_cs4231_put_single(snd_kcontrol_t * kc
1800 {
1801 cs4231_t *chip = snd_kcontrol_chip(kc
1802 unsigned long flags;
1803 int reg = kcontrol->private_value & 0
1804 int shift = (kcontrol->private_value
1805 int mask = (kcontrol->private_value >
1806 int invert = (kcontrol->private_value
1807 int change;
1808 unsigned short val;
1809
1810 val = (ucontrol->value.integer.value[
1811 if (invert)
1812 val = mask - val;
1813 val <<= shift;
1814 spin_lock_irqsave(&chip->reg_lock, fl
1815 val = (chip->image[reg] & ~(mask << s
1816 change = val != chip->image[reg];
1817 snd_cs4231_out(chip, reg, val);
1818 spin_unlock_irqrestore(&chip->reg_loc
1819 return change;
1820 }
1821
1822 int snd_cs4231_info_double(snd_kcontrol_t *kc
1823 {
1824 int mask = (kcontrol->private_value >
1825
1826 uinfo->type = mask == 1 ? SNDRV_CTL_E
1827 uinfo->count = 2;
1828 uinfo->value.integer.min = 0;
1829 uinfo->value.integer.max = mask;
1830 return 0;
1831 }
1832
1833 int snd_cs4231_get_double(snd_kcontrol_t * kc
1834 {
1835 cs4231_t *chip = snd_kcontrol_chip(kc
1836 unsigned long flags;
1837 int left_reg = kcontrol->private_valu
1838 int right_reg = (kcontrol->private_va
1839 int shift_left = (kcontrol->private_v
1840 int shift_right = (kcontrol->private_
1841 int mask = (kcontrol->private_value >
1842 int invert = (kcontrol->private_value
1843
1844 spin_lock_irqsave(&chip->reg_lock, fl
1845 ucontrol->value.integer.value[0] = (c
1846 ucontrol->value.integer.value[1] = (c
1847 spin_unlock_irqrestore(&chip->reg_loc
1848 if (invert) {
1849 ucontrol->value.integer.value
1850 ucontrol->value.integer.value
1851 }
1852 return 0;
1853 }
1854
1855 int snd_cs4231_put_double(snd_kcontrol_t * kc
1856 {
1857 cs4231_t *chip = snd_kcontrol_chip(kc
1858 unsigned long flags;
1859 int left_reg = kcontrol->private_valu
1860 int right_reg = (kcontrol->private_va
1861 int shift_left = (kcontrol->private_v
1862 int shift_right = (kcontrol->private_
1863 int mask = (kcontrol->private_value >
1864 int invert = (kcontrol->private_value
1865 int change;
1866 unsigned short val1, val2;
1867
1868 val1 = ucontrol->value.integer.value[
1869 val2 = ucontrol->value.integer.value[
1870 if (invert) {
1871 val1 = mask - val1;
1872 val2 = mask - val2;
1873 }
1874 val1 <<= shift_left;
1875 val2 <<= shift_right;
1876 spin_lock_irqsave(&chip->reg_lock, fl
1877 val1 = (chip->image[left_reg] & ~(mas
1878 val2 = (chip->image[right_reg] & ~(ma
1879 change = val1 != chip->image[left_reg
1880 snd_cs4231_out(chip, left_reg, val1);
1881 snd_cs4231_out(chip, right_reg, val2)
1882 spin_unlock_irqrestore(&chip->reg_loc
1883 return change;
1884 }
1885
1886 static snd_kcontrol_new_t snd_cs4231_controls
1887 CS4231_DOUBLE("PCM Playback Switch", 0, CS423
1888 CS4231_DOUBLE("PCM Playback Volume", 0, CS423
1889 CS4231_DOUBLE("Line Playback Switch", 0, CS42
1890 CS4231_DOUBLE("Line Playback Volume", 0, CS42
1891 CS4231_DOUBLE("Aux Playback Switch", 0, CS423
1892 CS4231_DOUBLE("Aux Playback Volume", 0, CS423
1893 CS4231_DOUBLE("Aux Playback Switch", 1, CS423
1894 CS4231_DOUBLE("Aux Playback Volume", 1, CS423
1895 CS4231_SINGLE("Mono Playback Switch", 0, CS42
1896 CS4231_SINGLE("Mono Playback Volume", 0, CS42
1897 CS4231_SINGLE("Mono Output Playback Switch",
1898 CS4231_SINGLE("Mono Output Playback Bypass",
1899 CS4231_DOUBLE("Capture Volume", 0, CS4231_LEF
1900 {
1901 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1902 .name = "Capture Source",
1903 .info = snd_cs4231_info_mux,
1904 .get = snd_cs4231_get_mux,
1905 .put = snd_cs4231_put_mux,
1906 },
1907 CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INP
1908 CS4231_SINGLE("Loopback Capture Switch", 0, C
1909 CS4231_SINGLE("Loopback Capture Volume", 0, C
1910 };
1911
1912 int snd_cs4231_mixer(cs4231_t *chip)
1913 {
1914 snd_card_t *card;
1915 unsigned int idx;
1916 int err;
1917
1918 snd_assert(chip != NULL && chip->pcm
1919
1920 card = chip->card;
1921
1922 strcpy(card->mixername, chip->pcm->na
1923
1924 for (idx = 0; idx < ARRAY_SIZE(snd_cs
1925 if ((err = snd_ctl_add(card,
1926 return err;
1927 }
1928 return 0;
1929 }
1930
1931 EXPORT_SYMBOL(snd_cs4231_out);
1932 EXPORT_SYMBOL(snd_cs4231_in);
1933 EXPORT_SYMBOL(snd_cs4236_ext_out);
1934 EXPORT_SYMBOL(snd_cs4236_ext_in);
1935 EXPORT_SYMBOL(snd_cs4231_mce_up);
1936 EXPORT_SYMBOL(snd_cs4231_mce_down);
1937 EXPORT_SYMBOL(snd_cs4231_interrupt);
1938 EXPORT_SYMBOL(snd_cs4231_chip_id);
1939 EXPORT_SYMBOL(snd_cs4231_create);
1940 EXPORT_SYMBOL(snd_cs4231_pcm);
1941 EXPORT_SYMBOL(snd_cs4231_mixer);
1942 EXPORT_SYMBOL(snd_cs4231_timer);
1943 EXPORT_SYMBOL(snd_cs4231_info_single);
1944 EXPORT_SYMBOL(snd_cs4231_get_single);
1945 EXPORT_SYMBOL(snd_cs4231_put_single);
1946 EXPORT_SYMBOL(snd_cs4231_info_double);
1947 EXPORT_SYMBOL(snd_cs4231_get_double);
1948 EXPORT_SYMBOL(snd_cs4231_put_double);
1949
1950 /*
1951 * INIT part
1952 */
1953
1954 static int __init alsa_cs4231_init(void)
1955 {
1956 return 0;
1957 }
1958
1959 static void __exit alsa_cs4231_exit(void)
1960 {
1961 }
1962
1963 module_init(alsa_cs4231_init)
1964 module_exit(alsa_cs4231_exit)
1965
| This page was automatically generated by the LXR engine. |