Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]

Diff markup

Differences between /linux/sound/isa/cs423x/cs4231_lib.c (Version 2.6.11.8) and /linux/sound/isa/cs423x/cs4231_lib.c (Version 2.6.31.13)


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