~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/isa/wss/wss_lib.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php