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