1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <linux/delay.h>
28#include <linux/pm.h>
29#include <linux/init.h>
30#include <linux/interrupt.h>
31#include <linux/slab.h>
32#include <linux/ioport.h>
33#include <sound/core.h>
34#include <sound/wss.h>
35#include <sound/pcm_params.h>
36#include <sound/tlv.h>
37
38#include <asm/io.h>
39#include <asm/dma.h>
40#include <asm/irq.h>
41
42MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
43MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips");
44MODULE_LICENSE("GPL");
45
46#if 0
47#define SNDRV_DEBUG_MCE
48#endif
49
50
51
52
53
54static unsigned char freq_bits[14] = {
55 0x00 | CS4231_XTAL2,
56 0x0E | CS4231_XTAL2,
57 0x00 | CS4231_XTAL1,
58 0x0E | CS4231_XTAL1,
59 0x02 | CS4231_XTAL2,
60 0x02 | CS4231_XTAL1,
61 0x04 | CS4231_XTAL2,
62 0x06 | CS4231_XTAL2,
63 0x04 | CS4231_XTAL1,
64 0x06 | CS4231_XTAL1,
65 0x0C | CS4231_XTAL2,
66 0x08 | CS4231_XTAL2,
67 0x0A | CS4231_XTAL2,
68 0x0C | CS4231_XTAL1
69};
70
71static unsigned int rates[14] = {
72 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050,
73 27042, 32000, 33075, 37800, 44100, 48000
74};
75
76static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
77 .count = ARRAY_SIZE(rates),
78 .list = rates,
79 .mask = 0,
80};
81
82static int snd_wss_xrate(struct snd_pcm_runtime *runtime)
83{
84 return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
85 &hw_constraints_rates);
86}
87
88static unsigned char snd_wss_original_image[32] =
89{
90 0x00,
91 0x00,
92 0x9f,
93 0x9f,
94 0x9f,
95 0x9f,
96 0xbf,
97 0xbf,
98 0x20,
99 CS4231_AUTOCALIB,
100 0x00,
101 0x00,
102 CS4231_MODE2,
103 0xfc,
104 0x00,
105 0x00,
106 0x80,
107 0x01,
108 0x9f,
109 0x9f,
110 0x00,
111 0x00,
112 0x00,
113 0x00,
114 0x00,
115 0x00,
116 0xcf,
117 0x00,
118 0x20,
119 0x00,
120 0x00,
121 0x00,
122};
123
124static unsigned char snd_opti93x_original_image[32] =
125{
126 0x00,
127 0x00,
128 0x88,
129 0x88,
130 0x88,
131 0x88,
132 0x80,
133 0x80,
134 0x00,
135 0x00,
136 0x00,
137 0x00,
138 0x0a,
139 0x00,
140 0x00,
141 0x00,
142 0x88,
143 0x88,
144 0x88,
145 0x88,
146 0x88,
147 0x88,
148 0x80,
149 0x80,
150 0x00,
151 0x00,
152 0x00,
153 0x00,
154 0x00,
155 0x00,
156 0x00,
157 0x00
158};
159
160
161
162
163
164static inline void wss_outb(struct snd_wss *chip, u8 offset, u8 val)
165{
166 outb(val, chip->port + offset);
167}
168
169static inline u8 wss_inb(struct snd_wss *chip, u8 offset)
170{
171 return inb(chip->port + offset);
172}
173
174static void snd_wss_wait(struct snd_wss *chip)
175{
176 int timeout;
177
178 for (timeout = 250;
179 timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
180 timeout--)
181 udelay(100);
182}
183
184static void snd_wss_dout(struct snd_wss *chip, unsigned char reg,
185 unsigned char value)
186{
187 int timeout;
188
189 for (timeout = 250;
190 timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
191 timeout--)
192 udelay(10);
193 wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
194 wss_outb(chip, CS4231P(REG), value);
195 mb();
196}
197
198void snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char value)
199{
200 snd_wss_wait(chip);
201#ifdef CONFIG_SND_DEBUG
202 if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
203 snd_printk(KERN_DEBUG "out: auto calibration time out "
204 "- reg = 0x%x, value = 0x%x\n", reg, value);
205#endif
206 wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
207 wss_outb(chip, CS4231P(REG), value);
208 chip->image[reg] = value;
209 mb();
210 snd_printdd("codec out - reg 0x%x = 0x%x\n",
211 chip->mce_bit | reg, value);
212}
213EXPORT_SYMBOL(snd_wss_out);
214
215unsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg)
216{
217 snd_wss_wait(chip);
218#ifdef CONFIG_SND_DEBUG
219 if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
220 snd_printk(KERN_DEBUG "in: auto calibration time out "
221 "- reg = 0x%x\n", reg);
222#endif
223 wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
224 mb();
225 return wss_inb(chip, CS4231P(REG));
226}
227EXPORT_SYMBOL(snd_wss_in);
228
229void snd_cs4236_ext_out(struct snd_wss *chip, unsigned char reg,
230 unsigned char val)
231{
232 wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
233 wss_outb(chip, CS4231P(REG),
234 reg | (chip->image[CS4236_EXT_REG] & 0x01));
235 wss_outb(chip, CS4231P(REG), val);
236 chip->eimage[CS4236_REG(reg)] = val;
237#if 0
238 printk(KERN_DEBUG "ext out : reg = 0x%x, val = 0x%x\n", reg, val);
239#endif
240}
241EXPORT_SYMBOL(snd_cs4236_ext_out);
242
243unsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg)
244{
245 wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
246 wss_outb(chip, CS4231P(REG),
247 reg | (chip->image[CS4236_EXT_REG] & 0x01));
248#if 1
249 return wss_inb(chip, CS4231P(REG));
250#else
251 {
252 unsigned char res;
253 res = wss_inb(chip, CS4231P(REG));
254 printk(KERN_DEBUG "ext in : reg = 0x%x, val = 0x%x\n",
255 reg, res);
256 return res;
257 }
258#endif
259}
260EXPORT_SYMBOL(snd_cs4236_ext_in);
261
262#if 0
263
264static void snd_wss_debug(struct snd_wss *chip)
265{
266 printk(KERN_DEBUG
267 "CS4231 REGS: INDEX = 0x%02x "
268 " STATUS = 0x%02x\n",
269 wss_inb(chip, CS4231P(REGSEL)),
270 wss_inb(chip, CS4231P(STATUS)));
271 printk(KERN_DEBUG
272 " 0x00: left input = 0x%02x "
273 " 0x10: alt 1 (CFIG 2) = 0x%02x\n",
274 snd_wss_in(chip, 0x00),
275 snd_wss_in(chip, 0x10));
276 printk(KERN_DEBUG
277 " 0x01: right input = 0x%02x "
278 " 0x11: alt 2 (CFIG 3) = 0x%02x\n",
279 snd_wss_in(chip, 0x01),
280 snd_wss_in(chip, 0x11));
281 printk(KERN_DEBUG
282 " 0x02: GF1 left input = 0x%02x "
283 " 0x12: left line in = 0x%02x\n",
284 snd_wss_in(chip, 0x02),
285 snd_wss_in(chip, 0x12));
286 printk(KERN_DEBUG
287 " 0x03: GF1 right input = 0x%02x "
288 " 0x13: right line in = 0x%02x\n",
289 snd_wss_in(chip, 0x03),
290 snd_wss_in(chip, 0x13));
291 printk(KERN_DEBUG
292 " 0x04: CD left input = 0x%02x "
293 " 0x14: timer low = 0x%02x\n",
294 snd_wss_in(chip, 0x04),
295 snd_wss_in(chip, 0x14));
296 printk(KERN_DEBUG
297 " 0x05: CD right input = 0x%02x "
298 " 0x15: timer high = 0x%02x\n",
299 snd_wss_in(chip, 0x05),
300 snd_wss_in(chip, 0x15));
301 printk(KERN_DEBUG
302 " 0x06: left output = 0x%02x "
303 " 0x16: left MIC (PnP) = 0x%02x\n",
304 snd_wss_in(chip, 0x06),
305 snd_wss_in(chip, 0x16));
306 printk(KERN_DEBUG
307 " 0x07: right output = 0x%02x "
308 " 0x17: right MIC (PnP) = 0x%02x\n",
309 snd_wss_in(chip, 0x07),
310 snd_wss_in(chip, 0x17));
311 printk(KERN_DEBUG
312 " 0x08: playback format = 0x%02x "
313 " 0x18: IRQ status = 0x%02x\n",
314 snd_wss_in(chip, 0x08),
315 snd_wss_in(chip, 0x18));
316 printk(KERN_DEBUG
317 " 0x09: iface (CFIG 1) = 0x%02x "
318 " 0x19: left line out = 0x%02x\n",
319 snd_wss_in(chip, 0x09),
320 snd_wss_in(chip, 0x19));
321 printk(KERN_DEBUG
322 " 0x0a: pin control = 0x%02x "
323 " 0x1a: mono control = 0x%02x\n",
324 snd_wss_in(chip, 0x0a),
325 snd_wss_in(chip, 0x1a));
326 printk(KERN_DEBUG
327 " 0x0b: init & status = 0x%02x "
328 " 0x1b: right line out = 0x%02x\n",
329 snd_wss_in(chip, 0x0b),
330 snd_wss_in(chip, 0x1b));
331 printk(KERN_DEBUG
332 " 0x0c: revision & mode = 0x%02x "
333 " 0x1c: record format = 0x%02x\n",
334 snd_wss_in(chip, 0x0c),
335 snd_wss_in(chip, 0x1c));
336 printk(KERN_DEBUG
337 " 0x0d: loopback = 0x%02x "
338 " 0x1d: var freq (PnP) = 0x%02x\n",
339 snd_wss_in(chip, 0x0d),
340 snd_wss_in(chip, 0x1d));
341 printk(KERN_DEBUG
342 " 0x0e: ply upr count = 0x%02x "
343 " 0x1e: ply lwr count = 0x%02x\n",
344 snd_wss_in(chip, 0x0e),
345 snd_wss_in(chip, 0x1e));
346 printk(KERN_DEBUG
347 " 0x0f: rec upr count = 0x%02x "
348 " 0x1f: rec lwr count = 0x%02x\n",
349 snd_wss_in(chip, 0x0f),
350 snd_wss_in(chip, 0x1f));
351}
352
353#endif
354
355
356
357
358
359static void snd_wss_busy_wait(struct snd_wss *chip)
360{
361 int timeout;
362
363
364 for (timeout = 5; timeout > 0; timeout--)
365 wss_inb(chip, CS4231P(REGSEL));
366
367 for (timeout = 25000;
368 timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
369 timeout--)
370 udelay(10);
371}
372
373void snd_wss_mce_up(struct snd_wss *chip)
374{
375 unsigned long flags;
376 int timeout;
377
378 snd_wss_wait(chip);
379#ifdef CONFIG_SND_DEBUG
380 if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
381 snd_printk(KERN_DEBUG
382 "mce_up - auto calibration time out (0)\n");
383#endif
384 spin_lock_irqsave(&chip->reg_lock, flags);
385 chip->mce_bit |= CS4231_MCE;
386 timeout = wss_inb(chip, CS4231P(REGSEL));
387 if (timeout == 0x80)
388 snd_printk(KERN_DEBUG "mce_up [0x%lx]: "
389 "serious init problem - codec still busy\n",
390 chip->port);
391 if (!(timeout & CS4231_MCE))
392 wss_outb(chip, CS4231P(REGSEL),
393 chip->mce_bit | (timeout & 0x1f));
394 spin_unlock_irqrestore(&chip->reg_lock, flags);
395}
396EXPORT_SYMBOL(snd_wss_mce_up);
397
398void snd_wss_mce_down(struct snd_wss *chip)
399{
400 unsigned long flags;
401 unsigned long end_time;
402 int timeout;
403 int hw_mask = WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK | WSS_HW_AD1848;
404
405 snd_wss_busy_wait(chip);
406
407#ifdef CONFIG_SND_DEBUG
408 if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
409 snd_printk(KERN_DEBUG "mce_down [0x%lx] - "
410 "auto calibration time out (0)\n",
411 (long)CS4231P(REGSEL));
412#endif
413 spin_lock_irqsave(&chip->reg_lock, flags);
414 chip->mce_bit &= ~CS4231_MCE;
415 timeout = wss_inb(chip, CS4231P(REGSEL));
416 wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
417 spin_unlock_irqrestore(&chip->reg_lock, flags);
418 if (timeout == 0x80)
419 snd_printk(KERN_DEBUG "mce_down [0x%lx]: "
420 "serious init problem - codec still busy\n",
421 chip->port);
422 if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask))
423 return;
424
425
426
427
428
429
430 msleep(1);
431
432 snd_printdd("(1) jiffies = %lu\n", jiffies);
433
434
435 end_time = jiffies + msecs_to_jiffies(250);
436 while (snd_wss_in(chip, CS4231_TEST_INIT) &
437 CS4231_CALIB_IN_PROGRESS) {
438
439 if (time_after(jiffies, end_time)) {
440 snd_printk(KERN_ERR "mce_down - "
441 "auto calibration time out (2)\n");
442 return;
443 }
444 msleep(1);
445 }
446
447 snd_printdd("(2) jiffies = %lu\n", jiffies);
448
449
450 end_time = jiffies + msecs_to_jiffies(100);
451 while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
452 if (time_after(jiffies, end_time)) {
453 snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n");
454 return;
455 }
456 msleep(1);
457 }
458
459 snd_printdd("(3) jiffies = %lu\n", jiffies);
460 snd_printd("mce_down - exit = 0x%x\n", wss_inb(chip, CS4231P(REGSEL)));
461}
462EXPORT_SYMBOL(snd_wss_mce_down);
463
464static unsigned int snd_wss_get_count(unsigned char format, unsigned int size)
465{
466 switch (format & 0xe0) {
467 case CS4231_LINEAR_16:
468 case CS4231_LINEAR_16_BIG:
469 size >>= 1;
470 break;
471 case CS4231_ADPCM_16:
472 return size >> 2;
473 }
474 if (format & CS4231_STEREO)
475 size >>= 1;
476 return size;
477}
478
479static int snd_wss_trigger(struct snd_pcm_substream *substream,
480 int cmd)
481{
482 struct snd_wss *chip = snd_pcm_substream_chip(substream);
483 int result = 0;
484 unsigned int what;
485 struct snd_pcm_substream *s;
486 int do_start;
487
488 switch (cmd) {
489 case SNDRV_PCM_TRIGGER_START:
490 case SNDRV_PCM_TRIGGER_RESUME:
491 do_start = 1; break;
492 case SNDRV_PCM_TRIGGER_STOP:
493 case SNDRV_PCM_TRIGGER_SUSPEND:
494 do_start = 0; break;
495 default:
496 return -EINVAL;
497 }
498
499 what = 0;
500 snd_pcm_group_for_each_entry(s, substream) {
501 if (s == chip->playback_substream) {
502 what |= CS4231_PLAYBACK_ENABLE;
503 snd_pcm_trigger_done(s, substream);
504 } else if (s == chip->capture_substream) {
505 what |= CS4231_RECORD_ENABLE;
506 snd_pcm_trigger_done(s, substream);
507 }
508 }
509 spin_lock(&chip->reg_lock);
510 if (do_start) {
511 chip->image[CS4231_IFACE_CTRL] |= what;
512 if (chip->trigger)
513 chip->trigger(chip, what, 1);
514 } else {
515 chip->image[CS4231_IFACE_CTRL] &= ~what;
516 if (chip->trigger)
517 chip->trigger(chip, what, 0);
518 }
519 snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
520 spin_unlock(&chip->reg_lock);
521#if 0
522 snd_wss_debug(chip);
523#endif
524 return result;
525}
526
527
528
529
530
531static unsigned char snd_wss_get_rate(unsigned int rate)
532{
533 int i;
534
535 for (i = 0; i < ARRAY_SIZE(rates); i++)
536 if (rate == rates[i])
537 return freq_bits[i];
538
539 return freq_bits[ARRAY_SIZE(rates) - 1];
540}
541
542static unsigned char snd_wss_get_format(struct snd_wss *chip,
543 int format,
544 int channels)
545{
546 unsigned char rformat;
547
548 rformat = CS4231_LINEAR_8;
549 switch (format) {
550 case SNDRV_PCM_FORMAT_MU_LAW: rformat = CS4231_ULAW_8; break;
551 case SNDRV_PCM_FORMAT_A_LAW: rformat = CS4231_ALAW_8; break;
552 case SNDRV_PCM_FORMAT_S16_LE: rformat = CS4231_LINEAR_16; break;
553 case SNDRV_PCM_FORMAT_S16_BE: rformat = CS4231_LINEAR_16_BIG; break;
554 case SNDRV_PCM_FORMAT_IMA_ADPCM: rformat = CS4231_ADPCM_16; break;
555 }
556 if (channels > 1)
557 rformat |= CS4231_STEREO;
558#if 0
559 snd_printk(KERN_DEBUG "get_format: 0x%x (mode=0x%x)\n", format, mode);
560#endif
561 return rformat;
562}
563
564static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute)
565{
566 unsigned long flags;
567
568 mute = mute ? 0x80 : 0;
569 spin_lock_irqsave(&chip->reg_lock, flags);
570 if (chip->calibrate_mute == mute) {
571 spin_unlock_irqrestore(&chip->reg_lock, flags);
572 return;
573 }
574 if (!mute) {
575 snd_wss_dout(chip, CS4231_LEFT_INPUT,
576 chip->image[CS4231_LEFT_INPUT]);
577 snd_wss_dout(chip, CS4231_RIGHT_INPUT,
578 chip->image[CS4231_RIGHT_INPUT]);
579 snd_wss_dout(chip, CS4231_LOOPBACK,
580 chip->image[CS4231_LOOPBACK]);
581 } else {
582 snd_wss_dout(chip, CS4231_LEFT_INPUT,
583 0);
584 snd_wss_dout(chip, CS4231_RIGHT_INPUT,
585 0);
586 snd_wss_dout(chip, CS4231_LOOPBACK,
587 0xfd);
588 }
589
590 snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT,
591 mute | chip->image[CS4231_AUX1_LEFT_INPUT]);
592 snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT,
593 mute | chip->image[CS4231_AUX1_RIGHT_INPUT]);
594 snd_wss_dout(chip, CS4231_AUX2_LEFT_INPUT,
595 mute | chip->image[CS4231_AUX2_LEFT_INPUT]);
596 snd_wss_dout(chip, CS4231_AUX2_RIGHT_INPUT,
597 mute | chip->image[CS4231_AUX2_RIGHT_INPUT]);
598 snd_wss_dout(chip, CS4231_LEFT_OUTPUT,
599 mute | chip->image[CS4231_LEFT_OUTPUT]);
600 snd_wss_dout(chip, CS4231_RIGHT_OUTPUT,
601 mute | chip->image[CS4231_RIGHT_OUTPUT]);
602 if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
603 snd_wss_dout(chip, CS4231_LEFT_LINE_IN,
604 mute | chip->image[CS4231_LEFT_LINE_IN]);
605 snd_wss_dout(chip, CS4231_RIGHT_LINE_IN,
606 mute | chip->image[CS4231_RIGHT_LINE_IN]);
607 snd_wss_dout(chip, CS4231_MONO_CTRL,
608 mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]);
609 }
610 if (chip->hardware == WSS_HW_INTERWAVE) {
611 snd_wss_dout(chip, CS4231_LEFT_MIC_INPUT,
612 mute | chip->image[CS4231_LEFT_MIC_INPUT]);
613 snd_wss_dout(chip, CS4231_RIGHT_MIC_INPUT,
614 mute | chip->image[CS4231_RIGHT_MIC_INPUT]);
615 snd_wss_dout(chip, CS4231_LINE_LEFT_OUTPUT,
616 mute | chip->image[CS4231_LINE_LEFT_OUTPUT]);
617 snd_wss_dout(chip, CS4231_LINE_RIGHT_OUTPUT,
618 mute | chip->image[CS4231_LINE_RIGHT_OUTPUT]);
619 }
620 chip->calibrate_mute = mute;
621 spin_unlock_irqrestore(&chip->reg_lock, flags);
622}
623
624static void snd_wss_playback_format(struct snd_wss *chip,
625 struct snd_pcm_hw_params *params,
626 unsigned char pdfr)
627{
628 unsigned long flags;
629 int full_calib = 1;
630
631 mutex_lock(&chip->mce_mutex);
632 if (chip->hardware == WSS_HW_CS4231A ||
633 (chip->hardware & WSS_HW_CS4232_MASK)) {
634 spin_lock_irqsave(&chip->reg_lock, flags);
635 if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (pdfr & 0x0f)) {
636 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
637 chip->image[CS4231_ALT_FEATURE_1] | 0x10);
638 chip->image[CS4231_PLAYBK_FORMAT] = pdfr;
639 snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
640 chip->image[CS4231_PLAYBK_FORMAT]);
641 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
642 chip->image[CS4231_ALT_FEATURE_1] &= ~0x10);
643 udelay(100);
644 full_calib = 0;
645 }
646 spin_unlock_irqrestore(&chip->reg_lock, flags);
647 } else if (chip->hardware == WSS_HW_AD1845) {
648 unsigned rate = params_rate(params);
649
650
651
652
653
654
655
656
657
658
659 spin_lock_irqsave(&chip->reg_lock, flags);
660 snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (pdfr & 0xf0));
661 snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff);
662 snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff);
663 full_calib = 0;
664 spin_unlock_irqrestore(&chip->reg_lock, flags);
665 }
666 if (full_calib) {
667 snd_wss_mce_up(chip);
668 spin_lock_irqsave(&chip->reg_lock, flags);
669 if (chip->hardware != WSS_HW_INTERWAVE && !chip->single_dma) {
670 if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)
671 pdfr = (pdfr & 0xf0) |
672 (chip->image[CS4231_REC_FORMAT] & 0x0f);
673 } else {
674 chip->image[CS4231_PLAYBK_FORMAT] = pdfr;
675 }
676 snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr);
677 spin_unlock_irqrestore(&chip->reg_lock, flags);
678 if (chip->hardware == WSS_HW_OPL3SA2)
679 udelay(100);
680 snd_wss_mce_down(chip);
681 }
682 mutex_unlock(&chip->mce_mutex);
683}
684
685static void snd_wss_capture_format(struct snd_wss *chip,
686 struct snd_pcm_hw_params *params,
687 unsigned char cdfr)
688{
689 unsigned long flags;
690 int full_calib = 1;
691
692 mutex_lock(&chip->mce_mutex);
693 if (chip->hardware == WSS_HW_CS4231A ||
694 (chip->hardware & WSS_HW_CS4232_MASK)) {
695 spin_lock_irqsave(&chip->reg_lock, flags);
696 if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (cdfr & 0x0f) ||
697 (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
698 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
699 chip->image[CS4231_ALT_FEATURE_1] | 0x20);
700 snd_wss_out(chip, CS4231_REC_FORMAT,
701 chip->image[CS4231_REC_FORMAT] = cdfr);
702 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
703 chip->image[CS4231_ALT_FEATURE_1] &= ~0x20);
704 full_calib = 0;
705 }
706 spin_unlock_irqrestore(&chip->reg_lock, flags);
707 } else if (chip->hardware == WSS_HW_AD1845) {
708 unsigned rate = params_rate(params);
709
710
711
712
713
714
715
716
717
718
719 spin_lock_irqsave(&chip->reg_lock, flags);
720 snd_wss_out(chip, CS4231_REC_FORMAT, (cdfr & 0xf0));
721 snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff);
722 snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff);
723 full_calib = 0;
724 spin_unlock_irqrestore(&chip->reg_lock, flags);
725 }
726 if (full_calib) {
727 snd_wss_mce_up(chip);
728 spin_lock_irqsave(&chip->reg_lock, flags);
729 if (chip->hardware != WSS_HW_INTERWAVE &&
730 !(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
731 if (chip->single_dma)
732 snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr);
733 else
734 snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
735 (chip->image[CS4231_PLAYBK_FORMAT] & 0xf0) |
736 (cdfr & 0x0f));
737 spin_unlock_irqrestore(&chip->reg_lock, flags);
738 snd_wss_mce_down(chip);
739 snd_wss_mce_up(chip);
740 spin_lock_irqsave(&chip->reg_lock, flags);
741 }
742 if (chip->hardware & WSS_HW_AD1848_MASK)
743 snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr);
744 else
745 snd_wss_out(chip, CS4231_REC_FORMAT, cdfr);
746 spin_unlock_irqrestore(&chip->reg_lock, flags);
747 snd_wss_mce_down(chip);
748 }
749 mutex_unlock(&chip->mce_mutex);
750}
751
752
753
754
755
756static unsigned long snd_wss_timer_resolution(struct snd_timer *timer)
757{
758 struct snd_wss *chip = snd_timer_chip(timer);
759 if (chip->hardware & WSS_HW_CS4236B_MASK)
760 return 14467;
761 else
762 return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920;
763}
764
765static int snd_wss_timer_start(struct snd_timer *timer)
766{
767 unsigned long flags;
768 unsigned int ticks;
769 struct snd_wss *chip = snd_timer_chip(timer);
770 spin_lock_irqsave(&chip->reg_lock, flags);
771 ticks = timer->sticks;
772 if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 ||
773 (unsigned char)(ticks >> 8) != chip->image[CS4231_TIMER_HIGH] ||
774 (unsigned char)ticks != chip->image[CS4231_TIMER_LOW]) {
775 chip->image[CS4231_TIMER_HIGH] = (unsigned char) (ticks >> 8);
776 snd_wss_out(chip, CS4231_TIMER_HIGH,
777 chip->image[CS4231_TIMER_HIGH]);
778 chip->image[CS4231_TIMER_LOW] = (unsigned char) ticks;
779 snd_wss_out(chip, CS4231_TIMER_LOW,
780 chip->image[CS4231_TIMER_LOW]);
781 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
782 chip->image[CS4231_ALT_FEATURE_1] |
783 CS4231_TIMER_ENABLE);
784 }
785 spin_unlock_irqrestore(&chip->reg_lock, flags);
786 return 0;
787}
788
789static int snd_wss_timer_stop(struct snd_timer *timer)
790{
791 unsigned long flags;
792 struct snd_wss *chip = snd_timer_chip(timer);
793 spin_lock_irqsave(&chip->reg_lock, flags);
794 chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE;
795 snd_wss_out(chip, CS4231_ALT_FEATURE_1,
796 chip->image[CS4231_ALT_FEATURE_1]);
797 spin_unlock_irqrestore(&chip->reg_lock, flags);
798 return 0;
799}
800
801static void snd_wss_init(struct snd_wss *chip)
802{
803 unsigned long flags;
804
805 snd_wss_calibrate_mute(chip, 1);
806 snd_wss_mce_down(chip);
807
808#ifdef SNDRV_DEBUG_MCE
809 snd_printk(KERN_DEBUG "init: (1)\n");
810#endif
811 snd_wss_mce_up(chip);
812 spin_lock_irqsave(&chip->reg_lock, flags);
813 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE |
814 CS4231_PLAYBACK_PIO |
815 CS4231_RECORD_ENABLE |
816 CS4231_RECORD_PIO |
817 CS4231_CALIB_MODE);
818 chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB;
819 snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
820 spin_unlock_irqrestore(&chip->reg_lock, flags);
821 snd_wss_mce_down(chip);
822
823#ifdef SNDRV_DEBUG_MCE
824 snd_printk(KERN_DEBUG "init: (2)\n");
825#endif
826
827 snd_wss_mce_up(chip);
828 spin_lock_irqsave(&chip->reg_lock, flags);
829 chip->image[CS4231_IFACE_CTRL] &= ~CS4231_AUTOCALIB;
830 snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
831 snd_wss_out(chip,
832 CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]);
833 spin_unlock_irqrestore(&chip->reg_lock, flags);
834 snd_wss_mce_down(chip);
835
836#ifdef SNDRV_DEBUG_MCE
837 snd_printk(KERN_DEBUG "init: (3) - afei = 0x%x\n",
838 chip->image[CS4231_ALT_FEATURE_1]);
839#endif
840
841 spin_lock_irqsave(&chip->reg_lock, flags);
842 snd_wss_out(chip, CS4231_ALT_FEATURE_2,
843 chip->image[CS4231_ALT_FEATURE_2]);
844 spin_unlock_irqrestore(&chip->reg_lock, flags);
845
846 snd_wss_mce_up(chip);
847 spin_lock_irqsave(&chip->reg_lock, flags);
848 snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
849 chip->image[CS4231_PLAYBK_FORMAT]);
850 spin_unlock_irqrestore(&chip->reg_lock, flags);
851 snd_wss_mce_down(chip);
852
853#ifdef SNDRV_DEBUG_MCE
854 snd_printk(KERN_DEBUG "init: (4)\n");
855#endif
856
857 snd_wss_mce_up(chip);
858 spin_lock_irqsave(&chip->reg_lock, flags);
859 if (!(chip->hardware & WSS_HW_AD1848_MASK))
860 snd_wss_out(chip, CS4231_REC_FORMAT,
861 chip->image[CS4231_REC_FORMAT]);
862 spin_unlock_irqrestore(&chip->reg_lock, flags);
863 snd_wss_mce_down(chip);
864 snd_wss_calibrate_mute(chip, 0);
865
866#ifdef SNDRV_DEBUG_MCE
867 snd_printk(KERN_DEBUG "init: (5)\n");
868#endif
869}
870
871static int snd_wss_open(struct snd_wss *chip, unsigned int mode)
872{
873 unsigned long flags;
874
875 mutex_lock(&chip->open_mutex);
876 if ((chip->mode & mode) ||
877 ((chip->mode & WSS_MODE_OPEN) && chip->single_dma)) {
878 mutex_unlock(&chip->open_mutex);
879 return -EAGAIN;
880 }
881 if (chip->mode & WSS_MODE_OPEN) {
882 chip->mode |= mode;
883 mutex_unlock(&chip->open_mutex);
884 return 0;
885 }
886
887 spin_lock_irqsave(&chip->reg_lock, flags);
888 if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
889 snd_wss_out(chip, CS4231_IRQ_STATUS,
890 CS4231_PLAYBACK_IRQ |
891 CS4231_RECORD_IRQ |
892 CS4231_TIMER_IRQ);
893 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
894 }
895 wss_outb(chip, CS4231P(STATUS), 0);
896 wss_outb(chip, CS4231P(STATUS), 0);
897 chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE;
898 snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
899 if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
900 snd_wss_out(chip, CS4231_IRQ_STATUS,
901 CS4231_PLAYBACK_IRQ |
902 CS4231_RECORD_IRQ |
903 CS4231_TIMER_IRQ);
904 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
905 }
906 spin_unlock_irqrestore(&chip->reg_lock, flags);
907
908 chip->mode = mode;
909 mutex_unlock(&chip->open_mutex);
910 return 0;
911}
912
913static void snd_wss_close(struct snd_wss *chip, unsigned int mode)
914{
915 unsigned long flags;
916
917 mutex_lock(&chip->open_mutex);
918 chip->mode &= ~mode;
919 if (chip->mode & WSS_MODE_OPEN) {
920 mutex_unlock(&chip->open_mutex);
921 return;
922 }
923
924 spin_lock_irqsave(&chip->reg_lock, flags);
925 if (!(chip->hardware & WSS_HW_AD1848_MASK))
926 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
927 wss_outb(chip, CS4231P(STATUS), 0);
928 wss_outb(chip, CS4231P(STATUS), 0);
929 chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE;
930 snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
931
932
933
934 if (chip->image[CS4231_IFACE_CTRL] & (CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
935 CS4231_RECORD_ENABLE | CS4231_RECORD_PIO)) {
936 spin_unlock_irqrestore(&chip->reg_lock, flags);
937 snd_wss_mce_up(chip);
938 spin_lock_irqsave(&chip->reg_lock, flags);
939 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
940 CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
941 snd_wss_out(chip, CS4231_IFACE_CTRL,
942 chip->image[CS4231_IFACE_CTRL]);
943 spin_unlock_irqrestore(&chip->reg_lock, flags);
944 snd_wss_mce_down(chip);
945 spin_lock_irqsave(&chip->reg_lock, flags);
946 }
947
948
949 if (!(chip->hardware & WSS_HW_AD1848_MASK))
950 snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
951 wss_outb(chip, CS4231P(STATUS), 0);
952 wss_outb(chip, CS4231P(STATUS), 0);
953 spin_unlock_irqrestore(&chip->reg_lock, flags);
954
955 chip->mode = 0;
956 mutex_unlock(&chip->open_mutex);
957}
958
959
960
961
962
963static int snd_wss_timer_open(struct snd_timer *timer)
964{
965 struct snd_wss *chip = snd_timer_chip(timer);
966 snd_wss_open(chip, WSS_MODE_TIMER);
967 return 0;
968}
969
970static int snd_wss_timer_close(struct snd_timer *timer)
971{
972 struct snd_wss *chip = snd_timer_chip(timer);
973 snd_wss_close(chip, WSS_MODE_TIMER);
974 return 0;
975}
976
977static struct snd_timer_hardware snd_wss_timer_table =
978{
979 .flags = SNDRV_TIMER_HW_AUTO,
980 .resolution = 9945,
981 .ticks = 65535,
982 .open = snd_wss_timer_open,
983 .close = snd_wss_timer_close,
984 .c_resolution = snd_wss_timer_resolution,
985 .start = snd_wss_timer_start,
986 .stop = snd_wss_timer_stop,
987};
988
989
990
991
992
993static int snd_wss_playback_hw_params(struct snd_pcm_substream *substream,
994 struct snd_pcm_hw_params *hw_params)
995{
996 struct snd_wss *chip = snd_pcm_substream_chip(substream);
997 unsigned char new_pdfr;
998 int err;
999
1000 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
1001 return err;
1002 new_pdfr = snd_wss_get_format(chip, params_format(hw_params),
1003 params_channels(hw_params)) |
1004 snd_wss_get_rate(params_rate(hw_params));
1005 chip->set_playback_format(chip, hw_params, new_pdfr);
1006 return 0;
1007}
1008
1009static int snd_wss_playback_hw_free(struct snd_pcm_substream *substream)
1010{
1011 return snd_pcm_lib_free_pages(substream);
1012}
1013
1014static int snd_wss_playback_prepare(struct snd_pcm_substream *substream)
1015{
1016 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1017 struct snd_pcm_runtime *runtime = substream->runtime;
1018 unsigned long flags;
1019 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
1020 unsigned int count = snd_pcm_lib_period_bytes(substream);
1021
1022 spin_lock_irqsave(&chip->reg_lock, flags);
1023 chip->p_dma_size = size;
1024 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO);
1025 snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
1026 count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT], count) - 1;
1027 snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
1028 snd_wss_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8));
1029 spin_unlock_irqrestore(&chip->reg_lock, flags);
1030#if 0
1031 snd_wss_debug(chip);
1032#endif
1033 return 0;
1034}
1035
1036static int snd_wss_capture_hw_params(struct snd_pcm_substream *substream,
1037 struct snd_pcm_hw_params *hw_params)
1038{
1039 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1040 unsigned char new_cdfr;
1041 int err;
1042
1043 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
1044 return err;
1045 new_cdfr = snd_wss_get_format(chip, params_format(hw_params),
1046 params_channels(hw_params)) |
1047 snd_wss_get_rate(params_rate(hw_params));
1048 chip->set_capture_format(chip, hw_params, new_cdfr);
1049 return 0;
1050}
1051
1052static int snd_wss_capture_hw_free(struct snd_pcm_substream *substream)
1053{
1054 return snd_pcm_lib_free_pages(substream);
1055}
1056
1057static int snd_wss_capture_prepare(struct snd_pcm_substream *substream)
1058{
1059 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1060 struct snd_pcm_runtime *runtime = substream->runtime;
1061 unsigned long flags;
1062 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
1063 unsigned int count = snd_pcm_lib_period_bytes(substream);
1064
1065 spin_lock_irqsave(&chip->reg_lock, flags);
1066 chip->c_dma_size = size;
1067 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
1068 snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
1069 if (chip->hardware & WSS_HW_AD1848_MASK)
1070 count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT],
1071 count);
1072 else
1073 count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT],
1074 count);
1075 count--;
1076 if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) {
1077 snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
1078 snd_wss_out(chip, CS4231_PLY_UPR_CNT,
1079 (unsigned char) (count >> 8));
1080 } else {
1081 snd_wss_out(chip, CS4231_REC_LWR_CNT, (unsigned char) count);
1082 snd_wss_out(chip, CS4231_REC_UPR_CNT,
1083 (unsigned char) (count >> 8));
1084 }
1085 spin_unlock_irqrestore(&chip->reg_lock, flags);
1086 return 0;
1087}
1088
1089void snd_wss_overrange(struct snd_wss *chip)
1090{
1091 unsigned long flags;
1092 unsigned char res;
1093
1094 spin_lock_irqsave(&chip->reg_lock, flags);
1095 res = snd_wss_in(chip, CS4231_TEST_INIT);
1096 spin_unlock_irqrestore(&chip->reg_lock, flags);
1097 if (res & (0x08 | 0x02))
1098 chip->capture_substream->runtime->overrange++;
1099}
1100EXPORT_SYMBOL(snd_wss_overrange);
1101
1102irqreturn_t snd_wss_interrupt(int irq, void *dev_id)
1103{
1104 struct snd_wss *chip = dev_id;
1105 unsigned char status;
1106
1107 if (chip->hardware & WSS_HW_AD1848_MASK)
1108
1109 status = CS4231_PLAYBACK_IRQ;
1110 else
1111 status = snd_wss_in(chip, CS4231_IRQ_STATUS);
1112 if (status & CS4231_TIMER_IRQ) {
1113 if (chip->timer)
1114 snd_timer_interrupt(chip->timer, chip->timer->sticks);
1115 }
1116 if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) {
1117 if (status & CS4231_PLAYBACK_IRQ) {
1118 if (chip->mode & WSS_MODE_PLAY) {
1119 if (chip->playback_substream)
1120 snd_pcm_period_elapsed(chip->playback_substream);
1121 }
1122 if (chip->mode & WSS_MODE_RECORD) {
1123 if (chip->capture_substream) {
1124 snd_wss_overrange(chip);
1125 snd_pcm_period_elapsed(chip->capture_substream);
1126 }
1127 }
1128 }
1129 } else {
1130 if (status & CS4231_PLAYBACK_IRQ) {
1131 if (chip->playback_substream)
1132 snd_pcm_period_elapsed(chip->playback_substream);
1133 }
1134 if (status & CS4231_RECORD_IRQ) {
1135 if (chip->capture_substream) {
1136 snd_wss_overrange(chip);
1137 snd_pcm_period_elapsed(chip->capture_substream);
1138 }
1139 }
1140 }
1141
1142 spin_lock(&chip->reg_lock);
1143 status = ~CS4231_ALL_IRQS | ~status;
1144 if (chip->hardware & WSS_HW_AD1848_MASK)
1145 wss_outb(chip, CS4231P(STATUS), 0);
1146 else
1147 snd_wss_out(chip, CS4231_IRQ_STATUS, status);
1148 spin_unlock(&chip->reg_lock);
1149 return IRQ_HANDLED;
1150}
1151EXPORT_SYMBOL(snd_wss_interrupt);
1152
1153static snd_pcm_uframes_t snd_wss_playback_pointer(struct snd_pcm_substream *substream)
1154{
1155 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1156 size_t ptr;
1157
1158 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
1159 return 0;
1160 ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size);
1161 return bytes_to_frames(substream->runtime, ptr);
1162}
1163
1164static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *substream)
1165{
1166 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1167 size_t ptr;
1168
1169 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))
1170 return 0;
1171 ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);
1172 return bytes_to_frames(substream->runtime, ptr);
1173}
1174
1175
1176
1177
1178
1179static int snd_ad1848_probe(struct snd_wss *chip)
1180{
1181 unsigned long timeout = jiffies + msecs_to_jiffies(1000);
1182 unsigned long flags;
1183 unsigned char r;
1184 unsigned short hardware = 0;
1185 int err = 0;
1186 int i;
1187
1188 while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
1189 if (time_after(jiffies, timeout))
1190 return -ENODEV;
1191 cond_resched();
1192 }
1193 spin_lock_irqsave(&chip->reg_lock, flags);
1194
1195
1196 snd_wss_dout(chip, CS4231_MISC_INFO, 0);
1197
1198 snd_wss_dout(chip, CS4231_RIGHT_INPUT, 0x45);
1199 r = snd_wss_in(chip, CS4231_RIGHT_INPUT);
1200 if (r != 0x45) {
1201
1202 if ((r & ~CS4231_ENABLE_MIC_GAIN) != 0x45) {
1203 err = -ENODEV;
1204 goto out;
1205 }
1206 hardware = WSS_HW_AD1847;
1207 } else {
1208 snd_wss_dout(chip, CS4231_LEFT_INPUT, 0xaa);
1209 r = snd_wss_in(chip, CS4231_LEFT_INPUT);
1210
1211 if ((r | CS4231_ENABLE_MIC_GAIN) != 0xaa) {
1212 err = -ENODEV;
1213 goto out;
1214 }
1215 }
1216
1217
1218 wss_inb(chip, CS4231P(STATUS));
1219 wss_outb(chip, CS4231P(STATUS), 0);
1220 mb();
1221
1222 if ((chip->hardware & WSS_HW_TYPE_MASK) != WSS_HW_DETECT)
1223 goto out;
1224
1225 if (hardware) {
1226 chip->hardware = hardware;
1227 goto out;
1228 }
1229
1230 r = snd_wss_in(chip, CS4231_MISC_INFO);
1231
1232
1233 snd_wss_dout(chip, CS4231_MISC_INFO, CS4231_MODE2);
1234 for (i = 0; i < 16; i++) {
1235 if (snd_wss_in(chip, i) != snd_wss_in(chip, 16 + i)) {
1236
1237 if ((r & 0xf) != 0xa)
1238 goto out_mode;
1239
1240
1241
1242
1243 snd_wss_dout(chip, CS4231_VERSION, 0);
1244 r = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
1245 if (!r)
1246 chip->hardware = WSS_HW_CMI8330;
1247 goto out_mode;
1248 }
1249 }
1250 if (r & 0x80)
1251 chip->hardware = WSS_HW_CS4248;
1252 else
1253 chip->hardware = WSS_HW_AD1848;
1254out_mode:
1255 snd_wss_dout(chip, CS4231_MISC_INFO, 0);
1256out:
1257 spin_unlock_irqrestore(&chip->reg_lock, flags);
1258 return err;
1259}
1260
1261static int snd_wss_probe(struct snd_wss *chip)
1262{
1263 unsigned long flags;
1264 int i, id, rev, regnum;
1265 unsigned char *ptr;
1266 unsigned int hw;
1267
1268 id = snd_ad1848_probe(chip);
1269 if (id < 0)
1270 return id;
1271
1272 hw = chip->hardware;
1273 if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) {
1274 for (i = 0; i < 50; i++) {
1275 mb();
1276 if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
1277 msleep(2);
1278 else {
1279 spin_lock_irqsave(&chip->reg_lock, flags);
1280 snd_wss_out(chip, CS4231_MISC_INFO,
1281 CS4231_MODE2);
1282 id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f;
1283 spin_unlock_irqrestore(&chip->reg_lock, flags);
1284 if (id == 0x0a)
1285 break;
1286 }
1287 }
1288 snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id);
1289 if (id != 0x0a)
1290 return -ENODEV;
1291
1292 rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
1293 snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev);
1294 if (rev == 0x80) {
1295 unsigned char tmp = snd_wss_in(chip, 23);
1296 snd_wss_out(chip, 23, ~tmp);
1297 if (snd_wss_in(chip, 23) != tmp)
1298 chip->hardware = WSS_HW_AD1845;
1299 else
1300 chip->hardware = WSS_HW_CS4231;
1301 } else if (rev == 0xa0) {
1302 chip->hardware = WSS_HW_CS4231A;
1303 } else if (rev == 0xa2) {
1304 chip->hardware = WSS_HW_CS4232;
1305 } else if (rev == 0xb2) {
1306 chip->hardware = WSS_HW_CS4232A;
1307 } else if (rev == 0x83) {
1308 chip->hardware = WSS_HW_CS4236;
1309 } else if (rev == 0x03) {
1310 chip->hardware = WSS_HW_CS4236B;
1311 } else {
1312 snd_printk(KERN_ERR
1313 "unknown CS chip with version 0x%x\n", rev);
1314 return -ENODEV;
1315 }
1316 }
1317 spin_lock_irqsave(&chip->reg_lock, flags);
1318 wss_inb(chip, CS4231P(STATUS));
1319 wss_outb(chip, CS4231P(STATUS), 0);
1320 mb();
1321 spin_unlock_irqrestore(&chip->reg_lock, flags);
1322
1323 if (!(chip->hardware & WSS_HW_AD1848_MASK))
1324 chip->image[CS4231_MISC_INFO] = CS4231_MODE2;
1325 switch (chip->hardware) {
1326 case WSS_HW_INTERWAVE:
1327 chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3;
1328 break;
1329 case WSS_HW_CS4235:
1330 case WSS_HW_CS4236B:
1331 case WSS_HW_CS4237B:
1332 case WSS_HW_CS4238B:
1333 case WSS_HW_CS4239:
1334 if (hw == WSS_HW_DETECT3)
1335 chip->image[CS4231_MISC_INFO] = CS4231_4236_MODE3;
1336 else
1337 chip->hardware = WSS_HW_CS4236;
1338 break;
1339 }
1340
1341 chip->image[CS4231_IFACE_CTRL] =
1342 (chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA) |
1343 (chip->single_dma ? CS4231_SINGLE_DMA : 0);
1344 if (chip->hardware != WSS_HW_OPTI93X) {
1345 chip->image[CS4231_ALT_FEATURE_1] = 0x80;
1346 chip->image[CS4231_ALT_FEATURE_2] =
1347 chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01;
1348 }
1349
1350 if (chip->hardware == WSS_HW_AD1845)
1351 chip->image[AD1845_PWR_DOWN] = 8;
1352
1353 ptr = (unsigned char *) &chip->image;
1354 regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32;
1355 snd_wss_mce_down(chip);
1356 spin_lock_irqsave(&chip->reg_lock, flags);
1357 for (i = 0; i < regnum; i++)
1358 snd_wss_out(chip, i, *ptr++);
1359 spin_unlock_irqrestore(&chip->reg_lock, flags);
1360 snd_wss_mce_up(chip);
1361 snd_wss_mce_down(chip);
1362
1363 mdelay(2);
1364
1365
1366 if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) {
1367 if (chip->hardware == WSS_HW_CS4236B) {
1368 rev = snd_cs4236_ext_in(chip, CS4236_VERSION);
1369 snd_cs4236_ext_out(chip, CS4236_VERSION, 0xff);
1370 id = snd_cs4236_ext_in(chip, CS4236_VERSION);
1371 snd_cs4236_ext_out(chip, CS4236_VERSION, rev);
1372 snd_printdd("CS4231: ext version; rev = 0x%x, id = 0x%x\n", rev, id);
1373 if ((id & 0x1f) == 0x1d) {
1374 chip->hardware = WSS_HW_CS4235;
1375 switch (id >> 5) {
1376 case 4:
1377 case 5:
1378 case 6:
1379 break;
1380 default:
1381 snd_printk(KERN_WARNING
1382 "unknown CS4235 chip "
1383 "(enhanced version = 0x%x)\n",
1384 id);
1385 }
1386 } else if ((id & 0x1f) == 0x0b) {
1387 switch (id >> 5) {
1388 case 4:
1389 case 5:
1390 case 6:
1391 case 7:
1392 chip->hardware = WSS_HW_CS4236B;
1393 break;
1394 default:
1395 snd_printk(KERN_WARNING
1396 "unknown CS4236 chip "
1397 "(enhanced version = 0x%x)\n",
1398 id);
1399 }
1400 } else if ((id & 0x1f) == 0x08) {
1401 chip->hardware = WSS_HW_CS4237B;
1402 switch (id >> 5) {
1403 case 4:
1404 case 5:
1405 case 6:
1406 case 7:
1407 break;
1408 default:
1409 snd_printk(KERN_WARNING
1410 "unknown CS4237B chip "
1411 "(enhanced version = 0x%x)\n",
1412 id);
1413 }
1414 } else if ((id & 0x1f) == 0x09) {
1415 chip->hardware = WSS_HW_CS4238B;
1416 switch (id >> 5) {
1417 case 5:
1418 case 6:
1419 case 7:
1420 break;
1421 default:
1422 snd_printk(KERN_WARNING
1423 "unknown CS4238B chip "
1424 "(enhanced version = 0x%x)\n",
1425 id);
1426 }
1427 } else if ((id & 0x1f) == 0x1e) {
1428 chip->hardware = WSS_HW_CS4239;
1429 switch (id >> 5) {
1430 case 4:
1431 case 5:
1432 case 6:
1433 break;
1434 default:
1435 snd_printk(KERN_WARNING
1436 "unknown CS4239 chip "
1437 "(enhanced version = 0x%x)\n",
1438 id);
1439 }
1440 } else {
1441 snd_printk(KERN_WARNING
1442 "unknown CS4236/CS423xB chip "
1443 "(enhanced version = 0x%x)\n", id);
1444 }
1445 }
1446 }
1447 return 0;
1448}
1449
1450
1451
1452
1453
1454static struct snd_pcm_hardware snd_wss_playback =
1455{
1456 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1457 SNDRV_PCM_INFO_MMAP_VALID |
1458 SNDRV_PCM_INFO_RESUME |
1459 SNDRV_PCM_INFO_SYNC_START),
1460 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
1461 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
1462 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1463 .rate_min = 5510,
1464 .rate_max = 48000,
1465 .channels_min = 1,
1466 .channels_max = 2,
1467 .buffer_bytes_max = (128*1024),
1468 .period_bytes_min = 64,
1469 .period_bytes_max = (128*1024),
1470 .periods_min = 1,
1471 .periods_max = 1024,
1472 .fifo_size = 0,
1473};
1474
1475static struct snd_pcm_hardware snd_wss_capture =
1476{
1477 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1478 SNDRV_PCM_INFO_MMAP_VALID |
1479 SNDRV_PCM_INFO_RESUME |
1480 SNDRV_PCM_INFO_SYNC_START),
1481 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
1482 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
1483 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1484 .rate_min = 5510,
1485 .rate_max = 48000,
1486 .channels_min = 1,
1487 .channels_max = 2,
1488 .buffer_bytes_max = (128*1024),
1489 .period_bytes_min = 64,
1490 .period_bytes_max = (128*1024),
1491 .periods_min = 1,
1492 .periods_max = 1024,
1493 .fifo_size = 0,
1494};
1495
1496
1497
1498
1499
1500static int snd_wss_playback_open(struct snd_pcm_substream *substream)
1501{
1502 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1503 struct snd_pcm_runtime *runtime = substream->runtime;
1504 int err;
1505
1506 runtime->hw = snd_wss_playback;
1507
1508
1509 if (chip->hardware & WSS_HW_AD1848_MASK)
1510 runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
1511 SNDRV_PCM_FMTBIT_S16_BE);
1512
1513
1514 if (chip->hardware == WSS_HW_INTERWAVE && chip->dma1 > 3)
1515 runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW;
1516
1517
1518 if (chip->hardware == WSS_HW_CS4235 ||
1519 chip->hardware == WSS_HW_CS4239)
1520 runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
1521
1522 snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
1523 snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
1524
1525 if (chip->claim_dma) {
1526 if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0)
1527 return err;
1528 }
1529
1530 err = snd_wss_open(chip, WSS_MODE_PLAY);
1531 if (err < 0) {
1532 if (chip->release_dma)
1533 chip->release_dma(chip, chip->dma_private_data, chip->dma1);
1534 snd_free_pages(runtime->dma_area, runtime->dma_bytes);
1535 return err;
1536 }
1537 chip->playback_substream = substream;
1538 snd_pcm_set_sync(substream);
1539 chip->rate_constraint(runtime);
1540 return 0;
1541}
1542
1543static int snd_wss_capture_open(struct snd_pcm_substream *substream)
1544{
1545 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1546 struct snd_pcm_runtime *runtime = substream->runtime;
1547 int err;
1548
1549 runtime->hw = snd_wss_capture;
1550
1551
1552 if (chip->hardware & WSS_HW_AD1848_MASK)
1553 runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
1554 SNDRV_PCM_FMTBIT_S16_BE);
1555
1556
1557 if (chip->hardware == WSS_HW_CS4235 ||
1558 chip->hardware == WSS_HW_CS4239 ||
1559 chip->hardware == WSS_HW_OPTI93X)
1560 runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 |
1561 SNDRV_PCM_FMTBIT_S16_LE;
1562
1563 snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
1564 snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
1565
1566 if (chip->claim_dma) {
1567 if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0)
1568 return err;
1569 }
1570
1571 err = snd_wss_open(chip, WSS_MODE_RECORD);
1572 if (err < 0) {
1573 if (chip->release_dma)
1574 chip->release_dma(chip, chip->dma_private_data, chip->dma2);
1575 snd_free_pages(runtime->dma_area, runtime->dma_bytes);
1576 return err;
1577 }
1578 chip->capture_substream = substream;
1579 snd_pcm_set_sync(substream);
1580 chip->rate_constraint(runtime);
1581 return 0;
1582}
1583
1584static int snd_wss_playback_close(struct snd_pcm_substream *substream)
1585{
1586 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1587
1588 chip->playback_substream = NULL;
1589 snd_wss_close(chip, WSS_MODE_PLAY);
1590 return 0;
1591}
1592
1593static int snd_wss_capture_close(struct snd_pcm_substream *substream)
1594{
1595 struct snd_wss *chip = snd_pcm_substream_chip(substream);
1596
1597 chip->capture_substream = NULL;
1598 snd_wss_close(chip, WSS_MODE_RECORD);
1599 return 0;
1600}
1601
1602static void snd_wss_thinkpad_twiddle(struct snd_wss *chip, int on)
1603{
1604 int tmp;
1605
1606 if (!chip->thinkpad_flag)
1607 return;
1608
1609 outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
1610 tmp = inb(AD1848_THINKPAD_CTL_PORT2);
1611
1612 if (on)
1613
1614 tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
1615 else
1616
1617 tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
1618
1619 outb(tmp, AD1848_THINKPAD_CTL_PORT2);
1620}
1621
1622#ifdef CONFIG_PM
1623
1624
1625static void snd_wss_suspend(struct snd_wss *chip)
1626{
1627 int reg;
1628 unsigned long flags;
1629
1630 snd_pcm_suspend_all(chip->pcm);
1631 spin_lock_irqsave(&chip->reg_lock, flags);
1632 for (reg = 0; reg < 32; reg++)
1633 chip->image[reg] = snd_wss_in(chip, reg);
1634 spin_unlock_irqrestore(&chip->reg_lock, flags);
1635 if (chip->thinkpad_flag)
1636 snd_wss_thinkpad_twiddle(chip, 0);
1637}
1638
1639
1640static void snd_wss_resume(struct snd_wss *chip)
1641{
1642 int reg;
1643 unsigned long flags;
1644
1645
1646 if (chip->thinkpad_flag)
1647 snd_wss_thinkpad_twiddle(chip, 1);
1648 snd_wss_mce_up(chip);
1649 spin_lock_irqsave(&chip->reg_lock, flags);
1650 for (reg = 0; reg < 32; reg++) {
1651 switch (reg) {
1652 case CS4231_VERSION:
1653 break;
1654 default:
1655 snd_wss_out(chip, reg, chip->image[reg]);
1656 break;
1657 }
1658 }
1659 spin_unlock_irqrestore(&chip->reg_lock, flags);
1660#if 1
1661 snd_wss_mce_down(chip);
1662#else
1663
1664
1665
1666
1667 snd_wss_busy_wait(chip);
1668 spin_lock_irqsave(&chip->reg_lock, flags);
1669 chip->mce_bit &= ~CS4231_MCE;
1670 timeout = wss_inb(chip, CS4231P(REGSEL));
1671 wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
1672 spin_unlock_irqrestore(&chip->reg_lock, flags);
1673 if (timeout == 0x80)
1674 snd_printk(KERN_ERR "down [0x%lx]: serious init problem "
1675 "- codec still busy\n", chip->port);
1676 if ((timeout & CS4231_MCE) == 0 ||
1677 !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) {
1678 return;
1679 }
1680 snd_wss_busy_wait(chip);
1681#endif
1682}
1683#endif
1684
1685int snd_wss_free(struct snd_wss *chip)
1686{
1687 release_and_free_resource(chip->res_port);
1688 release_and_free_resource(chip->res_cport);
1689 if (chip->irq >= 0) {
1690 disable_irq(chip->irq);
1691 if (!(chip->hwshare & WSS_HWSHARE_IRQ))
1692 free_irq(chip->irq, (void *) chip);
1693 }
1694 if (!(chip->hwshare & WSS_HWSHARE_DMA1) && chip->dma1 >= 0) {
1695 snd_dma_disable(chip->dma1);
1696 free_dma(chip->dma1);
1697 }
1698 if (!(chip->hwshare & WSS_HWSHARE_DMA2) &&
1699 chip->dma2 >= 0 && chip->dma2 != chip->dma1) {
1700 snd_dma_disable(chip->dma2);
1701 free_dma(chip->dma2);
1702 }
1703 if (chip->timer)
1704 snd_device_free(chip->card, chip->timer);
1705 kfree(chip);
1706 return 0;
1707}
1708EXPORT_SYMBOL(snd_wss_free);
1709
1710static int snd_wss_dev_free(struct snd_device *device)
1711{
1712 struct snd_wss *chip = device->device_data;
1713 return snd_wss_free(chip);
1714}
1715
1716const char *snd_wss_chip_id(struct snd_wss *chip)
1717{
1718 switch (chip->hardware) {
1719 case WSS_HW_CS4231:
1720 return "CS4231";
1721 case WSS_HW_CS4231A:
1722 return "CS4231A";
1723 case WSS_HW_CS4232:
1724 return "CS4232";
1725 case WSS_HW_CS4232A:
1726 return "CS4232A";
1727 case WSS_HW_CS4235:
1728 return "CS4235";
1729 case WSS_HW_CS4236:
1730 return "CS4236";
1731 case WSS_HW_CS4236B:
1732 return "CS4236B";
1733 case WSS_HW_CS4237B:
1734 return "CS4237B";
1735 case WSS_HW_CS4238B:
1736 return "CS4238B";
1737 case WSS_HW_CS4239:
1738 return "CS4239";
1739 case WSS_HW_INTERWAVE:
1740 return "AMD InterWave";
1741 case WSS_HW_OPL3SA2:
1742 return chip->card->shortname;
1743 case WSS_HW_AD1845:
1744 return "AD1845";
1745 case WSS_HW_OPTI93X:
1746 return "OPTi 93x";
1747 case WSS_HW_AD1847:
1748 return "AD1847";
1749 case WSS_HW_AD1848:
1750 return "AD1848";
1751 case WSS_HW_CS4248:
1752 return "CS4248";
1753 case WSS_HW_CMI8330:
1754 return "CMI8330/C3D";
1755 default:
1756 return "???";
1757 }
1758}
1759EXPORT_SYMBOL(snd_wss_chip_id);
1760
1761static int snd_wss_new(struct snd_card *card,
1762 unsigned short hardware,
1763 unsigned short hwshare,
1764 struct snd_wss **rchip)
1765{
1766 struct snd_wss *chip;
1767
1768 *rchip = NULL;
1769 chip = kzalloc(sizeof(*chip), GFP_KERNEL);
1770 if (chip == NULL)
1771 return -ENOMEM;
1772 chip->hardware = hardware;
1773 chip->hwshare = hwshare;
1774
1775 spin_lock_init(&chip->reg_lock);
1776 mutex_init(&chip->mce_mutex);
1777 mutex_init(&chip->open_mutex);
1778 chip->card = card;
1779 chip->rate_constraint = snd_wss_xrate;
1780 chip->set_playback_format = snd_wss_playback_format;
1781 chip->set_capture_format = snd_wss_capture_format;
1782 if (chip->hardware == WSS_HW_OPTI93X)
1783 memcpy(&chip->image, &snd_opti93x_original_image,
1784 sizeof(snd_opti93x_original_image));
1785 else
1786 memcpy(&chip->image, &snd_wss_original_image,
1787 sizeof(snd_wss_original_image));
1788 if (chip->hardware & WSS_HW_AD1848_MASK) {
1789 chip->image[CS4231_PIN_CTRL] = 0;
1790 chip->image[CS4231_TEST_INIT] = 0;
1791 }
1792
1793 *rchip = chip;
1794 return 0;
1795}
1796
1797int snd_wss_create(struct snd_card *card,
1798 unsigned long port,
1799 unsigned long cport,
1800 int irq, int dma1, int dma2,
1801 unsigned short hardware,
1802 unsigned short hwshare,
1803 struct snd_wss **rchip)
1804{
1805 static struct snd_device_ops ops = {
1806 .dev_free = snd_wss_dev_free,
1807 };
1808 struct snd_wss *chip;
1809 int err;
1810
1811 err = snd_wss_new(card, hardware, hwshare, &chip);
1812 if (err < 0)
1813 return err;
1814
1815 chip->irq = -1;
1816 chip->dma1 = -1;
1817 chip->dma2 = -1;
1818
1819 chip->res_port = request_region(port, 4, "WSS");
1820 if (!chip->res_port) {
1821 snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port);
1822 snd_wss_free(chip);
1823 return -EBUSY;
1824 }
1825 chip->port = port;
1826 if ((long)cport >= 0) {
1827 chip->res_cport = request_region(cport, 8, "CS4232 Control");
1828 if (!chip->res_cport) {
1829 snd_printk(KERN_ERR
1830 "wss: can't grab control port 0x%lx\n", cport);
1831 snd_wss_free(chip);
1832 return -ENODEV;
1833 }
1834 }
1835 chip->cport = cport;
1836 if (!(hwshare & WSS_HWSHARE_IRQ))
1837 if (request_irq(irq, snd_wss_interrupt, IRQF_DISABLED,
1838 "WSS", (void *) chip)) {
1839 snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq);
1840 snd_wss_free(chip);
1841 return -EBUSY;
1842 }
1843 chip->irq = irq;
1844 if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) {
1845 snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1);
1846 snd_wss_free(chip);
1847 return -EBUSY;
1848 }
1849 chip->dma1 = dma1;
1850 if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 &&
1851 dma2 >= 0 && request_dma(dma2, "WSS - 2")) {
1852 snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2);
1853 snd_wss_free(chip);
1854 return -EBUSY;
1855 }
1856 if (dma1 == dma2 || dma2 < 0) {
1857 chip->single_dma = 1;
1858 chip->dma2 = chip->dma1;
1859 } else
1860 chip->dma2 = dma2;
1861
1862 if (hardware == WSS_HW_THINKPAD) {
1863 chip->thinkpad_flag = 1;
1864 chip->hardware = WSS_HW_DETECT;
1865 snd_wss_thinkpad_twiddle(chip, 1);
1866 }
1867
1868
1869 if (snd_wss_probe(chip) < 0) {
1870 snd_wss_free(chip);
1871 return -ENODEV;
1872 }
1873 snd_wss_init(chip);
1874
1875#if 0
1876 if (chip->hardware & WSS_HW_CS4232_MASK) {
1877 if (chip->res_cport == NULL)
1878 snd_printk(KERN_ERR "CS4232 control port features are "
1879 "not accessible\n");
1880 }
1881#endif
1882
1883
1884 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
1885 if (err < 0) {
1886 snd_wss_free(chip);
1887 return err;
1888 }
1889
1890#ifdef CONFIG_PM
1891
1892 chip->suspend = snd_wss_suspend;
1893 chip->resume = snd_wss_resume;
1894#endif
1895
1896 *rchip = chip;
1897 return 0;
1898}
1899EXPORT_SYMBOL(snd_wss_create);
1900
1901static struct snd_pcm_ops snd_wss_playback_ops = {
1902 .open = snd_wss_playback_open,
1903 .close = snd_wss_playback_close,
1904 .ioctl = snd_pcm_lib_ioctl,
1905 .hw_params = snd_wss_playback_hw_params,
1906 .hw_free = snd_wss_playback_hw_free,
1907 .prepare = snd_wss_playback_prepare,
1908 .trigger = snd_wss_trigger,
1909 .pointer = snd_wss_playback_pointer,
1910};
1911
1912static struct snd_pcm_ops snd_wss_capture_ops = {
1913 .open = snd_wss_capture_open,
1914 .close = snd_wss_capture_close,
1915 .ioctl = snd_pcm_lib_ioctl,
1916 .hw_params = snd_wss_capture_hw_params,
1917 .hw_free = snd_wss_capture_hw_free,
1918 .prepare = snd_wss_capture_prepare,
1919 .trigger = snd_wss_trigger,
1920 .pointer = snd_wss_capture_pointer,
1921};
1922
1923int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
1924{
1925 struct snd_pcm *pcm;
1926 int err;
1927
1928 err = snd_pcm_new(chip->card, "WSS", device, 1, 1, &pcm);
1929 if (err < 0)
1930 return err;
1931
1932 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops);
1933 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops);
1934
1935
1936 pcm->private_data = chip;
1937 pcm->info_flags = 0;
1938 if (chip->single_dma)
1939 pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
1940 if (chip->hardware != WSS_HW_INTERWAVE)
1941 pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
1942 strcpy(pcm->name, snd_wss_chip_id(chip));
1943
1944 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1945 snd_dma_isa_data(),
1946 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
1947
1948 chip->pcm = pcm;
1949 if (rpcm)
1950 *rpcm = pcm;
1951 return 0;
1952}
1953EXPORT_SYMBOL(snd_wss_pcm);
1954
1955static void snd_wss_timer_free(struct snd_timer *timer)
1956{
1957 struct snd_wss *chip = timer->private_data;
1958 chip->timer = NULL;
1959}
1960
1961int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer)
1962{
1963 struct snd_timer *timer;
1964 struct snd_timer_id tid;
1965 int err;
1966
1967
1968 tid.dev_class = SNDRV_TIMER_CLASS_CARD;
1969 tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
1970 tid.card = chip->card->number;
1971 tid.device = device;
1972 tid.subdevice = 0;
1973 if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0)
1974 return err;
1975 strcpy(timer->name, snd_wss_chip_id(chip));
1976 timer->private_data = chip;
1977 timer->private_free = snd_wss_timer_free;
1978 timer->hw = snd_wss_timer_table;
1979 chip->timer = timer;
1980 if (rtimer)
1981 *rtimer = timer;
1982 return 0;
1983}
1984EXPORT_SYMBOL(snd_wss_timer);
1985
1986
1987
1988
1989
1990static int snd_wss_info_mux(struct snd_kcontrol *kcontrol,
1991 struct snd_ctl_elem_info *uinfo)
1992{
1993 static char *texts[4] = {
1994 "Line", "Aux", "Mic", "Mix"
1995 };
1996 static char *opl3sa_texts[4] = {
1997 "Line", "CD", "Mic", "Mix"
1998 };
1999 static char *gusmax_texts[4] = {
2000 "Line", "Synth", "Mic", "Mix"
2001 };
2002 char **ptexts = texts;
2003 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2004
2005 if (snd_BUG_ON(!chip->card))
2006 return -EINVAL;
2007 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2008 uinfo->count = 2;
2009 uinfo->value.enumerated.items = 4;
2010 if (uinfo->value.enumerated.item > 3)
2011 uinfo->value.enumerated.item = 3;
2012 if (!strcmp(chip->card->driver, "GUS MAX"))
2013 ptexts = gusmax_texts;
2014 switch (chip->hardware) {
2015 case WSS_HW_INTERWAVE:
2016 ptexts = gusmax_texts;
2017 break;
2018 case WSS_HW_OPL3SA2:
2019 ptexts = opl3sa_texts;
2020 break;
2021 }
2022 strcpy(uinfo->value.enumerated.name, ptexts[uinfo->value.enumerated.item]);
2023 return 0;
2024}
2025
2026static int snd_wss_get_mux(struct snd_kcontrol *kcontrol,
2027 struct snd_ctl_elem_value *ucontrol)
2028{
2029 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2030 unsigned long flags;
2031
2032 spin_lock_irqsave(&chip->reg_lock, flags);
2033 ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6;
2034 ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6;
2035 spin_unlock_irqrestore(&chip->reg_lock, flags);
2036 return 0;
2037}
2038
2039static int snd_wss_put_mux(struct snd_kcontrol *kcontrol,
2040 struct snd_ctl_elem_value *ucontrol)
2041{
2042 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2043 unsigned long flags;
2044 unsigned short left, right;
2045 int change;
2046
2047 if (ucontrol->value.enumerated.item[0] > 3 ||
2048 ucontrol->value.enumerated.item[1] > 3)
2049 return -EINVAL;
2050 left = ucontrol->value.enumerated.item[0] << 6;
2051 right = ucontrol->value.enumerated.item[1] << 6;
2052 spin_lock_irqsave(&chip->reg_lock, flags);
2053 left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left;
2054 right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right;
2055 change = left != chip->image[CS4231_LEFT_INPUT] ||
2056 right != chip->image[CS4231_RIGHT_INPUT];
2057 snd_wss_out(chip, CS4231_LEFT_INPUT, left);
2058 snd_wss_out(chip, CS4231_RIGHT_INPUT, right);
2059 spin_unlock_irqrestore(&chip->reg_lock, flags);
2060 return change;
2061}
2062
2063int snd_wss_info_single(struct snd_kcontrol *kcontrol,
2064 struct snd_ctl_elem_info *uinfo)
2065{
2066 int mask = (kcontrol->private_value >> 16) & 0xff;
2067
2068 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
2069 uinfo->count = 1;
2070 uinfo->value.integer.min = 0;
2071 uinfo->value.integer.max = mask;
2072 return 0;
2073}
2074EXPORT_SYMBOL(snd_wss_info_single);
2075
2076int snd_wss_get_single(struct snd_kcontrol *kcontrol,
2077 struct snd_ctl_elem_value *ucontrol)
2078{
2079 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2080 unsigned long flags;
2081 int reg = kcontrol->private_value & 0xff;
2082 int shift = (kcontrol->private_value >> 8) & 0xff;
2083 int mask = (kcontrol->private_value >> 16) & 0xff;
2084 int invert = (kcontrol->private_value >> 24) & 0xff;
2085
2086 spin_lock_irqsave(&chip->reg_lock, flags);
2087 ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
2088 spin_unlock_irqrestore(&chip->reg_lock, flags);
2089 if (invert)
2090 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
2091 return 0;
2092}
2093EXPORT_SYMBOL(snd_wss_get_single);
2094
2095int snd_wss_put_single(struct snd_kcontrol *kcontrol,
2096 struct snd_ctl_elem_value *ucontrol)
2097{
2098 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2099 unsigned long flags;
2100 int reg = kcontrol->private_value & 0xff;
2101 int shift = (kcontrol->private_value >> 8) & 0xff;
2102 int mask = (kcontrol->private_value >> 16) & 0xff;
2103 int invert = (kcontrol->private_value >> 24) & 0xff;
2104 int change;
2105 unsigned short val;
2106
2107 val = (ucontrol->value.integer.value[0] & mask);
2108 if (invert)
2109 val = mask - val;
2110 val <<= shift;
2111 spin_lock_irqsave(&chip->reg_lock, flags);
2112 val = (chip->image[reg] & ~(mask << shift)) | val;
2113 change = val != chip->image[reg];
2114 snd_wss_out(chip, reg, val);
2115 spin_unlock_irqrestore(&chip->reg_lock, flags);
2116 return change;
2117}
2118EXPORT_SYMBOL(snd_wss_put_single);
2119
2120int snd_wss_info_double(struct snd_kcontrol *kcontrol,
2121 struct snd_ctl_elem_info *uinfo)
2122{
2123 int mask = (kcontrol->private_value >> 24) & 0xff;
2124
2125 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
2126 uinfo->count = 2;
2127 uinfo->value.integer.min = 0;
2128 uinfo->value.integer.max = mask;
2129 return 0;
2130}
2131EXPORT_SYMBOL(snd_wss_info_double);
2132
2133int snd_wss_get_double(struct snd_kcontrol *kcontrol,
2134 struct snd_ctl_elem_value *ucontrol)
2135{
2136 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2137 unsigned long flags;
2138 int left_reg = kcontrol->private_value & 0xff;
2139 int right_reg = (kcontrol->private_value >> 8) & 0xff;
2140 int shift_left = (kcontrol->private_value >> 16) & 0x07;
2141 int shift_right = (kcontrol->private_value >> 19) & 0x07;
2142 int mask = (kcontrol->private_value >> 24) & 0xff;
2143 int invert = (kcontrol->private_value >> 22) & 1;
2144
2145 spin_lock_irqsave(&chip->reg_lock, flags);
2146 ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
2147 ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
2148 spin_unlock_irqrestore(&chip->reg_lock, flags);
2149 if (invert) {
2150 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
2151 ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
2152 }
2153 return 0;
2154}
2155EXPORT_SYMBOL(snd_wss_get_double);
2156
2157int snd_wss_put_double(struct snd_kcontrol *kcontrol,
2158 struct snd_ctl_elem_value *ucontrol)
2159{
2160 struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2161 unsigned long flags;
2162 int left_reg = kcontrol->private_value & 0xff;
2163 int right_reg = (kcontrol->private_value >> 8) & 0xff;
2164 int shift_left = (kcontrol->private_value >> 16) & 0x07;
2165 int shift_right = (kcontrol->private_value >> 19) & 0x07;
2166 int mask = (kcontrol->private_value >> 24) & 0xff;
2167 int invert = (kcontrol->private_value >> 22) & 1;
2168 int change;
2169 unsigned short val1, val2;
2170
2171 val1 = ucontrol->value.integer.value[0] & mask;
2172 val2 = ucontrol->value.integer.value[1] & mask;
2173 if (invert) {
2174 val1 = mask - val1;
2175 val2 = mask - val2;
2176 }
2177 val1 <<= shift_left;
2178 val2 <<= shift_right;
2179 spin_lock_irqsave(&chip->reg_lock, flags);
2180 if (left_reg != right_reg) {
2181 val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
2182 val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
2183 change = val1 != chip->image[left_reg] ||
2184 val2 != chip->image[right_reg];
2185 snd_wss_out(chip, left_reg, val1);
2186 snd_wss_out(chip, right_reg, val2);
2187 } else {
2188 mask = (mask << shift_left) | (mask << shift_right);
2189 val1 = (chip->image[left_reg] & ~mask) | val1 | val2;
2190 change = val1 != chip->image[left_reg];
2191 snd_wss_out(chip, left_reg, val1);
2192 }
2193 spin_unlock_irqrestore(&chip->reg_lock, flags);
2194 return change;
2195}
2196EXPORT_SYMBOL(snd_wss_put_double);
2197
2198static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
2199static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
2200static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
2201
2202static struct snd_kcontrol_new snd_ad1848_controls[] = {
2203WSS_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT,
2204 7, 7, 1, 1),
2205WSS_DOUBLE_TLV("PCM Playback Volume", 0,
2206 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
2207 db_scale_6bit),
2208WSS_DOUBLE("Aux Playback Switch", 0,
2209 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
2210WSS_DOUBLE_TLV("Aux Playback Volume", 0,
2211 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
2212 db_scale_5bit_12db_max),
2213WSS_DOUBLE("Aux Playback Switch", 1,
2214 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
2215WSS_DOUBLE_TLV("Aux Playback Volume", 1,
2216 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
2217 db_scale_5bit_12db_max),
2218WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
2219 0, 0, 15, 0, db_scale_rec_gain),
2220{
2221 .name = "Capture Source",
2222 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2223 .info = snd_wss_info_mux,
2224 .get = snd_wss_get_mux,
2225 .put = snd_wss_put_mux,
2226},
2227WSS_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
2228WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 1, 63, 0,
2229 db_scale_6bit),
2230};
2231
2232static struct snd_kcontrol_new snd_wss_controls[] = {
2233WSS_DOUBLE("PCM Playback Switch", 0,
2234 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
2235WSS_DOUBLE("PCM Playback Volume", 0,
2236 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
2237WSS_DOUBLE("Line Playback Switch", 0,
2238 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
2239WSS_DOUBLE("Line Playback Volume", 0,
2240 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
2241WSS_DOUBLE("Aux Playback Switch", 0,
2242 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
2243WSS_DOUBLE("Aux Playback Volume", 0,
2244 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
2245WSS_DOUBLE("Aux Playback Switch", 1,
2246 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
2247WSS_DOUBLE("Aux Playback Volume", 1,
2248 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
2249WSS_SINGLE("Mono Playback Switch", 0,
2250 CS4231_MONO_CTRL, 7, 1, 1),
2251WSS_SINGLE("Mono Playback Volume", 0,
2252 CS4231_MONO_CTRL, 0, 15, 1),
2253WSS_SINGLE("Mono Output Playback Switch", 0,
2254 CS4231_MONO_CTRL, 6, 1, 1),
2255WSS_SINGLE("Mono Output Playback Bypass", 0,
2256 CS4231_MONO_CTRL, 5, 1, 0),
2257WSS_DOUBLE("Capture Volume", 0,
2258 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
2259{
2260 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2261 .name = "Capture Source",
2262 .info = snd_wss_info_mux,
2263 .get = snd_wss_get_mux,
2264 .put = snd_wss_put_mux,
2265},
2266WSS_DOUBLE("Mic Boost", 0,
2267 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
2268WSS_SINGLE("Loopback Capture Switch", 0,
2269 CS4231_LOOPBACK, 0, 1, 0),
2270WSS_SINGLE("Loopback Capture Volume", 0,
2271 CS4231_LOOPBACK, 2, 63, 1)
2272};
2273
2274static struct snd_kcontrol_new snd_opti93x_controls[] = {
2275WSS_DOUBLE("Master Playback Switch", 0,
2276 OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
2277WSS_DOUBLE("Master Playback Volume", 0,
2278 OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1),
2279WSS_DOUBLE("PCM Playback Switch", 0,
2280 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
2281WSS_DOUBLE("PCM Playback Volume", 0,
2282 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1),
2283WSS_DOUBLE("FM Playback Switch", 0,
2284 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
2285WSS_DOUBLE("FM Playback Volume", 0,
2286 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1),
2287WSS_DOUBLE("Line Playback Switch", 0,
2288 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
2289WSS_DOUBLE("Line Playback Volume", 0,
2290 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1),
2291WSS_DOUBLE("Mic Playback Switch", 0,
2292 OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),
2293WSS_DOUBLE("Mic Playback Volume", 0,
2294 OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1),
2295WSS_DOUBLE("Mic Boost", 0,
2296 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
2297WSS_DOUBLE("CD Playback Switch", 0,
2298 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
2299WSS_DOUBLE("CD Playback Volume", 0,
2300 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1),
2301WSS_DOUBLE("Aux Playback Switch", 0,
2302 OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),
2303WSS_DOUBLE("Aux Playback Volume", 0,
2304 OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1),
2305WSS_DOUBLE("Capture Volume", 0,
2306 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
2307{
2308 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2309 .name = "Capture Source",
2310 .info = snd_wss_info_mux,
2311 .get = snd_wss_get_mux,
2312 .put = snd_wss_put_mux,
2313}
2314};
2315
2316int snd_wss_mixer(struct snd_wss *chip)
2317{
2318 struct snd_card *card;
2319 unsigned int idx;
2320 int err;
2321
2322 if (snd_BUG_ON(!chip || !chip->pcm))
2323 return -EINVAL;
2324
2325 card = chip->card;
2326
2327 strcpy(card->mixername, chip->pcm->name);
2328
2329 if (chip->hardware == WSS_HW_OPTI93X)
2330 for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
2331 err = snd_ctl_add(card,
2332 snd_ctl_new1(&snd_opti93x_controls[idx],
2333 chip));
2334 if (err < 0)
2335 return err;
2336 }
2337 else if (chip->hardware & WSS_HW_AD1848_MASK)
2338 for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++) {
2339 err = snd_ctl_add(card,
2340 snd_ctl_new1(&snd_ad1848_controls[idx],
2341 chip));
2342 if (err < 0)
2343 return err;
2344 }
2345 else
2346 for (idx = 0; idx < ARRAY_SIZE(snd_wss_controls); idx++) {
2347 err = snd_ctl_add(card,
2348 snd_ctl_new1(&snd_wss_controls[idx],
2349 chip));
2350 if (err < 0)
2351 return err;
2352 }
2353 return 0;
2354}
2355EXPORT_SYMBOL(snd_wss_mixer);
2356
2357const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction)
2358{
2359 return direction == SNDRV_PCM_STREAM_PLAYBACK ?
2360 &snd_wss_playback_ops : &snd_wss_capture_ops;
2361}
2362EXPORT_SYMBOL(snd_wss_get_pcm_ops);
2363
2364
2365
2366
2367
2368static int __init alsa_wss_init(void)
2369{
2370 return 0;
2371}
2372
2373static void __exit alsa_wss_exit(void)
2374{
2375}
2376
2377module_init(alsa_wss_init);
2378module_exit(alsa_wss_exit);
2379