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