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

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

Version: ~ [ linux-5.16-rc3 ] ~ [ linux-5.15.5 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.82 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.162 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.218 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.256 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.291 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.293 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ 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.5 ] ~ [ 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                 if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1)) < 0)
1497                         return err;
1498         }
1499 
1500         err = snd_wss_open(chip, WSS_MODE_PLAY);
1501         if (err < 0) {
1502                 if (chip->release_dma)
1503                         chip->release_dma(chip, chip->dma_private_data, chip->dma1);
1504                 return err;
1505         }
1506         chip->playback_substream = substream;
1507         snd_pcm_set_sync(substream);
1508         chip->rate_constraint(runtime);
1509         return 0;
1510 }
1511 
1512 static int snd_wss_capture_open(struct snd_pcm_substream *substream)
1513 {
1514         struct snd_wss *chip = snd_pcm_substream_chip(substream);
1515         struct snd_pcm_runtime *runtime = substream->runtime;
1516         int err;
1517 
1518         runtime->hw = snd_wss_capture;
1519 
1520         /* hardware limitation of older chipsets */
1521         if (chip->hardware & WSS_HW_AD1848_MASK)
1522                 runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
1523                                          SNDRV_PCM_FMTBIT_S16_BE);
1524 
1525         /* hardware limitation of cheap chips */
1526         if (chip->hardware == WSS_HW_CS4235 ||
1527             chip->hardware == WSS_HW_CS4239 ||
1528             chip->hardware == WSS_HW_OPTI93X)
1529                 runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 |
1530                                       SNDRV_PCM_FMTBIT_S16_LE;
1531 
1532         snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
1533         snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
1534 
1535         if (chip->claim_dma) {
1536                 if ((err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2)) < 0)
1537                         return err;
1538         }
1539 
1540         err = snd_wss_open(chip, WSS_MODE_RECORD);
1541         if (err < 0) {
1542                 if (chip->release_dma)
1543                         chip->release_dma(chip, chip->dma_private_data, chip->dma2);
1544                 return err;
1545         }
1546         chip->capture_substream = substream;
1547         snd_pcm_set_sync(substream);
1548         chip->rate_constraint(runtime);
1549         return 0;
1550 }
1551 
1552 static int snd_wss_playback_close(struct snd_pcm_substream *substream)
1553 {
1554         struct snd_wss *chip = snd_pcm_substream_chip(substream);
1555 
1556         chip->playback_substream = NULL;
1557         snd_wss_close(chip, WSS_MODE_PLAY);
1558         return 0;
1559 }
1560 
1561 static int snd_wss_capture_close(struct snd_pcm_substream *substream)
1562 {
1563         struct snd_wss *chip = snd_pcm_substream_chip(substream);
1564 
1565         chip->capture_substream = NULL;
1566         snd_wss_close(chip, WSS_MODE_RECORD);
1567         return 0;
1568 }
1569 
1570 static void snd_wss_thinkpad_twiddle(struct snd_wss *chip, int on)
1571 {
1572         int tmp;
1573 
1574         if (!chip->thinkpad_flag)
1575                 return;
1576 
1577         outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
1578         tmp = inb(AD1848_THINKPAD_CTL_PORT2);
1579 
1580         if (on)
1581                 /* turn it on */
1582                 tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
1583         else
1584                 /* turn it off */
1585                 tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
1586 
1587         outb(tmp, AD1848_THINKPAD_CTL_PORT2);
1588 }
1589 
1590 #ifdef CONFIG_PM
1591 
1592 /* lowlevel suspend callback for CS4231 */
1593 static void snd_wss_suspend(struct snd_wss *chip)
1594 {
1595         int reg;
1596         unsigned long flags;
1597 
1598         spin_lock_irqsave(&chip->reg_lock, flags);
1599         for (reg = 0; reg < 32; reg++)
1600                 chip->image[reg] = snd_wss_in(chip, reg);
1601         spin_unlock_irqrestore(&chip->reg_lock, flags);
1602         if (chip->thinkpad_flag)
1603                 snd_wss_thinkpad_twiddle(chip, 0);
1604 }
1605 
1606 /* lowlevel resume callback for CS4231 */
1607 static void snd_wss_resume(struct snd_wss *chip)
1608 {
1609         int reg;
1610         unsigned long flags;
1611         /* int timeout; */
1612 
1613         if (chip->thinkpad_flag)
1614                 snd_wss_thinkpad_twiddle(chip, 1);
1615         snd_wss_mce_up(chip);
1616         spin_lock_irqsave(&chip->reg_lock, flags);
1617         for (reg = 0; reg < 32; reg++) {
1618                 switch (reg) {
1619                 case CS4231_VERSION:
1620                         break;
1621                 default:
1622                         snd_wss_out(chip, reg, chip->image[reg]);
1623                         break;
1624                 }
1625         }
1626         /* Yamaha needs this to resume properly */
1627         if (chip->hardware == WSS_HW_OPL3SA2)
1628                 snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
1629                             chip->image[CS4231_PLAYBK_FORMAT]);
1630         spin_unlock_irqrestore(&chip->reg_lock, flags);
1631 #if 1
1632         snd_wss_mce_down(chip);
1633 #else
1634         /* The following is a workaround to avoid freeze after resume on TP600E.
1635            This is the first half of copy of snd_wss_mce_down(), but doesn't
1636            include rescheduling.  -- iwai
1637            */
1638         snd_wss_busy_wait(chip);
1639         spin_lock_irqsave(&chip->reg_lock, flags);
1640         chip->mce_bit &= ~CS4231_MCE;
1641         timeout = wss_inb(chip, CS4231P(REGSEL));
1642         wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
1643         spin_unlock_irqrestore(&chip->reg_lock, flags);
1644         if (timeout == 0x80)
1645                 snd_printk(KERN_ERR "down [0x%lx]: serious init problem "
1646                            "- codec still busy\n", chip->port);
1647         if ((timeout & CS4231_MCE) == 0 ||
1648             !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) {
1649                 return;
1650         }
1651         snd_wss_busy_wait(chip);
1652 #endif
1653 }
1654 #endif /* CONFIG_PM */
1655 
1656 static int snd_wss_free(struct snd_wss *chip)
1657 {
1658         release_and_free_resource(chip->res_port);
1659         release_and_free_resource(chip->res_cport);
1660         if (chip->irq >= 0) {
1661                 disable_irq(chip->irq);
1662                 if (!(chip->hwshare & WSS_HWSHARE_IRQ))
1663                         free_irq(chip->irq, (void *) chip);
1664         }
1665         if (!(chip->hwshare & WSS_HWSHARE_DMA1) && chip->dma1 >= 0) {
1666                 snd_dma_disable(chip->dma1);
1667                 free_dma(chip->dma1);
1668         }
1669         if (!(chip->hwshare & WSS_HWSHARE_DMA2) &&
1670             chip->dma2 >= 0 && chip->dma2 != chip->dma1) {
1671                 snd_dma_disable(chip->dma2);
1672                 free_dma(chip->dma2);
1673         }
1674         if (chip->timer)
1675                 snd_device_free(chip->card, chip->timer);
1676         kfree(chip);
1677         return 0;
1678 }
1679 
1680 static int snd_wss_dev_free(struct snd_device *device)
1681 {
1682         struct snd_wss *chip = device->device_data;
1683         return snd_wss_free(chip);
1684 }
1685 
1686 const char *snd_wss_chip_id(struct snd_wss *chip)
1687 {
1688         switch (chip->hardware) {
1689         case WSS_HW_CS4231:
1690                 return "CS4231";
1691         case WSS_HW_CS4231A:
1692                 return "CS4231A";
1693         case WSS_HW_CS4232:
1694                 return "CS4232";
1695         case WSS_HW_CS4232A:
1696                 return "CS4232A";
1697         case WSS_HW_CS4235:
1698                 return "CS4235";
1699         case WSS_HW_CS4236:
1700                 return "CS4236";
1701         case WSS_HW_CS4236B:
1702                 return "CS4236B";
1703         case WSS_HW_CS4237B:
1704                 return "CS4237B";
1705         case WSS_HW_CS4238B:
1706                 return "CS4238B";
1707         case WSS_HW_CS4239:
1708                 return "CS4239";
1709         case WSS_HW_INTERWAVE:
1710                 return "AMD InterWave";
1711         case WSS_HW_OPL3SA2:
1712                 return chip->card->shortname;
1713         case WSS_HW_AD1845:
1714                 return "AD1845";
1715         case WSS_HW_OPTI93X:
1716                 return "OPTi 93x";
1717         case WSS_HW_AD1847:
1718                 return "AD1847";
1719         case WSS_HW_AD1848:
1720                 return "AD1848";
1721         case WSS_HW_CS4248:
1722                 return "CS4248";
1723         case WSS_HW_CMI8330:
1724                 return "CMI8330/C3D";
1725         default:
1726                 return "???";
1727         }
1728 }
1729 EXPORT_SYMBOL(snd_wss_chip_id);
1730 
1731 static int snd_wss_new(struct snd_card *card,
1732                           unsigned short hardware,
1733                           unsigned short hwshare,
1734                           struct snd_wss **rchip)
1735 {
1736         struct snd_wss *chip;
1737 
1738         *rchip = NULL;
1739         chip = kzalloc(sizeof(*chip), GFP_KERNEL);
1740         if (chip == NULL)
1741                 return -ENOMEM;
1742         chip->hardware = hardware;
1743         chip->hwshare = hwshare;
1744 
1745         spin_lock_init(&chip->reg_lock);
1746         mutex_init(&chip->mce_mutex);
1747         mutex_init(&chip->open_mutex);
1748         chip->card = card;
1749         chip->rate_constraint = snd_wss_xrate;
1750         chip->set_playback_format = snd_wss_playback_format;
1751         chip->set_capture_format = snd_wss_capture_format;
1752         if (chip->hardware == WSS_HW_OPTI93X)
1753                 memcpy(&chip->image, &snd_opti93x_original_image,
1754                        sizeof(snd_opti93x_original_image));
1755         else
1756                 memcpy(&chip->image, &snd_wss_original_image,
1757                        sizeof(snd_wss_original_image));
1758         if (chip->hardware & WSS_HW_AD1848_MASK) {
1759                 chip->image[CS4231_PIN_CTRL] = 0;
1760                 chip->image[CS4231_TEST_INIT] = 0;
1761         }
1762 
1763         *rchip = chip;
1764         return 0;
1765 }
1766 
1767 int snd_wss_create(struct snd_card *card,
1768                       unsigned long port,
1769                       unsigned long cport,
1770                       int irq, int dma1, int dma2,
1771                       unsigned short hardware,
1772                       unsigned short hwshare,
1773                       struct snd_wss **rchip)
1774 {
1775         static const struct snd_device_ops ops = {
1776                 .dev_free =     snd_wss_dev_free,
1777         };
1778         struct snd_wss *chip;
1779         int err;
1780 
1781         err = snd_wss_new(card, hardware, hwshare, &chip);
1782         if (err < 0)
1783                 return err;
1784 
1785         chip->irq = -1;
1786         chip->dma1 = -1;
1787         chip->dma2 = -1;
1788 
1789         chip->res_port = request_region(port, 4, "WSS");
1790         if (!chip->res_port) {
1791                 snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port);
1792                 snd_wss_free(chip);
1793                 return -EBUSY;
1794         }
1795         chip->port = port;
1796         if ((long)cport >= 0) {
1797                 chip->res_cport = request_region(cport, 8, "CS4232 Control");
1798                 if (!chip->res_cport) {
1799                         snd_printk(KERN_ERR
1800                                 "wss: can't grab control port 0x%lx\n", cport);
1801                         snd_wss_free(chip);
1802                         return -ENODEV;
1803                 }
1804         }
1805         chip->cport = cport;
1806         if (!(hwshare & WSS_HWSHARE_IRQ))
1807                 if (request_irq(irq, snd_wss_interrupt, 0,
1808                                 "WSS", (void *) chip)) {
1809                         snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq);
1810                         snd_wss_free(chip);
1811                         return -EBUSY;
1812                 }
1813         chip->irq = irq;
1814         card->sync_irq = chip->irq;
1815         if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) {
1816                 snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1);
1817                 snd_wss_free(chip);
1818                 return -EBUSY;
1819         }
1820         chip->dma1 = dma1;
1821         if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 &&
1822               dma2 >= 0 && request_dma(dma2, "WSS - 2")) {
1823                 snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2);
1824                 snd_wss_free(chip);
1825                 return -EBUSY;
1826         }
1827         if (dma1 == dma2 || dma2 < 0) {
1828                 chip->single_dma = 1;
1829                 chip->dma2 = chip->dma1;
1830         } else
1831                 chip->dma2 = dma2;
1832 
1833         if (hardware == WSS_HW_THINKPAD) {
1834                 chip->thinkpad_flag = 1;
1835                 chip->hardware = WSS_HW_DETECT; /* reset */
1836                 snd_wss_thinkpad_twiddle(chip, 1);
1837         }
1838 
1839         /* global setup */
1840         if (snd_wss_probe(chip) < 0) {
1841                 snd_wss_free(chip);
1842                 return -ENODEV;
1843         }
1844         snd_wss_init(chip);
1845 
1846 #if 0
1847         if (chip->hardware & WSS_HW_CS4232_MASK) {
1848                 if (chip->res_cport == NULL)
1849                         snd_printk(KERN_ERR "CS4232 control port features are "
1850                                    "not accessible\n");
1851         }
1852 #endif
1853 
1854         /* Register device */
1855         err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
1856         if (err < 0) {
1857                 snd_wss_free(chip);
1858                 return err;
1859         }
1860 
1861 #ifdef CONFIG_PM
1862         /* Power Management */
1863         chip->suspend = snd_wss_suspend;
1864         chip->resume = snd_wss_resume;
1865 #endif
1866 
1867         *rchip = chip;
1868         return 0;
1869 }
1870 EXPORT_SYMBOL(snd_wss_create);
1871 
1872 static const struct snd_pcm_ops snd_wss_playback_ops = {
1873         .open =         snd_wss_playback_open,
1874         .close =        snd_wss_playback_close,
1875         .hw_params =    snd_wss_playback_hw_params,
1876         .prepare =      snd_wss_playback_prepare,
1877         .trigger =      snd_wss_trigger,
1878         .pointer =      snd_wss_playback_pointer,
1879 };
1880 
1881 static const struct snd_pcm_ops snd_wss_capture_ops = {
1882         .open =         snd_wss_capture_open,
1883         .close =        snd_wss_capture_close,
1884         .hw_params =    snd_wss_capture_hw_params,
1885         .prepare =      snd_wss_capture_prepare,
1886         .trigger =      snd_wss_trigger,
1887         .pointer =      snd_wss_capture_pointer,
1888 };
1889 
1890 int snd_wss_pcm(struct snd_wss *chip, int device)
1891 {
1892         struct snd_pcm *pcm;
1893         int err;
1894 
1895         err = snd_pcm_new(chip->card, "WSS", device, 1, 1, &pcm);
1896         if (err < 0)
1897                 return err;
1898 
1899         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops);
1900         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops);
1901 
1902         /* global setup */
1903         pcm->private_data = chip;
1904         pcm->info_flags = 0;
1905         if (chip->single_dma)
1906                 pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
1907         if (chip->hardware != WSS_HW_INTERWAVE)
1908                 pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
1909         strcpy(pcm->name, snd_wss_chip_id(chip));
1910 
1911         snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, chip->card->dev,
1912                                        64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
1913 
1914         chip->pcm = pcm;
1915         return 0;
1916 }
1917 EXPORT_SYMBOL(snd_wss_pcm);
1918 
1919 static void snd_wss_timer_free(struct snd_timer *timer)
1920 {
1921         struct snd_wss *chip = timer->private_data;
1922         chip->timer = NULL;
1923 }
1924 
1925 int snd_wss_timer(struct snd_wss *chip, int device)
1926 {
1927         struct snd_timer *timer;
1928         struct snd_timer_id tid;
1929         int err;
1930 
1931         /* Timer initialization */
1932         tid.dev_class = SNDRV_TIMER_CLASS_CARD;
1933         tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
1934         tid.card = chip->card->number;
1935         tid.device = device;
1936         tid.subdevice = 0;
1937         if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0)
1938                 return err;
1939         strcpy(timer->name, snd_wss_chip_id(chip));
1940         timer->private_data = chip;
1941         timer->private_free = snd_wss_timer_free;
1942         timer->hw = snd_wss_timer_table;
1943         chip->timer = timer;
1944         return 0;
1945 }
1946 EXPORT_SYMBOL(snd_wss_timer);
1947 
1948 /*
1949  *  MIXER part
1950  */
1951 
1952 static int snd_wss_info_mux(struct snd_kcontrol *kcontrol,
1953                             struct snd_ctl_elem_info *uinfo)
1954 {
1955         static const char * const texts[4] = {
1956                 "Line", "Aux", "Mic", "Mix"
1957         };
1958         static const char * const opl3sa_texts[4] = {
1959                 "Line", "CD", "Mic", "Mix"
1960         };
1961         static const char * const gusmax_texts[4] = {
1962                 "Line", "Synth", "Mic", "Mix"
1963         };
1964         const char * const *ptexts = texts;
1965         struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
1966 
1967         if (snd_BUG_ON(!chip->card))
1968                 return -EINVAL;
1969         if (!strcmp(chip->card->driver, "GUS MAX"))
1970                 ptexts = gusmax_texts;
1971         switch (chip->hardware) {
1972         case WSS_HW_INTERWAVE:
1973                 ptexts = gusmax_texts;
1974                 break;
1975         case WSS_HW_OPTI93X:
1976         case WSS_HW_OPL3SA2:
1977                 ptexts = opl3sa_texts;
1978                 break;
1979         }
1980         return snd_ctl_enum_info(uinfo, 2, 4, ptexts);
1981 }
1982 
1983 static int snd_wss_get_mux(struct snd_kcontrol *kcontrol,
1984                            struct snd_ctl_elem_value *ucontrol)
1985 {
1986         struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
1987         unsigned long flags;
1988 
1989         spin_lock_irqsave(&chip->reg_lock, flags);
1990         ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6;
1991         ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6;
1992         spin_unlock_irqrestore(&chip->reg_lock, flags);
1993         return 0;
1994 }
1995 
1996 static int snd_wss_put_mux(struct snd_kcontrol *kcontrol,
1997                            struct snd_ctl_elem_value *ucontrol)
1998 {
1999         struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2000         unsigned long flags;
2001         unsigned short left, right;
2002         int change;
2003 
2004         if (ucontrol->value.enumerated.item[0] > 3 ||
2005             ucontrol->value.enumerated.item[1] > 3)
2006                 return -EINVAL;
2007         left = ucontrol->value.enumerated.item[0] << 6;
2008         right = ucontrol->value.enumerated.item[1] << 6;
2009         spin_lock_irqsave(&chip->reg_lock, flags);
2010         left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left;
2011         right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right;
2012         change = left != chip->image[CS4231_LEFT_INPUT] ||
2013                  right != chip->image[CS4231_RIGHT_INPUT];
2014         snd_wss_out(chip, CS4231_LEFT_INPUT, left);
2015         snd_wss_out(chip, CS4231_RIGHT_INPUT, right);
2016         spin_unlock_irqrestore(&chip->reg_lock, flags);
2017         return change;
2018 }
2019 
2020 int snd_wss_info_single(struct snd_kcontrol *kcontrol,
2021                         struct snd_ctl_elem_info *uinfo)
2022 {
2023         int mask = (kcontrol->private_value >> 16) & 0xff;
2024 
2025         uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
2026         uinfo->count = 1;
2027         uinfo->value.integer.min = 0;
2028         uinfo->value.integer.max = mask;
2029         return 0;
2030 }
2031 EXPORT_SYMBOL(snd_wss_info_single);
2032 
2033 int snd_wss_get_single(struct snd_kcontrol *kcontrol,
2034                        struct snd_ctl_elem_value *ucontrol)
2035 {
2036         struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2037         unsigned long flags;
2038         int reg = kcontrol->private_value & 0xff;
2039         int shift = (kcontrol->private_value >> 8) & 0xff;
2040         int mask = (kcontrol->private_value >> 16) & 0xff;
2041         int invert = (kcontrol->private_value >> 24) & 0xff;
2042 
2043         spin_lock_irqsave(&chip->reg_lock, flags);
2044         ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
2045         spin_unlock_irqrestore(&chip->reg_lock, flags);
2046         if (invert)
2047                 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
2048         return 0;
2049 }
2050 EXPORT_SYMBOL(snd_wss_get_single);
2051 
2052 int snd_wss_put_single(struct snd_kcontrol *kcontrol,
2053                        struct snd_ctl_elem_value *ucontrol)
2054 {
2055         struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2056         unsigned long flags;
2057         int reg = kcontrol->private_value & 0xff;
2058         int shift = (kcontrol->private_value >> 8) & 0xff;
2059         int mask = (kcontrol->private_value >> 16) & 0xff;
2060         int invert = (kcontrol->private_value >> 24) & 0xff;
2061         int change;
2062         unsigned short val;
2063 
2064         val = (ucontrol->value.integer.value[0] & mask);
2065         if (invert)
2066                 val = mask - val;
2067         val <<= shift;
2068         spin_lock_irqsave(&chip->reg_lock, flags);
2069         val = (chip->image[reg] & ~(mask << shift)) | val;
2070         change = val != chip->image[reg];
2071         snd_wss_out(chip, reg, val);
2072         spin_unlock_irqrestore(&chip->reg_lock, flags);
2073         return change;
2074 }
2075 EXPORT_SYMBOL(snd_wss_put_single);
2076 
2077 int snd_wss_info_double(struct snd_kcontrol *kcontrol,
2078                         struct snd_ctl_elem_info *uinfo)
2079 {
2080         int mask = (kcontrol->private_value >> 24) & 0xff;
2081 
2082         uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
2083         uinfo->count = 2;
2084         uinfo->value.integer.min = 0;
2085         uinfo->value.integer.max = mask;
2086         return 0;
2087 }
2088 EXPORT_SYMBOL(snd_wss_info_double);
2089 
2090 int snd_wss_get_double(struct snd_kcontrol *kcontrol,
2091                        struct snd_ctl_elem_value *ucontrol)
2092 {
2093         struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2094         unsigned long flags;
2095         int left_reg = kcontrol->private_value & 0xff;
2096         int right_reg = (kcontrol->private_value >> 8) & 0xff;
2097         int shift_left = (kcontrol->private_value >> 16) & 0x07;
2098         int shift_right = (kcontrol->private_value >> 19) & 0x07;
2099         int mask = (kcontrol->private_value >> 24) & 0xff;
2100         int invert = (kcontrol->private_value >> 22) & 1;
2101 
2102         spin_lock_irqsave(&chip->reg_lock, flags);
2103         ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
2104         ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
2105         spin_unlock_irqrestore(&chip->reg_lock, flags);
2106         if (invert) {
2107                 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
2108                 ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
2109         }
2110         return 0;
2111 }
2112 EXPORT_SYMBOL(snd_wss_get_double);
2113 
2114 int snd_wss_put_double(struct snd_kcontrol *kcontrol,
2115                        struct snd_ctl_elem_value *ucontrol)
2116 {
2117         struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
2118         unsigned long flags;
2119         int left_reg = kcontrol->private_value & 0xff;
2120         int right_reg = (kcontrol->private_value >> 8) & 0xff;
2121         int shift_left = (kcontrol->private_value >> 16) & 0x07;
2122         int shift_right = (kcontrol->private_value >> 19) & 0x07;
2123         int mask = (kcontrol->private_value >> 24) & 0xff;
2124         int invert = (kcontrol->private_value >> 22) & 1;
2125         int change;
2126         unsigned short val1, val2;
2127 
2128         val1 = ucontrol->value.integer.value[0] & mask;
2129         val2 = ucontrol->value.integer.value[1] & mask;
2130         if (invert) {
2131                 val1 = mask - val1;
2132                 val2 = mask - val2;
2133         }
2134         val1 <<= shift_left;
2135         val2 <<= shift_right;
2136         spin_lock_irqsave(&chip->reg_lock, flags);
2137         if (left_reg != right_reg) {
2138                 val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
2139                 val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
2140                 change = val1 != chip->image[left_reg] ||
2141                          val2 != chip->image[right_reg];
2142                 snd_wss_out(chip, left_reg, val1);
2143                 snd_wss_out(chip, right_reg, val2);
2144         } else {
2145                 mask = (mask << shift_left) | (mask << shift_right);
2146                 val1 = (chip->image[left_reg] & ~mask) | val1 | val2;
2147                 change = val1 != chip->image[left_reg];
2148                 snd_wss_out(chip, left_reg, val1);
2149         }
2150         spin_unlock_irqrestore(&chip->reg_lock, flags);
2151         return change;
2152 }
2153 EXPORT_SYMBOL(snd_wss_put_double);
2154 
2155 static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
2156 static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
2157 static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
2158 static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
2159 
2160 static const struct snd_kcontrol_new snd_wss_controls[] = {
2161 WSS_DOUBLE("PCM Playback Switch", 0,
2162                 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
2163 WSS_DOUBLE_TLV("PCM Playback Volume", 0,
2164                 CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
2165                 db_scale_6bit),
2166 WSS_DOUBLE("Aux Playback Switch", 0,
2167                 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
2168 WSS_DOUBLE_TLV("Aux Playback Volume", 0,
2169                 CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
2170                 db_scale_5bit_12db_max),
2171 WSS_DOUBLE("Aux Playback Switch", 1,
2172                 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
2173 WSS_DOUBLE_TLV("Aux Playback Volume", 1,
2174                 CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
2175                 db_scale_5bit_12db_max),
2176 WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
2177                 0, 0, 15, 0, db_scale_rec_gain),
2178 {
2179         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2180         .name = "Capture Source",
2181         .info = snd_wss_info_mux,
2182         .get = snd_wss_get_mux,
2183         .put = snd_wss_put_mux,
2184 },
2185 WSS_DOUBLE("Mic Boost (+20dB)", 0,
2186                 CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
2187 WSS_SINGLE("Loopback Capture Switch", 0,
2188                 CS4231_LOOPBACK, 0, 1, 0),
2189 WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1,
2190                 db_scale_6bit),
2191 WSS_DOUBLE("Line Playback Switch", 0,
2192                 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
2193 WSS_DOUBLE_TLV("Line Playback Volume", 0,
2194                 CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
2195                 db_scale_5bit_12db_max),
2196 WSS_SINGLE("Beep Playback Switch", 0,
2197                 CS4231_MONO_CTRL, 7, 1, 1),
2198 WSS_SINGLE_TLV("Beep Playback Volume", 0,
2199                 CS4231_MONO_CTRL, 0, 15, 1,
2200                 db_scale_4bit),
2201 WSS_SINGLE("Mono Output Playback Switch", 0,
2202                 CS4231_MONO_CTRL, 6, 1, 1),
2203 WSS_SINGLE("Beep Bypass Playback Switch", 0,
2204                 CS4231_MONO_CTRL, 5, 1, 0),
2205 };
2206 
2207 int snd_wss_mixer(struct snd_wss *chip)
2208 {
2209         struct snd_card *card;
2210         unsigned int idx;
2211         int err;
2212         int count = ARRAY_SIZE(snd_wss_controls);
2213 
2214         if (snd_BUG_ON(!chip || !chip->pcm))
2215                 return -EINVAL;
2216 
2217         card = chip->card;
2218 
2219         strcpy(card->mixername, chip->pcm->name);
2220 
2221         /* Use only the first 11 entries on AD1848 */
2222         if (chip->hardware & WSS_HW_AD1848_MASK)
2223                 count = 11;
2224         /* There is no loopback on OPTI93X */
2225         else if (chip->hardware == WSS_HW_OPTI93X)
2226                 count = 9;
2227 
2228         for (idx = 0; idx < count; idx++) {
2229                 err = snd_ctl_add(card,
2230                                 snd_ctl_new1(&snd_wss_controls[idx],
2231                                              chip));
2232                 if (err < 0)
2233                         return err;
2234         }
2235         return 0;
2236 }
2237 EXPORT_SYMBOL(snd_wss_mixer);
2238 
2239 const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction)
2240 {
2241         return direction == SNDRV_PCM_STREAM_PLAYBACK ?
2242                 &snd_wss_playback_ops : &snd_wss_capture_ops;
2243 }
2244 EXPORT_SYMBOL(snd_wss_get_pcm_ops);
2245 

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp