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