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/wss/wss_lib.c (Version 2.6.31.13) and /linux/sound/isa/wss/wss_lib.c (Version 2.6.25.8)


  1 /*                                                  1 
  2  *  Copyright (c) by Jaroslav Kysela <perex@pe    
  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 <linux/delay.h>                          
 28 #include <linux/pm.h>                             
 29 #include <linux/init.h>                           
 30 #include <linux/interrupt.h>                      
 31 #include <linux/slab.h>                           
 32 #include <linux/ioport.h>                         
 33 #include <sound/core.h>                           
 34 #include <sound/wss.h>                            
 35 #include <sound/pcm_params.h>                     
 36 #include <sound/tlv.h>                            
 37                                                   
 38 #include <asm/io.h>                               
 39 #include <asm/dma.h>                              
 40 #include <asm/irq.h>                              
 41                                                   
 42 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.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 struct snd_pcm_hw_constraint_list hw_co    
 77         .count = ARRAY_SIZE(rates),               
 78         .list = rates,                            
 79         .mask = 0,                                
 80 };                                                
 81                                                   
 82 static int snd_wss_xrate(struct snd_pcm_runtim    
 83 {                                                 
 84         return snd_pcm_hw_constraint_list(runt    
 85                                           &hw_    
 86 }                                                 
 87                                                   
 88 static unsigned char snd_wss_original_image[32    
 89 {                                                 
 90         0x00,                   /* 00/00 - lic    
 91         0x00,                   /* 01/01 - ric    
 92         0x9f,                   /* 02/02 - la1    
 93         0x9f,                   /* 03/03 - ra1    
 94         0x9f,                   /* 04/04 - la2    
 95         0x9f,                   /* 05/05 - ra2    
 96         0xbf,                   /* 06/06 - loc    
 97         0xbf,                   /* 07/07 - roc    
 98         0x20,                   /* 08/08 - pdf    
 99         CS4231_AUTOCALIB,       /* 09/09 - ic     
100         0x00,                   /* 0a/10 - pc     
101         0x00,                   /* 0b/11 - ti     
102         CS4231_MODE2,           /* 0c/12 - mi     
103         0xfc,                   /* 0d/13 - lbc    
104         0x00,                   /* 0e/14 - pbr    
105         0x00,                   /* 0f/15 - pbr    
106         0x80,                   /* 10/16 - afe    
107         0x01,                   /* 11/17 - afe    
108         0x9f,                   /* 12/18 - lli    
109         0x9f,                   /* 13/19 - rli    
110         0x00,                   /* 14/20 - tlb    
111         0x00,                   /* 15/21 - thb    
112         0x00,                   /* 16/22 - la3    
113         0x00,                   /* 17/23 - ra3    
114         0x00,                   /* 18/24 - afs    
115         0x00,                   /* 19/25 - lam    
116         0xcf,                   /* 1a/26 - mio    
117         0x00,                   /* 1b/27 - ram    
118         0x20,                   /* 1c/28 - cdf    
119         0x00,                   /* 1d/29 - res    
120         0x00,                   /* 1e/30 - cbr    
121         0x00,                   /* 1f/31 - cbr    
122 };                                                
123                                                   
124 static unsigned char snd_opti93x_original_imag    
125 {                                                 
126         0x00,           /* 00/00 - l_mixout_ou    
127         0x00,           /* 01/01 - r_mixout_ou    
128         0x88,           /* 02/02 - l_cd_inctrl    
129         0x88,           /* 03/03 - r_cd_inctrl    
130         0x88,           /* 04/04 - l_a1/fm_inc    
131         0x88,           /* 05/05 - r_a1/fm_inc    
132         0x80,           /* 06/06 - l_dac_inctr    
133         0x80,           /* 07/07 - r_dac_inctr    
134         0x00,           /* 08/08 - ply_datafor    
135         0x00,           /* 09/09 - if_conf */     
136         0x00,           /* 0a/10 - pin_ctrl */    
137         0x00,           /* 0b/11 - err_init_re    
138         0x0a,           /* 0c/12 - id_reg */      
139         0x00,           /* 0d/13 - reserved */    
140         0x00,           /* 0e/14 - ply_upcount    
141         0x00,           /* 0f/15 - ply_lowcoun    
142         0x88,           /* 10/16 - reserved/l_    
143         0x88,           /* 11/17 - reserved/r_    
144         0x88,           /* 12/18 - l_line_inct    
145         0x88,           /* 13/19 - r_line_inct    
146         0x88,           /* 14/20 - l_mic_inctr    
147         0x88,           /* 15/21 - r_mic_inctr    
148         0x80,           /* 16/22 - l_out_outct    
149         0x80,           /* 17/23 - r_out_outct    
150         0x00,           /* 18/24 - reserved */    
151         0x00,           /* 19/25 - reserved */    
152         0x00,           /* 1a/26 - reserved */    
153         0x00,           /* 1b/27 - reserved */    
154         0x00,           /* 1c/28 - cap_datafor    
155         0x00,           /* 1d/29 - reserved */    
156         0x00,           /* 1e/30 - cap_upcount    
157         0x00            /* 1f/31 - cap_lowcoun    
158 };                                                
159                                                   
160 /*                                                
161  *  Basic I/O functions                           
162  */                                               
163                                                   
164 static inline void wss_outb(struct snd_wss *ch    
165 {                                                 
166         outb(val, chip->port + offset);           
167 }                                                 
168                                                   
169 static inline u8 wss_inb(struct snd_wss *chip,    
170 {                                                 
171         return inb(chip->port + offset);          
172 }                                                 
173                                                   
174 static void snd_wss_wait(struct snd_wss *chip)    
175 {                                                 
176         int timeout;                              
177                                                   
178         for (timeout = 250;                       
179              timeout > 0 && (wss_inb(chip, CS4    
180              timeout--)                           
181                 udelay(100);                      
182 }                                                 
183                                                   
184 static void snd_wss_dout(struct snd_wss *chip,    
185                          unsigned char value)     
186 {                                                 
187         int timeout;                              
188                                                   
189         for (timeout = 250;                       
190              timeout > 0 && (wss_inb(chip, CS4    
191              timeout--)                           
192                 udelay(10);                       
193         wss_outb(chip, CS4231P(REGSEL), chip->    
194         wss_outb(chip, CS4231P(REG), value);      
195         mb();                                     
196 }                                                 
197                                                   
198 void snd_wss_out(struct snd_wss *chip, unsigne    
199 {                                                 
200         snd_wss_wait(chip);                       
201 #ifdef CONFIG_SND_DEBUG                           
202         if (wss_inb(chip, CS4231P(REGSEL)) & C    
203                 snd_printk(KERN_DEBUG "out: au    
204                            "- reg = 0x%x, valu    
205 #endif                                            
206         wss_outb(chip, CS4231P(REGSEL), chip->    
207         wss_outb(chip, CS4231P(REG), value);      
208         chip->image[reg] = value;                 
209         mb();                                     
210         snd_printdd("codec out - reg 0x%x = 0x    
211                         chip->mce_bit | reg, v    
212 }                                                 
213 EXPORT_SYMBOL(snd_wss_out);                       
214                                                   
215 unsigned char snd_wss_in(struct snd_wss *chip,    
216 {                                                 
217         snd_wss_wait(chip);                       
218 #ifdef CONFIG_SND_DEBUG                           
219         if (wss_inb(chip, CS4231P(REGSEL)) & C    
220                 snd_printk(KERN_DEBUG "in: aut    
221                            "- reg = 0x%x\n", r    
222 #endif                                            
223         wss_outb(chip, CS4231P(REGSEL), chip->    
224         mb();                                     
225         return wss_inb(chip, CS4231P(REG));       
226 }                                                 
227 EXPORT_SYMBOL(snd_wss_in);                        
228                                                   
229 void snd_cs4236_ext_out(struct snd_wss *chip,     
230                         unsigned char val)        
231 {                                                 
232         wss_outb(chip, CS4231P(REGSEL), chip->    
233         wss_outb(chip, CS4231P(REG),              
234                  reg | (chip->image[CS4236_EXT    
235         wss_outb(chip, CS4231P(REG), val);        
236         chip->eimage[CS4236_REG(reg)] = val;      
237 #if 0                                             
238         printk(KERN_DEBUG "ext out : reg = 0x%    
239 #endif                                            
240 }                                                 
241 EXPORT_SYMBOL(snd_cs4236_ext_out);                
242                                                   
243 unsigned char snd_cs4236_ext_in(struct snd_wss    
244 {                                                 
245         wss_outb(chip, CS4231P(REGSEL), chip->    
246         wss_outb(chip, CS4231P(REG),              
247                  reg | (chip->image[CS4236_EXT    
248 #if 1                                             
249         return wss_inb(chip, CS4231P(REG));       
250 #else                                             
251         {                                         
252                 unsigned char res;                
253                 res = wss_inb(chip, CS4231P(RE    
254                 printk(KERN_DEBUG "ext in : re    
255                        reg, res);                 
256                 return res;                       
257         }                                         
258 #endif                                            
259 }                                                 
260 EXPORT_SYMBOL(snd_cs4236_ext_in);                 
261                                                   
262 #if 0                                             
263                                                   
264 static void snd_wss_debug(struct snd_wss *chip    
265 {                                                 
266         printk(KERN_DEBUG                         
267                 "CS4231 REGS:      INDEX = 0x%    
268                 "                 STATUS = 0x%    
269                                         wss_in    
270                                         wss_in    
271         printk(KERN_DEBUG                         
272                 "  0x00: left input      = 0x%    
273                 "  0x10: alt 1 (CFIG 2)  = 0x%    
274                                         snd_ws    
275                                         snd_ws    
276         printk(KERN_DEBUG                         
277                 "  0x01: right input     = 0x%    
278                 "  0x11: alt 2 (CFIG 3)  = 0x%    
279                                         snd_ws    
280                                         snd_ws    
281         printk(KERN_DEBUG                         
282                 "  0x02: GF1 left input  = 0x%    
283                 "  0x12: left line in    = 0x%    
284                                         snd_ws    
285                                         snd_ws    
286         printk(KERN_DEBUG                         
287                 "  0x03: GF1 right input = 0x%    
288                 "  0x13: right line in   = 0x%    
289                                         snd_ws    
290                                         snd_ws    
291         printk(KERN_DEBUG                         
292                 "  0x04: CD left input   = 0x%    
293                 "  0x14: timer low       = 0x%    
294                                         snd_ws    
295                                         snd_ws    
296         printk(KERN_DEBUG                         
297                 "  0x05: CD right input  = 0x%    
298                 "  0x15: timer high      = 0x%    
299                                         snd_ws    
300                                         snd_ws    
301         printk(KERN_DEBUG                         
302                 "  0x06: left output     = 0x%    
303                 "  0x16: left MIC (PnP)  = 0x%    
304                                         snd_ws    
305                                         snd_ws    
306         printk(KERN_DEBUG                         
307                 "  0x07: right output    = 0x%    
308                 "  0x17: right MIC (PnP) = 0x%    
309                                         snd_ws    
310                                         snd_ws    
311         printk(KERN_DEBUG                         
312                 "  0x08: playback format = 0x%    
313                 "  0x18: IRQ status      = 0x%    
314                                         snd_ws    
315                                         snd_ws    
316         printk(KERN_DEBUG                         
317                 "  0x09: iface (CFIG 1)  = 0x%    
318                 "  0x19: left line out   = 0x%    
319                                         snd_ws    
320                                         snd_ws    
321         printk(KERN_DEBUG                         
322                 "  0x0a: pin control     = 0x%    
323                 "  0x1a: mono control    = 0x%    
324                                         snd_ws    
325                                         snd_ws    
326         printk(KERN_DEBUG                         
327                 "  0x0b: init & status   = 0x%    
328                 "  0x1b: right line out  = 0x%    
329                                         snd_ws    
330                                         snd_ws    
331         printk(KERN_DEBUG                         
332                 "  0x0c: revision & mode = 0x%    
333                 "  0x1c: record format   = 0x%    
334                                         snd_ws    
335                                         snd_ws    
336         printk(KERN_DEBUG                         
337                 "  0x0d: loopback        = 0x%    
338                 "  0x1d: var freq (PnP)  = 0x%    
339                                         snd_ws    
340                                         snd_ws    
341         printk(KERN_DEBUG                         
342                 "  0x0e: ply upr count   = 0x%    
343                 "  0x1e: ply lwr count   = 0x%    
344                                         snd_ws    
345                                         snd_ws    
346         printk(KERN_DEBUG                         
347                 "  0x0f: rec upr count   = 0x%    
348                 "  0x1f: rec lwr count   = 0x%    
349                                         snd_ws    
350                                         snd_ws    
351 }                                                 
352                                                   
353 #endif                                            
354                                                   
355 /*                                                
356  *  CS4231 detection / MCE routines               
357  */                                               
358                                                   
359 static void snd_wss_busy_wait(struct snd_wss *    
360 {                                                 
361         int timeout;                              
362                                                   
363         /* huh.. looks like this sequence is p    
364         for (timeout = 5; timeout > 0; timeout    
365                 wss_inb(chip, CS4231P(REGSEL))    
366         /* end of cleanup sequence */             
367         for (timeout = 25000;                     
368              timeout > 0 && (wss_inb(chip, CS4    
369              timeout--)                           
370                 udelay(10);                       
371 }                                                 
372                                                   
373 void snd_wss_mce_up(struct snd_wss *chip)         
374 {                                                 
375         unsigned long flags;                      
376         int timeout;                              
377                                                   
378         snd_wss_wait(chip);                       
379 #ifdef CONFIG_SND_DEBUG                           
380         if (wss_inb(chip, CS4231P(REGSEL)) & C    
381                 snd_printk(KERN_DEBUG             
382                            "mce_up - auto cali    
383 #endif                                            
384         spin_lock_irqsave(&chip->reg_lock, fla    
385         chip->mce_bit |= CS4231_MCE;              
386         timeout = wss_inb(chip, CS4231P(REGSEL    
387         if (timeout == 0x80)                      
388                 snd_printk(KERN_DEBUG "mce_up     
389                            "serious init probl    
390                            chip->port);           
391         if (!(timeout & CS4231_MCE))              
392                 wss_outb(chip, CS4231P(REGSEL)    
393                          chip->mce_bit | (time    
394         spin_unlock_irqrestore(&chip->reg_lock    
395 }                                                 
396 EXPORT_SYMBOL(snd_wss_mce_up);                    
397                                                   
398 void snd_wss_mce_down(struct snd_wss *chip)       
399 {                                                 
400         unsigned long flags;                      
401         unsigned long end_time;                   
402         int timeout;                              
403         int hw_mask = WSS_HW_CS4231_MASK | WSS    
404                                                   
405         snd_wss_busy_wait(chip);                  
406                                                   
407 #ifdef CONFIG_SND_DEBUG                           
408         if (wss_inb(chip, CS4231P(REGSEL)) & C    
409                 snd_printk(KERN_DEBUG "mce_dow    
410                            "auto calibration t    
411                            (long)CS4231P(REGSE    
412 #endif                                            
413         spin_lock_irqsave(&chip->reg_lock, fla    
414         chip->mce_bit &= ~CS4231_MCE;             
415         timeout = wss_inb(chip, CS4231P(REGSEL    
416         wss_outb(chip, CS4231P(REGSEL), chip->    
417         spin_unlock_irqrestore(&chip->reg_lock    
418         if (timeout == 0x80)                      
419                 snd_printk(KERN_DEBUG "mce_dow    
420                            "serious init probl    
421                            chip->port);           
422         if ((timeout & CS4231_MCE) == 0 || !(c    
423                 return;                           
424                                                   
425         /*                                        
426          * Wait for (possible -- during init a    
427          * calibration process to start. Needs    
428          * which at the slowest possible rate     
429          */                                       
430         msleep(1);                                
431                                                   
432         snd_printdd("(1) jiffies = %lu\n", jif    
433                                                   
434         /* check condition up to 250 ms */        
435         end_time = jiffies + msecs_to_jiffies(    
436         while (snd_wss_in(chip, CS4231_TEST_IN    
437                 CS4231_CALIB_IN_PROGRESS) {       
438                                                   
439                 if (time_after(jiffies, end_ti    
440                         snd_printk(KERN_ERR "m    
441                                         "auto     
442                         return;                   
443                 }                                 
444                 msleep(1);                        
445         }                                         
446                                                   
447         snd_printdd("(2) jiffies = %lu\n", jif    
448                                                   
449         /* check condition up to 100 ms */        
450         end_time = jiffies + msecs_to_jiffies(    
451         while (wss_inb(chip, CS4231P(REGSEL))     
452                 if (time_after(jiffies, end_ti    
453                         snd_printk(KERN_ERR "m    
454                         return;                   
455                 }                                 
456                 msleep(1);                        
457         }                                         
458                                                   
459         snd_printdd("(3) jiffies = %lu\n", jif    
460         snd_printd("mce_down - exit = 0x%x\n",    
461 }                                                 
462 EXPORT_SYMBOL(snd_wss_mce_down);                  
463                                                   
464 static unsigned int snd_wss_get_count(unsigned    
465 {                                                 
466         switch (format & 0xe0) {                  
467         case CS4231_LINEAR_16:                    
468         case CS4231_LINEAR_16_BIG:                
469                 size >>= 1;                       
470                 break;                            
471         case CS4231_ADPCM_16:                     
472                 return size >> 2;                 
473         }                                         
474         if (format & CS4231_STEREO)               
475                 size >>= 1;                       
476         return size;                              
477 }                                                 
478                                                   
479 static int snd_wss_trigger(struct snd_pcm_subs    
480                            int cmd)               
481 {                                                 
482         struct snd_wss *chip = snd_pcm_substre    
483         int result = 0;                           
484         unsigned int what;                        
485         struct snd_pcm_substream *s;              
486         int do_start;                             
487                                                   
488         switch (cmd) {                            
489         case SNDRV_PCM_TRIGGER_START:             
490         case SNDRV_PCM_TRIGGER_RESUME:            
491                 do_start = 1; break;              
492         case SNDRV_PCM_TRIGGER_STOP:              
493         case SNDRV_PCM_TRIGGER_SUSPEND:           
494                 do_start = 0; break;              
495         default:                                  
496                 return -EINVAL;                   
497         }                                         
498                                                   
499         what = 0;                                 
500         snd_pcm_group_for_each_entry(s, substr    
501                 if (s == chip->playback_substr    
502                         what |= CS4231_PLAYBAC    
503                         snd_pcm_trigger_done(s    
504                 } else if (s == chip->capture_    
505                         what |= CS4231_RECORD_    
506                         snd_pcm_trigger_done(s    
507                 }                                 
508         }                                         
509         spin_lock(&chip->reg_lock);               
510         if (do_start) {                           
511                 chip->image[CS4231_IFACE_CTRL]    
512                 if (chip->trigger)                
513                         chip->trigger(chip, wh    
514         } else {                                  
515                 chip->image[CS4231_IFACE_CTRL]    
516                 if (chip->trigger)                
517                         chip->trigger(chip, wh    
518         }                                         
519         snd_wss_out(chip, CS4231_IFACE_CTRL, c    
520         spin_unlock(&chip->reg_lock);             
521 #if 0                                             
522         snd_wss_debug(chip);                      
523 #endif                                            
524         return result;                            
525 }                                                 
526                                                   
527 /*                                                
528  *  CODEC I/O                                     
529  */                                               
530                                                   
531 static unsigned char snd_wss_get_rate(unsigned    
532 {                                                 
533         int i;                                    
534                                                   
535         for (i = 0; i < ARRAY_SIZE(rates); i++    
536                 if (rate == rates[i])             
537                         return freq_bits[i];      
538         // snd_BUG();                             
539         return freq_bits[ARRAY_SIZE(rates) - 1    
540 }                                                 
541                                                   
542 static unsigned char snd_wss_get_format(struct    
543                                         int fo    
544                                         int ch    
545 {                                                 
546         unsigned char rformat;                    
547                                                   
548         rformat = CS4231_LINEAR_8;                
549         switch (format) {                         
550         case SNDRV_PCM_FORMAT_MU_LAW:   rforma    
551         case SNDRV_PCM_FORMAT_A_LAW:    rforma    
552         case SNDRV_PCM_FORMAT_S16_LE:   rforma    
553         case SNDRV_PCM_FORMAT_S16_BE:   rforma    
554         case SNDRV_PCM_FORMAT_IMA_ADPCM:          
555         }                                         
556         if (channels > 1)                         
557                 rformat |= CS4231_STEREO;         
558 #if 0                                             
559         snd_printk(KERN_DEBUG "get_format: 0x%    
560 #endif                                            
561         return rformat;                           
562 }                                                 
563                                                   
564 static void snd_wss_calibrate_mute(struct snd_    
565 {                                                 
566         unsigned long flags;                      
567                                                   
568         mute = mute ? 0x80 : 0;                   
569         spin_lock_irqsave(&chip->reg_lock, fla    
570         if (chip->calibrate_mute == mute) {       
571                 spin_unlock_irqrestore(&chip->    
572                 return;                           
573         }                                         
574         if (!mute) {                              
575                 snd_wss_dout(chip, CS4231_LEFT    
576                              chip->image[CS423    
577                 snd_wss_dout(chip, CS4231_RIGH    
578                              chip->image[CS423    
579                 snd_wss_dout(chip, CS4231_LOOP    
580                              chip->image[CS423    
581         } else {                                  
582                 snd_wss_dout(chip, CS4231_LEFT    
583                              0);                  
584                 snd_wss_dout(chip, CS4231_RIGH    
585                              0);                  
586                 snd_wss_dout(chip, CS4231_LOOP    
587                              0xfd);               
588         }                                         
589                                                   
590         snd_wss_dout(chip, CS4231_AUX1_LEFT_IN    
591                      mute | chip->image[CS4231    
592         snd_wss_dout(chip, CS4231_AUX1_RIGHT_I    
593                      mute | chip->image[CS4231    
594         snd_wss_dout(chip, CS4231_AUX2_LEFT_IN    
595                      mute | chip->image[CS4231    
596         snd_wss_dout(chip, CS4231_AUX2_RIGHT_I    
597                      mute | chip->image[CS4231    
598         snd_wss_dout(chip, CS4231_LEFT_OUTPUT,    
599                      mute | chip->image[CS4231    
600         snd_wss_dout(chip, CS4231_RIGHT_OUTPUT    
601                      mute | chip->image[CS4231    
602         if (!(chip->hardware & WSS_HW_AD1848_M    
603                 snd_wss_dout(chip, CS4231_LEFT    
604                              mute | chip->imag    
605                 snd_wss_dout(chip, CS4231_RIGH    
606                              mute | chip->imag    
607                 snd_wss_dout(chip, CS4231_MONO    
608                              mute ? 0xc0 : chi    
609         }                                         
610         if (chip->hardware == WSS_HW_INTERWAVE    
611                 snd_wss_dout(chip, CS4231_LEFT    
612                              mute | chip->imag    
613                 snd_wss_dout(chip, CS4231_RIGH    
614                              mute | chip->imag    
615                 snd_wss_dout(chip, CS4231_LINE    
616                              mute | chip->imag    
617                 snd_wss_dout(chip, CS4231_LINE    
618                              mute | chip->imag    
619         }                                         
620         chip->calibrate_mute = mute;              
621         spin_unlock_irqrestore(&chip->reg_lock    
622 }                                                 
623                                                   
624 static void snd_wss_playback_format(struct snd    
625                                        struct     
626                                        unsigne    
627 {                                                 
628         unsigned long flags;                      
629         int full_calib = 1;                       
630                                                   
631         mutex_lock(&chip->mce_mutex);             
632         if (chip->hardware == WSS_HW_CS4231A |    
633             (chip->hardware & WSS_HW_CS4232_MA    
634                 spin_lock_irqsave(&chip->reg_l    
635                 if ((chip->image[CS4231_PLAYBK    
636                         snd_wss_out(chip, CS42    
637                                     chip->imag    
638                         chip->image[CS4231_PLA    
639                         snd_wss_out(chip, CS42    
640                                     chip->imag    
641                         snd_wss_out(chip, CS42    
642                                     chip->imag    
643                         udelay(100); /* Fixes     
644                         full_calib = 0;           
645                 }                                 
646                 spin_unlock_irqrestore(&chip->    
647         } else if (chip->hardware == WSS_HW_AD    
648                 unsigned rate = params_rate(pa    
649                                                   
650                 /*                                
651                  * Program the AD1845 correctl    
652                  * Note that we do NOT need to    
653                  * the PLAYBACK_ENABLE bit of     
654                  * register is set.               
655                  *                                
656                  * NOTE: We seem to need to wr    
657                  *       to get the correct sa    
658                  */                               
659                 spin_lock_irqsave(&chip->reg_l    
660                 snd_wss_out(chip, CS4231_PLAYB    
661                 snd_wss_out(chip, AD1845_UPR_F    
662                 snd_wss_out(chip, AD1845_LWR_F    
663                 full_calib = 0;                   
664                 spin_unlock_irqrestore(&chip->    
665         }                                         
666         if (full_calib) {                         
667                 snd_wss_mce_up(chip);             
668                 spin_lock_irqsave(&chip->reg_l    
669                 if (chip->hardware != WSS_HW_I    
670                         if (chip->image[CS4231    
671                                 pdfr = (pdfr &    
672                                        (chip->    
673                 } else {                          
674                         chip->image[CS4231_PLA    
675                 }                                 
676                 snd_wss_out(chip, CS4231_PLAYB    
677                 spin_unlock_irqrestore(&chip->    
678                 if (chip->hardware == WSS_HW_O    
679                         udelay(100);    /* thi    
680                 snd_wss_mce_down(chip);           
681         }                                         
682         mutex_unlock(&chip->mce_mutex);           
683 }                                                 
684                                                   
685 static void snd_wss_capture_format(struct snd_    
686                                    struct snd_    
687                                    unsigned ch    
688 {                                                 
689         unsigned long flags;                      
690         int full_calib = 1;                       
691                                                   
692         mutex_lock(&chip->mce_mutex);             
693         if (chip->hardware == WSS_HW_CS4231A |    
694             (chip->hardware & WSS_HW_CS4232_MA    
695                 spin_lock_irqsave(&chip->reg_l    
696                 if ((chip->image[CS4231_PLAYBK    
697                     (chip->image[CS4231_IFACE_    
698                         snd_wss_out(chip, CS42    
699                                 chip->image[CS    
700                         snd_wss_out(chip, CS42    
701                                 chip->image[CS    
702                         snd_wss_out(chip, CS42    
703                                 chip->image[CS    
704                         full_calib = 0;           
705                 }                                 
706                 spin_unlock_irqrestore(&chip->    
707         } else if (chip->hardware == WSS_HW_AD    
708                 unsigned rate = params_rate(pa    
709                                                   
710                 /*                                
711                  * Program the AD1845 correctl    
712                  * Note that we do NOT need to    
713                  * the PLAYBACK_ENABLE bit of     
714                  * register is set.               
715                  *                                
716                  * NOTE: We seem to need to wr    
717                  *       to get the correct sa    
718                  */                               
719                 spin_lock_irqsave(&chip->reg_l    
720                 snd_wss_out(chip, CS4231_REC_F    
721                 snd_wss_out(chip, AD1845_UPR_F    
722                 snd_wss_out(chip, AD1845_LWR_F    
723                 full_calib = 0;                   
724                 spin_unlock_irqrestore(&chip->    
725         }                                         
726         if (full_calib) {                         
727                 snd_wss_mce_up(chip);             
728                 spin_lock_irqsave(&chip->reg_l    
729                 if (chip->hardware != WSS_HW_I    
730                     !(chip->image[CS4231_IFACE    
731                         if (chip->single_dma)     
732                                 snd_wss_out(ch    
733                         else                      
734                                 snd_wss_out(ch    
735                                    (chip->imag    
736                                    (cdfr & 0x0    
737                         spin_unlock_irqrestore    
738                         snd_wss_mce_down(chip)    
739                         snd_wss_mce_up(chip);     
740                         spin_lock_irqsave(&chi    
741                 }                                 
742                 if (chip->hardware & WSS_HW_AD    
743                         snd_wss_out(chip, CS42    
744                 else                              
745                         snd_wss_out(chip, CS42    
746                 spin_unlock_irqrestore(&chip->    
747                 snd_wss_mce_down(chip);           
748         }                                         
749         mutex_unlock(&chip->mce_mutex);           
750 }                                                 
751                                                   
752 /*                                                
753  *  Timer interface                               
754  */                                               
755                                                   
756 static unsigned long snd_wss_timer_resolution(    
757 {                                                 
758         struct snd_wss *chip = snd_timer_chip(    
759         if (chip->hardware & WSS_HW_CS4236B_MA    
760                 return 14467;                     
761         else                                      
762                 return chip->image[CS4231_PLAY    
763 }                                                 
764                                                   
765 static int snd_wss_timer_start(struct snd_time    
766 {                                                 
767         unsigned long flags;                      
768         unsigned int ticks;                       
769         struct snd_wss *chip = snd_timer_chip(    
770         spin_lock_irqsave(&chip->reg_lock, fla    
771         ticks = timer->sticks;                    
772         if ((chip->image[CS4231_ALT_FEATURE_1]    
773             (unsigned char)(ticks >> 8) != chi    
774             (unsigned char)ticks != chip->imag    
775                 chip->image[CS4231_TIMER_HIGH]    
776                 snd_wss_out(chip, CS4231_TIMER    
777                             chip->image[CS4231    
778                 chip->image[CS4231_TIMER_LOW]     
779                 snd_wss_out(chip, CS4231_TIMER    
780                             chip->image[CS4231    
781                 snd_wss_out(chip, CS4231_ALT_F    
782                             chip->image[CS4231    
783                             CS4231_TIMER_ENABL    
784         }                                         
785         spin_unlock_irqrestore(&chip->reg_lock    
786         return 0;                                 
787 }                                                 
788                                                   
789 static int snd_wss_timer_stop(struct snd_timer    
790 {                                                 
791         unsigned long flags;                      
792         struct snd_wss *chip = snd_timer_chip(    
793         spin_lock_irqsave(&chip->reg_lock, fla    
794         chip->image[CS4231_ALT_FEATURE_1] &= ~    
795         snd_wss_out(chip, CS4231_ALT_FEATURE_1    
796                     chip->image[CS4231_ALT_FEA    
797         spin_unlock_irqrestore(&chip->reg_lock    
798         return 0;                                 
799 }                                                 
800                                                   
801 static void snd_wss_init(struct snd_wss *chip)    
802 {                                                 
803         unsigned long flags;                      
804                                                   
805         snd_wss_calibrate_mute(chip, 1);          
806         snd_wss_mce_down(chip);                   
807                                                   
808 #ifdef SNDRV_DEBUG_MCE                            
809         snd_printk(KERN_DEBUG "init: (1)\n");     
810 #endif                                            
811         snd_wss_mce_up(chip);                     
812         spin_lock_irqsave(&chip->reg_lock, fla    
813         chip->image[CS4231_IFACE_CTRL] &= ~(CS    
814                                             CS    
815                                             CS    
816                                             CS    
817                                             CS    
818         chip->image[CS4231_IFACE_CTRL] |= CS42    
819         snd_wss_out(chip, CS4231_IFACE_CTRL, c    
820         spin_unlock_irqrestore(&chip->reg_lock    
821         snd_wss_mce_down(chip);                   
822                                                   
823 #ifdef SNDRV_DEBUG_MCE                            
824         snd_printk(KERN_DEBUG "init: (2)\n");     
825 #endif                                            
826                                                   
827         snd_wss_mce_up(chip);                     
828         spin_lock_irqsave(&chip->reg_lock, fla    
829         chip->image[CS4231_IFACE_CTRL] &= ~CS4    
830         snd_wss_out(chip, CS4231_IFACE_CTRL, c    
831         snd_wss_out(chip,                         
832                     CS4231_ALT_FEATURE_1, chip    
833         spin_unlock_irqrestore(&chip->reg_lock    
834         snd_wss_mce_down(chip);                   
835                                                   
836 #ifdef SNDRV_DEBUG_MCE                            
837         snd_printk(KERN_DEBUG "init: (3) - afe    
838                    chip->image[CS4231_ALT_FEAT    
839 #endif                                            
840                                                   
841         spin_lock_irqsave(&chip->reg_lock, fla    
842         snd_wss_out(chip, CS4231_ALT_FEATURE_2    
843                     chip->image[CS4231_ALT_FEA    
844         spin_unlock_irqrestore(&chip->reg_lock    
845                                                   
846         snd_wss_mce_up(chip);                     
847         spin_lock_irqsave(&chip->reg_lock, fla    
848         snd_wss_out(chip, CS4231_PLAYBK_FORMAT    
849                     chip->image[CS4231_PLAYBK_    
850         spin_unlock_irqrestore(&chip->reg_lock    
851         snd_wss_mce_down(chip);                   
852                                                   
853 #ifdef SNDRV_DEBUG_MCE                            
854         snd_printk(KERN_DEBUG "init: (4)\n");     
855 #endif                                            
856                                                   
857         snd_wss_mce_up(chip);                     
858         spin_lock_irqsave(&chip->reg_lock, fla    
859         if (!(chip->hardware & WSS_HW_AD1848_M    
860                 snd_wss_out(chip, CS4231_REC_F    
861                             chip->image[CS4231    
862         spin_unlock_irqrestore(&chip->reg_lock    
863         snd_wss_mce_down(chip);                   
864         snd_wss_calibrate_mute(chip, 0);          
865                                                   
866 #ifdef SNDRV_DEBUG_MCE                            
867         snd_printk(KERN_DEBUG "init: (5)\n");     
868 #endif                                            
869 }                                                 
870                                                   
871 static int snd_wss_open(struct snd_wss *chip,     
872 {                                                 
873         unsigned long flags;                      
874                                                   
875         mutex_lock(&chip->open_mutex);            
876         if ((chip->mode & mode) ||                
877             ((chip->mode & WSS_MODE_OPEN) && c    
878                 mutex_unlock(&chip->open_mutex    
879                 return -EAGAIN;                   
880         }                                         
881         if (chip->mode & WSS_MODE_OPEN) {         
882                 chip->mode |= mode;               
883                 mutex_unlock(&chip->open_mutex    
884                 return 0;                         
885         }                                         
886         /* ok. now enable and ack CODEC IRQ */    
887         spin_lock_irqsave(&chip->reg_lock, fla    
888         if (!(chip->hardware & WSS_HW_AD1848_M    
889                 snd_wss_out(chip, CS4231_IRQ_S    
890                             CS4231_PLAYBACK_IR    
891                             CS4231_RECORD_IRQ     
892                             CS4231_TIMER_IRQ);    
893                 snd_wss_out(chip, CS4231_IRQ_S    
894         }                                         
895         wss_outb(chip, CS4231P(STATUS), 0);       
896         wss_outb(chip, CS4231P(STATUS), 0);       
897         chip->image[CS4231_PIN_CTRL] |= CS4231    
898         snd_wss_out(chip, CS4231_PIN_CTRL, chi    
899         if (!(chip->hardware & WSS_HW_AD1848_M    
900                 snd_wss_out(chip, CS4231_IRQ_S    
901                             CS4231_PLAYBACK_IR    
902                             CS4231_RECORD_IRQ     
903                             CS4231_TIMER_IRQ);    
904                 snd_wss_out(chip, CS4231_IRQ_S    
905         }                                         
906         spin_unlock_irqrestore(&chip->reg_lock    
907                                                   
908         chip->mode = mode;                        
909         mutex_unlock(&chip->open_mutex);          
910         return 0;                                 
911 }                                                 
912                                                   
913 static void snd_wss_close(struct snd_wss *chip    
914 {                                                 
915         unsigned long flags;                      
916                                                   
917         mutex_lock(&chip->open_mutex);            
918         chip->mode &= ~mode;                      
919         if (chip->mode & WSS_MODE_OPEN) {         
920                 mutex_unlock(&chip->open_mutex    
921                 return;                           
922         }                                         
923         /* disable IRQ */                         
924         spin_lock_irqsave(&chip->reg_lock, fla    
925         if (!(chip->hardware & WSS_HW_AD1848_M    
926                 snd_wss_out(chip, CS4231_IRQ_S    
927         wss_outb(chip, CS4231P(STATUS), 0);       
928         wss_outb(chip, CS4231P(STATUS), 0);       
929         chip->image[CS4231_PIN_CTRL] &= ~CS423    
930         snd_wss_out(chip, CS4231_PIN_CTRL, chi    
931                                                   
932         /* now disable record & playback */       
933                                                   
934         if (chip->image[CS4231_IFACE_CTRL] & (    
935                                                   
936                 spin_unlock_irqrestore(&chip->    
937                 snd_wss_mce_up(chip);             
938                 spin_lock_irqsave(&chip->reg_l    
939                 chip->image[CS4231_IFACE_CTRL]    
940                                                   
941                 snd_wss_out(chip, CS4231_IFACE    
942                             chip->image[CS4231    
943                 spin_unlock_irqrestore(&chip->    
944                 snd_wss_mce_down(chip);           
945                 spin_lock_irqsave(&chip->reg_l    
946         }                                         
947                                                   
948         /* clear IRQ again */                     
949         if (!(chip->hardware & WSS_HW_AD1848_M    
950                 snd_wss_out(chip, CS4231_IRQ_S    
951         wss_outb(chip, CS4231P(STATUS), 0);       
952         wss_outb(chip, CS4231P(STATUS), 0);       
953         spin_unlock_irqrestore(&chip->reg_lock    
954                                                   
955         chip->mode = 0;                           
956         mutex_unlock(&chip->open_mutex);          
957 }                                                 
958                                                   
959 /*                                                
960  *  timer open/close                              
961  */                                               
962                                                   
963 static int snd_wss_timer_open(struct snd_timer    
964 {                                                 
965         struct snd_wss *chip = snd_timer_chip(    
966         snd_wss_open(chip, WSS_MODE_TIMER);       
967         return 0;                                 
968 }                                                 
969                                                   
970 static int snd_wss_timer_close(struct snd_time    
971 {                                                 
972         struct snd_wss *chip = snd_timer_chip(    
973         snd_wss_close(chip, WSS_MODE_TIMER);      
974         return 0;                                 
975 }                                                 
976                                                   
977 static struct snd_timer_hardware snd_wss_timer    
978 {                                                 
979         .flags =        SNDRV_TIMER_HW_AUTO,      
980         .resolution =   9945,                     
981         .ticks =        65535,                    
982         .open =         snd_wss_timer_open,       
983         .close =        snd_wss_timer_close,      
984         .c_resolution = snd_wss_timer_resoluti    
985         .start =        snd_wss_timer_start,      
986         .stop =         snd_wss_timer_stop,       
987 };                                                
988                                                   
989 /*                                                
990  *  ok.. exported functions..                     
991  */                                               
992                                                   
993 static int snd_wss_playback_hw_params(struct s    
994                                          struc    
995 {                                                 
996         struct snd_wss *chip = snd_pcm_substre    
997         unsigned char new_pdfr;                   
998         int err;                                  
999                                                   
1000         if ((err = snd_pcm_lib_malloc_pages(s    
1001                 return err;                      
1002         new_pdfr = snd_wss_get_format(chip, p    
1003                                 params_channe    
1004                                 snd_wss_get_r    
1005         chip->set_playback_format(chip, hw_pa    
1006         return 0;                                
1007 }                                                
1008                                                  
1009 static int snd_wss_playback_hw_free(struct sn    
1010 {                                                
1011         return snd_pcm_lib_free_pages(substre    
1012 }                                                
1013                                                  
1014 static int snd_wss_playback_prepare(struct sn    
1015 {                                                
1016         struct snd_wss *chip = snd_pcm_substr    
1017         struct snd_pcm_runtime *runtime = sub    
1018         unsigned long flags;                     
1019         unsigned int size = snd_pcm_lib_buffe    
1020         unsigned int count = snd_pcm_lib_peri    
1021                                                  
1022         spin_lock_irqsave(&chip->reg_lock, fl    
1023         chip->p_dma_size = size;                 
1024         chip->image[CS4231_IFACE_CTRL] &= ~(C    
1025         snd_dma_program(chip->dma1, runtime->    
1026         count = snd_wss_get_count(chip->image    
1027         snd_wss_out(chip, CS4231_PLY_LWR_CNT,    
1028         snd_wss_out(chip, CS4231_PLY_UPR_CNT,    
1029         spin_unlock_irqrestore(&chip->reg_loc    
1030 #if 0                                            
1031         snd_wss_debug(chip);                     
1032 #endif                                           
1033         return 0;                                
1034 }                                                
1035                                                  
1036 static int snd_wss_capture_hw_params(struct s    
1037                                         struc    
1038 {                                                
1039         struct snd_wss *chip = snd_pcm_substr    
1040         unsigned char new_cdfr;                  
1041         int err;                                 
1042                                                  
1043         if ((err = snd_pcm_lib_malloc_pages(s    
1044                 return err;                      
1045         new_cdfr = snd_wss_get_format(chip, p    
1046                            params_channels(hw    
1047                            snd_wss_get_rate(p    
1048         chip->set_capture_format(chip, hw_par    
1049         return 0;                                
1050 }                                                
1051                                                  
1052 static int snd_wss_capture_hw_free(struct snd    
1053 {                                                
1054         return snd_pcm_lib_free_pages(substre    
1055 }                                                
1056                                                  
1057 static int snd_wss_capture_prepare(struct snd    
1058 {                                                
1059         struct snd_wss *chip = snd_pcm_substr    
1060         struct snd_pcm_runtime *runtime = sub    
1061         unsigned long flags;                     
1062         unsigned int size = snd_pcm_lib_buffe    
1063         unsigned int count = snd_pcm_lib_peri    
1064                                                  
1065         spin_lock_irqsave(&chip->reg_lock, fl    
1066         chip->c_dma_size = size;                 
1067         chip->image[CS4231_IFACE_CTRL] &= ~(C    
1068         snd_dma_program(chip->dma2, runtime->    
1069         if (chip->hardware & WSS_HW_AD1848_MA    
1070                 count = snd_wss_get_count(chi    
1071                                           cou    
1072         else                                     
1073                 count = snd_wss_get_count(chi    
1074                                           cou    
1075         count--;                                 
1076         if (chip->single_dma && chip->hardwar    
1077                 snd_wss_out(chip, CS4231_PLY_    
1078                 snd_wss_out(chip, CS4231_PLY_    
1079                             (unsigned char) (    
1080         } else {                                 
1081                 snd_wss_out(chip, CS4231_REC_    
1082                 snd_wss_out(chip, CS4231_REC_    
1083                             (unsigned char) (    
1084         }                                        
1085         spin_unlock_irqrestore(&chip->reg_loc    
1086         return 0;                                
1087 }                                                
1088                                                  
1089 void snd_wss_overrange(struct snd_wss *chip)     
1090 {                                                
1091         unsigned long flags;                     
1092         unsigned char res;                       
1093                                                  
1094         spin_lock_irqsave(&chip->reg_lock, fl    
1095         res = snd_wss_in(chip, CS4231_TEST_IN    
1096         spin_unlock_irqrestore(&chip->reg_loc    
1097         if (res & (0x08 | 0x02))        /* de    
1098                 chip->capture_substream->runt    
1099 }                                                
1100 EXPORT_SYMBOL(snd_wss_overrange);                
1101                                                  
1102 irqreturn_t snd_wss_interrupt(int irq, void *    
1103 {                                                
1104         struct snd_wss *chip = dev_id;           
1105         unsigned char status;                    
1106                                                  
1107         if (chip->hardware & WSS_HW_AD1848_MA    
1108                 /* pretend it was the only po    
1109                 status = CS4231_PLAYBACK_IRQ;    
1110         else                                     
1111                 status = snd_wss_in(chip, CS4    
1112         if (status & CS4231_TIMER_IRQ) {         
1113                 if (chip->timer)                 
1114                         snd_timer_interrupt(c    
1115         }                                        
1116         if (chip->single_dma && chip->hardwar    
1117                 if (status & CS4231_PLAYBACK_    
1118                         if (chip->mode & WSS_    
1119                                 if (chip->pla    
1120                                         snd_p    
1121                         }                        
1122                         if (chip->mode & WSS_    
1123                                 if (chip->cap    
1124                                         snd_w    
1125                                         snd_p    
1126                                 }                
1127                         }                        
1128                 }                                
1129         } else {                                 
1130                 if (status & CS4231_PLAYBACK_    
1131                         if (chip->playback_su    
1132                                 snd_pcm_perio    
1133                 }                                
1134                 if (status & CS4231_RECORD_IR    
1135                         if (chip->capture_sub    
1136                                 snd_wss_overr    
1137                                 snd_pcm_perio    
1138                         }                        
1139                 }                                
1140         }                                        
1141                                                  
1142         spin_lock(&chip->reg_lock);              
1143         status = ~CS4231_ALL_IRQS | ~status;     
1144         if (chip->hardware & WSS_HW_AD1848_MA    
1145                 wss_outb(chip, CS4231P(STATUS    
1146         else                                     
1147                 snd_wss_out(chip, CS4231_IRQ_    
1148         spin_unlock(&chip->reg_lock);            
1149         return IRQ_HANDLED;                      
1150 }                                                
1151 EXPORT_SYMBOL(snd_wss_interrupt);                
1152                                                  
1153 static snd_pcm_uframes_t snd_wss_playback_poi    
1154 {                                                
1155         struct snd_wss *chip = snd_pcm_substr    
1156         size_t ptr;                              
1157                                                  
1158         if (!(chip->image[CS4231_IFACE_CTRL]     
1159                 return 0;                        
1160         ptr = snd_dma_pointer(chip->dma1, chi    
1161         return bytes_to_frames(substream->run    
1162 }                                                
1163                                                  
1164 static snd_pcm_uframes_t snd_wss_capture_poin    
1165 {                                                
1166         struct snd_wss *chip = snd_pcm_substr    
1167         size_t ptr;                              
1168                                                  
1169         if (!(chip->image[CS4231_IFACE_CTRL]     
1170                 return 0;                        
1171         ptr = snd_dma_pointer(chip->dma2, chi    
1172         return bytes_to_frames(substream->run    
1173 }                                                
1174                                                  
1175 /*                                               
1176                                                  
1177  */                                              
1178                                                  
1179 static int snd_ad1848_probe(struct snd_wss *c    
1180 {                                                
1181         unsigned long timeout = jiffies + mse    
1182         unsigned long flags;                     
1183         unsigned char r;                         
1184         unsigned short hardware = 0;             
1185         int err = 0;                             
1186         int i;                                   
1187                                                  
1188         while (wss_inb(chip, CS4231P(REGSEL))    
1189                 if (time_after(jiffies, timeo    
1190                         return -ENODEV;          
1191                 cond_resched();                  
1192         }                                        
1193         spin_lock_irqsave(&chip->reg_lock, fl    
1194                                                  
1195         /* set CS423x MODE 1 */                  
1196         snd_wss_dout(chip, CS4231_MISC_INFO,     
1197                                                  
1198         snd_wss_dout(chip, CS4231_RIGHT_INPUT    
1199         r = snd_wss_in(chip, CS4231_RIGHT_INP    
1200         if (r != 0x45) {                         
1201                 /* RMGE always high on AD1847    
1202                 if ((r & ~CS4231_ENABLE_MIC_G    
1203                         err = -ENODEV;           
1204                         goto out;                
1205                 }                                
1206                 hardware = WSS_HW_AD1847;        
1207         } else {                                 
1208                 snd_wss_dout(chip, CS4231_LEF    
1209                 r = snd_wss_in(chip, CS4231_L    
1210                 /* L/RMGE always low on AT232    
1211                 if ((r | CS4231_ENABLE_MIC_GA    
1212                         err = -ENODEV;           
1213                         goto out;                
1214                 }                                
1215         }                                        
1216                                                  
1217         /* clear pending IRQ */                  
1218         wss_inb(chip, CS4231P(STATUS));          
1219         wss_outb(chip, CS4231P(STATUS), 0);      
1220         mb();                                    
1221                                                  
1222         if ((chip->hardware & WSS_HW_TYPE_MAS    
1223                 goto out;                        
1224                                                  
1225         if (hardware) {                          
1226                 chip->hardware = hardware;       
1227                 goto out;                        
1228         }                                        
1229                                                  
1230         r = snd_wss_in(chip, CS4231_MISC_INFO    
1231                                                  
1232         /* set CS423x MODE 2 */                  
1233         snd_wss_dout(chip, CS4231_MISC_INFO,     
1234         for (i = 0; i < 16; i++) {               
1235                 if (snd_wss_in(chip, i) != sn    
1236                         /* we have more than     
1237                         if ((r & 0xf) != 0xa)    
1238                                 goto out_mode    
1239                         /*                       
1240                          * on CMI8330, CS4231    
1241                          * can be set to 0       
1242                          */                      
1243                         snd_wss_dout(chip, CS    
1244                         r = snd_wss_in(chip,     
1245                         if (!r)                  
1246                                 chip->hardwar    
1247                         goto out_mode;           
1248                 }                                
1249         }                                        
1250         if (r & 0x80)                            
1251                 chip->hardware = WSS_HW_CS424    
1252         else                                     
1253                 chip->hardware = WSS_HW_AD184    
1254 out_mode:                                        
1255         snd_wss_dout(chip, CS4231_MISC_INFO,     
1256 out:                                             
1257         spin_unlock_irqrestore(&chip->reg_loc    
1258         return err;                              
1259 }                                                
1260                                                  
1261 static int snd_wss_probe(struct snd_wss *chip    
1262 {                                                
1263         unsigned long flags;                     
1264         int i, id, rev, regnum;                  
1265         unsigned char *ptr;                      
1266         unsigned int hw;                         
1267                                                  
1268         id = snd_ad1848_probe(chip);             
1269         if (id < 0)                              
1270                 return id;                       
1271                                                  
1272         hw = chip->hardware;                     
1273         if ((hw & WSS_HW_TYPE_MASK) == WSS_HW    
1274                 for (i = 0; i < 50; i++) {       
1275                         mb();                    
1276                         if (wss_inb(chip, CS4    
1277                                 msleep(2);       
1278                         else {                   
1279                                 spin_lock_irq    
1280                                 snd_wss_out(c    
1281                                             C    
1282                                 id = snd_wss_    
1283                                 spin_unlock_i    
1284                                 if (id == 0x0    
1285                                         break    
1286                         }                        
1287                 }                                
1288                 snd_printdd("wss: port = 0x%l    
1289                 if (id != 0x0a)                  
1290                         return -ENODEV; /* no    
1291                                                  
1292                 rev = snd_wss_in(chip, CS4231    
1293                 snd_printdd("CS4231: VERSION     
1294                 if (rev == 0x80) {               
1295                         unsigned char tmp = s    
1296                         snd_wss_out(chip, 23,    
1297                         if (snd_wss_in(chip,     
1298                                 chip->hardwar    
1299                         else                     
1300                                 chip->hardwar    
1301                 } else if (rev == 0xa0) {        
1302                         chip->hardware = WSS_    
1303                 } else if (rev == 0xa2) {        
1304                         chip->hardware = WSS_    
1305                 } else if (rev == 0xb2) {        
1306                         chip->hardware = WSS_    
1307                 } else if (rev == 0x83) {        
1308                         chip->hardware = WSS_    
1309                 } else if (rev == 0x03) {        
1310                         chip->hardware = WSS_    
1311                 } else {                         
1312                         snd_printk(KERN_ERR      
1313                                    "unknown C    
1314                         return -ENODEV;          
1315                 }                                
1316         }                                        
1317         spin_lock_irqsave(&chip->reg_lock, fl    
1318         wss_inb(chip, CS4231P(STATUS)); /* cl    
1319         wss_outb(chip, CS4231P(STATUS), 0);      
1320         mb();                                    
1321         spin_unlock_irqrestore(&chip->reg_loc    
1322                                                  
1323         if (!(chip->hardware & WSS_HW_AD1848_    
1324                 chip->image[CS4231_MISC_INFO]    
1325         switch (chip->hardware) {                
1326         case WSS_HW_INTERWAVE:                   
1327                 chip->image[CS4231_MISC_INFO]    
1328                 break;                           
1329         case WSS_HW_CS4235:                      
1330         case WSS_HW_CS4236B:                     
1331         case WSS_HW_CS4237B:                     
1332         case WSS_HW_CS4238B:                     
1333         case WSS_HW_CS4239:                      
1334                 if (hw == WSS_HW_DETECT3)        
1335                         chip->image[CS4231_MI    
1336                 else                             
1337                         chip->hardware = WSS_    
1338                 break;                           
1339         }                                        
1340                                                  
1341         chip->image[CS4231_IFACE_CTRL] =         
1342             (chip->image[CS4231_IFACE_CTRL] &    
1343             (chip->single_dma ? CS4231_SINGLE    
1344         if (chip->hardware != WSS_HW_OPTI93X)    
1345                 chip->image[CS4231_ALT_FEATUR    
1346                 chip->image[CS4231_ALT_FEATUR    
1347                         chip->hardware == WSS    
1348         }                                        
1349         /* enable fine grained frequency sele    
1350         if (chip->hardware == WSS_HW_AD1845)     
1351                 chip->image[AD1845_PWR_DOWN]     
1352                                                  
1353         ptr = (unsigned char *) &chip->image;    
1354         regnum = (chip->hardware & WSS_HW_AD1    
1355         snd_wss_mce_down(chip);                  
1356         spin_lock_irqsave(&chip->reg_lock, fl    
1357         for (i = 0; i < regnum; i++)    /* ok    
1358                 snd_wss_out(chip, i, *ptr++);    
1359         spin_unlock_irqrestore(&chip->reg_loc    
1360         snd_wss_mce_up(chip);                    
1361         snd_wss_mce_down(chip);                  
1362                                                  
1363         mdelay(2);                               
1364                                                  
1365         /* ok.. try check hardware version fo    
1366         if ((hw & WSS_HW_TYPE_MASK) == WSS_HW    
1367                 if (chip->hardware == WSS_HW_    
1368                         rev = snd_cs4236_ext_    
1369                         snd_cs4236_ext_out(ch    
1370                         id = snd_cs4236_ext_i    
1371                         snd_cs4236_ext_out(ch    
1372                         snd_printdd("CS4231:     
1373                         if ((id & 0x1f) == 0x    
1374                                 chip->hardwar    
1375                                 switch (id >>    
1376                                 case 4:          
1377                                 case 5:          
1378                                 case 6:          
1379                                         break    
1380                                 default:         
1381                                         snd_p    
1382                                                  
1383                                                  
1384                                                  
1385                                 }                
1386                         } else if ((id & 0x1f    
1387                                 switch (id >>    
1388                                 case 4:          
1389                                 case 5:          
1390                                 case 6:          
1391                                 case 7:          
1392                                         chip-    
1393                                         break    
1394                                 default:         
1395                                         snd_p    
1396                                                  
1397                                                  
1398                                                  
1399                                 }                
1400                         } else if ((id & 0x1f    
1401                                 chip->hardwar    
1402                                 switch (id >>    
1403                                 case 4:          
1404                                 case 5:          
1405                                 case 6:          
1406                                 case 7:          
1407                                         break    
1408                                 default:         
1409                                         snd_p    
1410                                                  
1411                                                  
1412                                                  
1413                                 }                
1414                         } else if ((id & 0x1f    
1415                                 chip->hardwar    
1416                                 switch (id >>    
1417                                 case 5:          
1418                                 case 6:          
1419                                 case 7:          
1420                                         break    
1421                                 default:         
1422                                         snd_p    
1423                                                  
1424                                                  
1425                                                  
1426                                 }                
1427                         } else if ((id & 0x1f    
1428                                 chip->hardwar    
1429                                 switch (id >>    
1430                                 case 4:          
1431                                 case 5:          
1432                                 case 6:          
1433                                         break    
1434                                 default:         
1435                                         snd_p    
1436                                                  
1437                                                  
1438                                                  
1439                                 }                
1440                         } else {                 
1441                                 snd_printk(KE    
1442                                            "u    
1443                                            "(    
1444                         }                        
1445                 }                                
1446         }                                        
1447         return 0;               /* all things    
1448 }                                                
1449                                                  
1450 /*                                               
1451                                                  
1452  */                                              
1453                                                  
1454 static struct snd_pcm_hardware snd_wss_playba    
1455 {                                                
1456         .info =                 (SNDRV_PCM_IN    
1457                                  SNDRV_PCM_IN    
1458                                  SNDRV_PCM_IN    
1459                                  SNDRV_PCM_IN    
1460         .formats =              (SNDRV_PCM_FM    
1461                                  SNDRV_PCM_FM    
1462         .rates =                SNDRV_PCM_RAT    
1463         .rate_min =             5510,            
1464         .rate_max =             48000,           
1465         .channels_min =         1,               
1466         .channels_max =         2,               
1467         .buffer_bytes_max =     (128*1024),      
1468         .period_bytes_min =     64,              
1469         .period_bytes_max =     (128*1024),      
1470         .periods_min =          1,               
1471         .periods_max =          1024,            
1472         .fifo_size =            0,               
1473 };                                               
1474                                                  
1475 static struct snd_pcm_hardware snd_wss_captur    
1476 {                                                
1477         .info =                 (SNDRV_PCM_IN    
1478                                  SNDRV_PCM_IN    
1479                                  SNDRV_PCM_IN    
1480                                  SNDRV_PCM_IN    
1481         .formats =              (SNDRV_PCM_FM    
1482                                  SNDRV_PCM_FM    
1483         .rates =                SNDRV_PCM_RAT    
1484         .rate_min =             5510,            
1485         .rate_max =             48000,           
1486         .channels_min =         1,               
1487         .channels_max =         2,               
1488         .buffer_bytes_max =     (128*1024),      
1489         .period_bytes_min =     64,              
1490         .period_bytes_max =     (128*1024),      
1491         .periods_min =          1,               
1492         .periods_max =          1024,            
1493         .fifo_size =            0,               
1494 };                                               
1495                                                  
1496 /*                                               
1497                                                  
1498  */                                              
1499                                                  
1500 static int snd_wss_playback_open(struct snd_p    
1501 {                                                
1502         struct snd_wss *chip = snd_pcm_substr    
1503         struct snd_pcm_runtime *runtime = sub    
1504         int err;                                 
1505                                                  
1506         runtime->hw = snd_wss_playback;          
1507                                                  
1508         /* hardware limitation of older chips    
1509         if (chip->hardware & WSS_HW_AD1848_MA    
1510                 runtime->hw.formats &= ~(SNDR    
1511                                          SNDR    
1512                                                  
1513         /* hardware bug in InterWave chipset     
1514         if (chip->hardware == WSS_HW_INTERWAV    
1515                 runtime->hw.formats &= ~SNDRV    
1516                                                  
1517         /* hardware limitation of cheap chips    
1518         if (chip->hardware == WSS_HW_CS4235 |    
1519             chip->hardware == WSS_HW_CS4239)     
1520                 runtime->hw.formats = SNDRV_P    
1521                                                  
1522         snd_pcm_limit_isa_dma_size(chip->dma1    
1523         snd_pcm_limit_isa_dma_size(chip->dma1    
1524                                                  
1525         if (chip->claim_dma) {                   
1526                 if ((err = chip->claim_dma(ch    
1527                         return err;              
1528         }                                        
1529                                                  
1530         err = snd_wss_open(chip, WSS_MODE_PLA    
1531         if (err < 0) {                           
1532                 if (chip->release_dma)           
1533                         chip->release_dma(chi    
1534                 snd_free_pages(runtime->dma_a    
1535                 return err;                      
1536         }                                        
1537         chip->playback_substream = substream;    
1538         snd_pcm_set_sync(substream);             
1539         chip->rate_constraint(runtime);          
1540         return 0;                                
1541 }                                                
1542                                                  
1543 static int snd_wss_capture_open(struct snd_pc    
1544 {                                                
1545         struct snd_wss *chip = snd_pcm_substr    
1546         struct snd_pcm_runtime *runtime = sub    
1547         int err;                                 
1548                                                  
1549         runtime->hw = snd_wss_capture;           
1550                                                  
1551         /* hardware limitation of older chips    
1552         if (chip->hardware & WSS_HW_AD1848_MA    
1553                 runtime->hw.formats &= ~(SNDR    
1554                                          SNDR    
1555                                                  
1556         /* hardware limitation of cheap chips    
1557         if (chip->hardware == WSS_HW_CS4235 |    
1558             chip->hardware == WSS_HW_CS4239 |    
1559             chip->hardware == WSS_HW_OPTI93X)    
1560                 runtime->hw.formats = SNDRV_P    
1561                                       SNDRV_P    
1562                                                  
1563         snd_pcm_limit_isa_dma_size(chip->dma2    
1564         snd_pcm_limit_isa_dma_size(chip->dma2    
1565                                                  
1566         if (chip->claim_dma) {                   
1567                 if ((err = chip->claim_dma(ch    
1568                         return err;              
1569         }                                        
1570                                                  
1571         err = snd_wss_open(chip, WSS_MODE_REC    
1572         if (err < 0) {                           
1573                 if (chip->release_dma)           
1574                         chip->release_dma(chi    
1575                 snd_free_pages(runtime->dma_a    
1576                 return err;                      
1577         }                                        
1578         chip->capture_substream = substream;     
1579         snd_pcm_set_sync(substream);             
1580         chip->rate_constraint(runtime);          
1581         return 0;                                
1582 }                                                
1583                                                  
1584 static int snd_wss_playback_close(struct snd_    
1585 {                                                
1586         struct snd_wss *chip = snd_pcm_substr    
1587                                                  
1588         chip->playback_substream = NULL;         
1589         snd_wss_close(chip, WSS_MODE_PLAY);      
1590         return 0;                                
1591 }                                                
1592                                                  
1593 static int snd_wss_capture_close(struct snd_p    
1594 {                                                
1595         struct snd_wss *chip = snd_pcm_substr    
1596                                                  
1597         chip->capture_substream = NULL;          
1598         snd_wss_close(chip, WSS_MODE_RECORD);    
1599         return 0;                                
1600 }                                                
1601                                                  
1602 static void snd_wss_thinkpad_twiddle(struct s    
1603 {                                                
1604         int tmp;                                 
1605                                                  
1606         if (!chip->thinkpad_flag)                
1607                 return;                          
1608                                                  
1609         outb(0x1c, AD1848_THINKPAD_CTL_PORT1)    
1610         tmp = inb(AD1848_THINKPAD_CTL_PORT2);    
1611                                                  
1612         if (on)                                  
1613                 /* turn it on */                 
1614                 tmp |= AD1848_THINKPAD_CS4248    
1615         else                                     
1616                 /* turn it off */                
1617                 tmp &= ~AD1848_THINKPAD_CS424    
1618                                                  
1619         outb(tmp, AD1848_THINKPAD_CTL_PORT2);    
1620 }                                                
1621                                                  
1622 #ifdef CONFIG_PM                                 
1623                                                  
1624 /* lowlevel suspend callback for CS4231 */       
1625 static void snd_wss_suspend(struct snd_wss *c    
1626 {                                                
1627         int reg;                                 
1628         unsigned long flags;                     
1629                                                  
1630         snd_pcm_suspend_all(chip->pcm);          
1631         spin_lock_irqsave(&chip->reg_lock, fl    
1632         for (reg = 0; reg < 32; reg++)           
1633                 chip->image[reg] = snd_wss_in    
1634         spin_unlock_irqrestore(&chip->reg_loc    
1635         if (chip->thinkpad_flag)                 
1636                 snd_wss_thinkpad_twiddle(chip    
1637 }                                                
1638                                                  
1639 /* lowlevel resume callback for CS4231 */        
1640 static void snd_wss_resume(struct snd_wss *ch    
1641 {                                                
1642         int reg;                                 
1643         unsigned long flags;                     
1644         /* int timeout; */                       
1645                                                  
1646         if (chip->thinkpad_flag)                 
1647                 snd_wss_thinkpad_twiddle(chip    
1648         snd_wss_mce_up(chip);                    
1649         spin_lock_irqsave(&chip->reg_lock, fl    
1650         for (reg = 0; reg < 32; reg++) {         
1651                 switch (reg) {                   
1652                 case CS4231_VERSION:             
1653                         break;                   
1654                 default:                         
1655                         snd_wss_out(chip, reg    
1656                         break;                   
1657                 }                                
1658         }                                        
1659         spin_unlock_irqrestore(&chip->reg_loc    
1660 #if 1                                            
1661         snd_wss_mce_down(chip);                  
1662 #else                                            
1663         /* The following is a workaround to a    
1664            This is the first half of copy of     
1665            include rescheduling.  -- iwai        
1666            */                                    
1667         snd_wss_busy_wait(chip);                 
1668         spin_lock_irqsave(&chip->reg_lock, fl    
1669         chip->mce_bit &= ~CS4231_MCE;            
1670         timeout = wss_inb(chip, CS4231P(REGSE    
1671         wss_outb(chip, CS4231P(REGSEL), chip-    
1672         spin_unlock_irqrestore(&chip->reg_loc    
1673         if (timeout == 0x80)                     
1674                 snd_printk(KERN_ERR "down [0x    
1675                            "- codec still bus    
1676         if ((timeout & CS4231_MCE) == 0 ||       
1677             !(chip->hardware & (WSS_HW_CS4231    
1678                 return;                          
1679         }                                        
1680         snd_wss_busy_wait(chip);                 
1681 #endif                                           
1682 }                                                
1683 #endif /* CONFIG_PM */                           
1684                                                  
1685 int snd_wss_free(struct snd_wss *chip)           
1686 {                                                
1687         release_and_free_resource(chip->res_p    
1688         release_and_free_resource(chip->res_c    
1689         if (chip->irq >= 0) {                    
1690                 disable_irq(chip->irq);          
1691                 if (!(chip->hwshare & WSS_HWS    
1692                         free_irq(chip->irq, (    
1693         }                                        
1694         if (!(chip->hwshare & WSS_HWSHARE_DMA    
1695                 snd_dma_disable(chip->dma1);     
1696                 free_dma(chip->dma1);            
1697         }                                        
1698         if (!(chip->hwshare & WSS_HWSHARE_DMA    
1699             chip->dma2 >= 0 && chip->dma2 !=     
1700                 snd_dma_disable(chip->dma2);     
1701                 free_dma(chip->dma2);            
1702         }                                        
1703         if (chip->timer)                         
1704                 snd_device_free(chip->card, c    
1705         kfree(chip);                             
1706         return 0;                                
1707 }                                                
1708 EXPORT_SYMBOL(snd_wss_free);                     
1709                                                  
1710 static int snd_wss_dev_free(struct snd_device    
1711 {                                                
1712         struct snd_wss *chip = device->device    
1713         return snd_wss_free(chip);               
1714 }                                                
1715                                                  
1716 const char *snd_wss_chip_id(struct snd_wss *c    
1717 {                                                
1718         switch (chip->hardware) {                
1719         case WSS_HW_CS4231:                      
1720                 return "CS4231";                 
1721         case WSS_HW_CS4231A:                     
1722                 return "CS4231A";                
1723         case WSS_HW_CS4232:                      
1724                 return "CS4232";                 
1725         case WSS_HW_CS4232A:                     
1726                 return "CS4232A";                
1727         case WSS_HW_CS4235:                      
1728                 return "CS4235";                 
1729         case WSS_HW_CS4236:                      
1730                 return "CS4236";                 
1731         case WSS_HW_CS4236B:                     
1732                 return "CS4236B";                
1733         case WSS_HW_CS4237B:                     
1734                 return "CS4237B";                
1735         case WSS_HW_CS4238B:                     
1736                 return "CS4238B";                
1737         case WSS_HW_CS4239:                      
1738                 return "CS4239";                 
1739         case WSS_HW_INTERWAVE:                   
1740                 return "AMD InterWave";          
1741         case WSS_HW_OPL3SA2:                     
1742                 return chip->card->shortname;    
1743         case WSS_HW_AD1845:                      
1744                 return "AD1845";                 
1745         case WSS_HW_OPTI93X:                     
1746                 return "OPTi 93x";               
1747         case WSS_HW_AD1847:                      
1748                 return "AD1847";                 
1749         case WSS_HW_AD1848:                      
1750                 return "AD1848";                 
1751         case WSS_HW_CS4248:                      
1752                 return "CS4248";                 
1753         case WSS_HW_CMI8330:                     
1754                 return "CMI8330/C3D";            
1755         default:                                 
1756                 return "???";                    
1757         }                                        
1758 }                                                
1759 EXPORT_SYMBOL(snd_wss_chip_id);                  
1760                                                  
1761 static int snd_wss_new(struct snd_card *card,    
1762                           unsigned short hard    
1763                           unsigned short hwsh    
1764                           struct snd_wss **rc    
1765 {                                                
1766         struct snd_wss *chip;                    
1767                                                  
1768         *rchip = NULL;                           
1769         chip = kzalloc(sizeof(*chip), GFP_KER    
1770         if (chip == NULL)                        
1771                 return -ENOMEM;                  
1772         chip->hardware = hardware;               
1773         chip->hwshare = hwshare;                 
1774                                                  
1775         spin_lock_init(&chip->reg_lock);         
1776         mutex_init(&chip->mce_mutex);            
1777         mutex_init(&chip->open_mutex);           
1778         chip->card = card;                       
1779         chip->rate_constraint = snd_wss_xrate    
1780         chip->set_playback_format = snd_wss_p    
1781         chip->set_capture_format = snd_wss_ca    
1782         if (chip->hardware == WSS_HW_OPTI93X)    
1783                 memcpy(&chip->image, &snd_opt    
1784                        sizeof(snd_opti93x_ori    
1785         else                                     
1786                 memcpy(&chip->image, &snd_wss    
1787                        sizeof(snd_wss_origina    
1788         if (chip->hardware & WSS_HW_AD1848_MA    
1789                 chip->image[CS4231_PIN_CTRL]     
1790                 chip->image[CS4231_TEST_INIT]    
1791         }                                        
1792                                                  
1793         *rchip = chip;                           
1794         return 0;                                
1795 }                                                
1796                                                  
1797 int snd_wss_create(struct snd_card *card,        
1798                       unsigned long port,        
1799                       unsigned long cport,       
1800                       int irq, int dma1, int     
1801                       unsigned short hardware    
1802                       unsigned short hwshare,    
1803                       struct snd_wss **rchip)    
1804 {                                                
1805         static struct snd_device_ops ops = {     
1806                 .dev_free =     snd_wss_dev_f    
1807         };                                       
1808         struct snd_wss *chip;                    
1809         int err;                                 
1810                                                  
1811         err = snd_wss_new(card, hardware, hws    
1812         if (err < 0)                             
1813                 return err;                      
1814                                                  
1815         chip->irq = -1;                          
1816         chip->dma1 = -1;                         
1817         chip->dma2 = -1;                         
1818                                                  
1819         chip->res_port = request_region(port,    
1820         if (!chip->res_port) {                   
1821                 snd_printk(KERN_ERR "wss: can    
1822                 snd_wss_free(chip);              
1823                 return -EBUSY;                   
1824         }                                        
1825         chip->port = port;                       
1826         if ((long)cport >= 0) {                  
1827                 chip->res_cport = request_reg    
1828                 if (!chip->res_cport) {          
1829                         snd_printk(KERN_ERR      
1830                                 "wss: can't g    
1831                         snd_wss_free(chip);      
1832                         return -ENODEV;          
1833                 }                                
1834         }                                        
1835         chip->cport = cport;                     
1836         if (!(hwshare & WSS_HWSHARE_IRQ))        
1837                 if (request_irq(irq, snd_wss_    
1838                                 "WSS", (void     
1839                         snd_printk(KERN_ERR "    
1840                         snd_wss_free(chip);      
1841                         return -EBUSY;           
1842                 }                                
1843         chip->irq = irq;                         
1844         if (!(hwshare & WSS_HWSHARE_DMA1) &&     
1845                 snd_printk(KERN_ERR "wss: can    
1846                 snd_wss_free(chip);              
1847                 return -EBUSY;                   
1848         }                                        
1849         chip->dma1 = dma1;                       
1850         if (!(hwshare & WSS_HWSHARE_DMA2) &&     
1851               dma2 >= 0 && request_dma(dma2,     
1852                 snd_printk(KERN_ERR "wss: can    
1853                 snd_wss_free(chip);              
1854                 return -EBUSY;                   
1855         }                                        
1856         if (dma1 == dma2 || dma2 < 0) {          
1857                 chip->single_dma = 1;            
1858                 chip->dma2 = chip->dma1;         
1859         } else                                   
1860                 chip->dma2 = dma2;               
1861                                                  
1862         if (hardware == WSS_HW_THINKPAD) {       
1863                 chip->thinkpad_flag = 1;         
1864                 chip->hardware = WSS_HW_DETEC    
1865                 snd_wss_thinkpad_twiddle(chip    
1866         }                                        
1867                                                  
1868         /* global setup */                       
1869         if (snd_wss_probe(chip) < 0) {           
1870                 snd_wss_free(chip);              
1871                 return -ENODEV;                  
1872         }                                        
1873         snd_wss_init(chip);                      
1874                                                  
1875 #if 0                                            
1876         if (chip->hardware & WSS_HW_CS4232_MA    
1877                 if (chip->res_cport == NULL)     
1878                         snd_printk(KERN_ERR "    
1879                                    "not acces    
1880         }                                        
1881 #endif                                           
1882                                                  
1883         /* Register device */                    
1884         err = snd_device_new(card, SNDRV_DEV_    
1885         if (err < 0) {                           
1886                 snd_wss_free(chip);              
1887                 return err;                      
1888         }                                        
1889                                                  
1890 #ifdef CONFIG_PM                                 
1891         /* Power Management */                   
1892         chip->suspend = snd_wss_suspend;         
1893         chip->resume = snd_wss_resume;           
1894 #endif                                           
1895                                                  
1896         *rchip = chip;                           
1897         return 0;                                
1898 }                                                
1899 EXPORT_SYMBOL(snd_wss_create);                   
1900                                                  
1901 static struct snd_pcm_ops snd_wss_playback_op    
1902         .open =         snd_wss_playback_open    
1903         .close =        snd_wss_playback_clos    
1904         .ioctl =        snd_pcm_lib_ioctl,       
1905         .hw_params =    snd_wss_playback_hw_p    
1906         .hw_free =      snd_wss_playback_hw_f    
1907         .prepare =      snd_wss_playback_prep    
1908         .trigger =      snd_wss_trigger,         
1909         .pointer =      snd_wss_playback_poin    
1910 };                                               
1911                                                  
1912 static struct snd_pcm_ops snd_wss_capture_ops    
1913         .open =         snd_wss_capture_open,    
1914         .close =        snd_wss_capture_close    
1915         .ioctl =        snd_pcm_lib_ioctl,       
1916         .hw_params =    snd_wss_capture_hw_pa    
1917         .hw_free =      snd_wss_capture_hw_fr    
1918         .prepare =      snd_wss_capture_prepa    
1919         .trigger =      snd_wss_trigger,         
1920         .pointer =      snd_wss_capture_point    
1921 };                                               
1922                                                  
1923 int snd_wss_pcm(struct snd_wss *chip, int dev    
1924 {                                                
1925         struct snd_pcm *pcm;                     
1926         int err;                                 
1927                                                  
1928         err = snd_pcm_new(chip->card, "WSS",     
1929         if (err < 0)                             
1930                 return err;                      
1931                                                  
1932         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM    
1933         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM    
1934                                                  
1935         /* global setup */                       
1936         pcm->private_data = chip;                
1937         pcm->info_flags = 0;                     
1938         if (chip->single_dma)                    
1939                 pcm->info_flags |= SNDRV_PCM_    
1940         if (chip->hardware != WSS_HW_INTERWAV    
1941                 pcm->info_flags |= SNDRV_PCM_    
1942         strcpy(pcm->name, snd_wss_chip_id(chi    
1943                                                  
1944         snd_pcm_lib_preallocate_pages_for_all    
1945                                                  
1946                                                  
1947                                                  
1948         chip->pcm = pcm;                         
1949         if (rpcm)                                
1950                 *rpcm = pcm;                     
1951         return 0;                                
1952 }                                                
1953 EXPORT_SYMBOL(snd_wss_pcm);                      
1954                                                  
1955 static void snd_wss_timer_free(struct snd_tim    
1956 {                                                
1957         struct snd_wss *chip = timer->private    
1958         chip->timer = NULL;                      
1959 }                                                
1960                                                  
1961 int snd_wss_timer(struct snd_wss *chip, int d    
1962 {                                                
1963         struct snd_timer *timer;                 
1964         struct snd_timer_id tid;                 
1965         int err;                                 
1966                                                  
1967         /* Timer initialization */               
1968         tid.dev_class = SNDRV_TIMER_CLASS_CAR    
1969         tid.dev_sclass = SNDRV_TIMER_SCLASS_N    
1970         tid.card = chip->card->number;           
1971         tid.device = device;                     
1972         tid.subdevice = 0;                       
1973         if ((err = snd_timer_new(chip->card,     
1974                 return err;                      
1975         strcpy(timer->name, snd_wss_chip_id(c    
1976         timer->private_data = chip;              
1977         timer->private_free = snd_wss_timer_f    
1978         timer->hw = snd_wss_timer_table;         
1979         chip->timer = timer;                     
1980         if (rtimer)                              
1981                 *rtimer = timer;                 
1982         return 0;                                
1983 }                                                
1984 EXPORT_SYMBOL(snd_wss_timer);                    
1985                                                  
1986 /*                                               
1987  *  MIXER part                                   
1988  */                                              
1989                                                  
1990 static int snd_wss_info_mux(struct snd_kcontr    
1991                             struct snd_ctl_el    
1992 {                                                
1993         static char *texts[4] = {                
1994                 "Line", "Aux", "Mic", "Mix"      
1995         };                                       
1996         static char *opl3sa_texts[4] = {         
1997                 "Line", "CD", "Mic", "Mix"       
1998         };                                       
1999         static char *gusmax_texts[4] = {         
2000                 "Line", "Synth", "Mic", "Mix"    
2001         };                                       
2002         char **ptexts = texts;                   
2003         struct snd_wss *chip = snd_kcontrol_c    
2004                                                  
2005         if (snd_BUG_ON(!chip->card))             
2006                 return -EINVAL;                  
2007         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENU    
2008         uinfo->count = 2;                        
2009         uinfo->value.enumerated.items = 4;       
2010         if (uinfo->value.enumerated.item > 3)    
2011                 uinfo->value.enumerated.item     
2012         if (!strcmp(chip->card->driver, "GUS     
2013                 ptexts = gusmax_texts;           
2014         switch (chip->hardware) {                
2015         case WSS_HW_INTERWAVE:                   
2016                 ptexts = gusmax_texts;           
2017                 break;                           
2018         case WSS_HW_OPL3SA2:                     
2019                 ptexts = opl3sa_texts;           
2020                 break;                           
2021         }                                        
2022         strcpy(uinfo->value.enumerated.name,     
2023         return 0;                                
2024 }                                                
2025                                                  
2026 static int snd_wss_get_mux(struct snd_kcontro    
2027                            struct snd_ctl_ele    
2028 {                                                
2029         struct snd_wss *chip = snd_kcontrol_c    
2030         unsigned long flags;                     
2031                                                  
2032         spin_lock_irqsave(&chip->reg_lock, fl    
2033         ucontrol->value.enumerated.item[0] =     
2034         ucontrol->value.enumerated.item[1] =     
2035         spin_unlock_irqrestore(&chip->reg_loc    
2036         return 0;                                
2037 }                                                
2038                                                  
2039 static int snd_wss_put_mux(struct snd_kcontro    
2040                            struct snd_ctl_ele    
2041 {                                                
2042         struct snd_wss *chip = snd_kcontrol_c    
2043         unsigned long flags;                     
2044         unsigned short left, right;              
2045         int change;                              
2046                                                  
2047         if (ucontrol->value.enumerated.item[0    
2048             ucontrol->value.enumerated.item[1    
2049                 return -EINVAL;                  
2050         left = ucontrol->value.enumerated.ite    
2051         right = ucontrol->value.enumerated.it    
2052         spin_lock_irqsave(&chip->reg_lock, fl    
2053         left = (chip->image[CS4231_LEFT_INPUT    
2054         right = (chip->image[CS4231_RIGHT_INP    
2055         change = left != chip->image[CS4231_L    
2056                  right != chip->image[CS4231_    
2057         snd_wss_out(chip, CS4231_LEFT_INPUT,     
2058         snd_wss_out(chip, CS4231_RIGHT_INPUT,    
2059         spin_unlock_irqrestore(&chip->reg_loc    
2060         return change;                           
2061 }                                                
2062                                                  
2063 int snd_wss_info_single(struct snd_kcontrol *    
2064                         struct snd_ctl_elem_i    
2065 {                                                
2066         int mask = (kcontrol->private_value >    
2067                                                  
2068         uinfo->type = mask == 1 ? SNDRV_CTL_E    
2069         uinfo->count = 1;                        
2070         uinfo->value.integer.min = 0;            
2071         uinfo->value.integer.max = mask;         
2072         return 0;                                
2073 }                                                
2074 EXPORT_SYMBOL(snd_wss_info_single);              
2075                                                  
2076 int snd_wss_get_single(struct snd_kcontrol *k    
2077                        struct snd_ctl_elem_va    
2078 {                                                
2079         struct snd_wss *chip = snd_kcontrol_c    
2080         unsigned long flags;                     
2081         int reg = kcontrol->private_value & 0    
2082         int shift = (kcontrol->private_value     
2083         int mask = (kcontrol->private_value >    
2084         int invert = (kcontrol->private_value    
2085                                                  
2086         spin_lock_irqsave(&chip->reg_lock, fl    
2087         ucontrol->value.integer.value[0] = (c    
2088         spin_unlock_irqrestore(&chip->reg_loc    
2089         if (invert)                              
2090                 ucontrol->value.integer.value    
2091         return 0;                                
2092 }                                                
2093 EXPORT_SYMBOL(snd_wss_get_single);               
2094                                                  
2095 int snd_wss_put_single(struct snd_kcontrol *k    
2096                        struct snd_ctl_elem_va    
2097 {                                                
2098         struct snd_wss *chip = snd_kcontrol_c    
2099         unsigned long flags;                     
2100         int reg = kcontrol->private_value & 0    
2101         int shift = (kcontrol->private_value     
2102         int mask = (kcontrol->private_value >    
2103         int invert = (kcontrol->private_value    
2104         int change;                              
2105         unsigned short val;                      
2106                                                  
2107         val = (ucontrol->value.integer.value[    
2108         if (invert)                              
2109                 val = mask - val;                
2110         val <<= shift;                           
2111         spin_lock_irqsave(&chip->reg_lock, fl    
2112         val = (chip->image[reg] & ~(mask << s    
2113         change = val != chip->image[reg];        
2114         snd_wss_out(chip, reg, val);             
2115         spin_unlock_irqrestore(&chip->reg_loc    
2116         return change;                           
2117 }                                                
2118 EXPORT_SYMBOL(snd_wss_put_single);               
2119                                                  
2120 int snd_wss_info_double(struct snd_kcontrol *    
2121                         struct snd_ctl_elem_i    
2122 {                                                
2123         int mask = (kcontrol->private_value >    
2124                                                  
2125         uinfo->type = mask == 1 ? SNDRV_CTL_E    
2126         uinfo->count = 2;                        
2127         uinfo->value.integer.min = 0;            
2128         uinfo->value.integer.max = mask;         
2129         return 0;                                
2130 }                                                
2131 EXPORT_SYMBOL(snd_wss_info_double);              
2132                                                  
2133 int snd_wss_get_double(struct snd_kcontrol *k    
2134                        struct snd_ctl_elem_va    
2135 {                                                
2136         struct snd_wss *chip = snd_kcontrol_c    
2137         unsigned long flags;                     
2138         int left_reg = kcontrol->private_valu    
2139         int right_reg = (kcontrol->private_va    
2140         int shift_left = (kcontrol->private_v    
2141         int shift_right = (kcontrol->private_    
2142         int mask = (kcontrol->private_value >    
2143         int invert = (kcontrol->private_value    
2144                                                  
2145         spin_lock_irqsave(&chip->reg_lock, fl    
2146         ucontrol->value.integer.value[0] = (c    
2147         ucontrol->value.integer.value[1] = (c    
2148         spin_unlock_irqrestore(&chip->reg_loc    
2149         if (invert) {                            
2150                 ucontrol->value.integer.value    
2151                 ucontrol->value.integer.value    
2152         }                                        
2153         return 0;                                
2154 }                                                
2155 EXPORT_SYMBOL(snd_wss_get_double);               
2156                                                  
2157 int snd_wss_put_double(struct snd_kcontrol *k    
2158                        struct snd_ctl_elem_va    
2159 {                                                
2160         struct snd_wss *chip = snd_kcontrol_c    
2161         unsigned long flags;                     
2162         int left_reg = kcontrol->private_valu    
2163         int right_reg = (kcontrol->private_va    
2164         int shift_left = (kcontrol->private_v    
2165         int shift_right = (kcontrol->private_    
2166         int mask = (kcontrol->private_value >    
2167         int invert = (kcontrol->private_value    
2168         int change;                              
2169         unsigned short val1, val2;               
2170                                                  
2171         val1 = ucontrol->value.integer.value[    
2172         val2 = ucontrol->value.integer.value[    
2173         if (invert) {                            
2174                 val1 = mask - val1;              
2175                 val2 = mask - val2;              
2176         }                                        
2177         val1 <<= shift_left;                     
2178         val2 <<= shift_right;                    
2179         spin_lock_irqsave(&chip->reg_lock, fl    
2180         if (left_reg != right_reg) {             
2181                 val1 = (chip->image[left_reg]    
2182                 val2 = (chip->image[right_reg    
2183                 change = val1 != chip->image[    
2184                          val2 != chip->image[    
2185                 snd_wss_out(chip, left_reg, v    
2186                 snd_wss_out(chip, right_reg,     
2187         } else {                                 
2188                 mask = (mask << shift_left) |    
2189                 val1 = (chip->image[left_reg]    
2190                 change = val1 != chip->image[    
2191                 snd_wss_out(chip, left_reg, v    
2192         }                                        
2193         spin_unlock_irqrestore(&chip->reg_loc    
2194         return change;                           
2195 }                                                
2196 EXPORT_SYMBOL(snd_wss_put_double);               
2197                                                  
2198 static const DECLARE_TLV_DB_SCALE(db_scale_6b    
2199 static const DECLARE_TLV_DB_SCALE(db_scale_5b    
2200 static const DECLARE_TLV_DB_SCALE(db_scale_re    
2201                                                  
2202 static struct snd_kcontrol_new snd_ad1848_con    
2203 WSS_DOUBLE("PCM Playback Switch", 0, CS4231_L    
2204            7, 7, 1, 1),                          
2205 WSS_DOUBLE_TLV("PCM Playback Volume", 0,         
2206                CS4231_LEFT_OUTPUT, CS4231_RIG    
2207                db_scale_6bit),                   
2208 WSS_DOUBLE("Aux Playback Switch", 0,             
2209            CS4231_AUX1_LEFT_INPUT, CS4231_AUX    
2210 WSS_DOUBLE_TLV("Aux Playback Volume", 0,         
2211                CS4231_AUX1_LEFT_INPUT, CS4231    
2212                db_scale_5bit_12db_max),          
2213 WSS_DOUBLE("Aux Playback Switch", 1,             
2214            CS4231_AUX2_LEFT_INPUT, CS4231_AUX    
2215 WSS_DOUBLE_TLV("Aux Playback Volume", 1,         
2216                CS4231_AUX2_LEFT_INPUT, CS4231    
2217                db_scale_5bit_12db_max),          
2218 WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LE    
2219                 0, 0, 15, 0, db_scale_rec_gai    
2220 {                                                
2221         .name = "Capture Source",                
2222         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,     
2223         .info = snd_wss_info_mux,                
2224         .get = snd_wss_get_mux,                  
2225         .put = snd_wss_put_mux,                  
2226 },                                               
2227 WSS_SINGLE("Loopback Capture Switch", 0, CS42    
2228 WSS_SINGLE_TLV("Loopback Capture Volume", 0,     
2229                db_scale_6bit),                   
2230 };                                               
2231                                                  
2232 static struct snd_kcontrol_new snd_wss_contro    
2233 WSS_DOUBLE("PCM Playback Switch", 0,             
2234                 CS4231_LEFT_OUTPUT, CS4231_RI    
2235 WSS_DOUBLE("PCM Playback Volume", 0,             
2236                 CS4231_LEFT_OUTPUT, CS4231_RI    
2237 WSS_DOUBLE("Line Playback Switch", 0,            
2238                 CS4231_LEFT_LINE_IN, CS4231_R    
2239 WSS_DOUBLE("Line Playback Volume", 0,            
2240                 CS4231_LEFT_LINE_IN, CS4231_R    
2241 WSS_DOUBLE("Aux Playback Switch", 0,             
2242                 CS4231_AUX1_LEFT_INPUT, CS423    
2243 WSS_DOUBLE("Aux Playback Volume", 0,             
2244                 CS4231_AUX1_LEFT_INPUT, CS423    
2245 WSS_DOUBLE("Aux Playback Switch", 1,             
2246                 CS4231_AUX2_LEFT_INPUT, CS423    
2247 WSS_DOUBLE("Aux Playback Volume", 1,             
2248                 CS4231_AUX2_LEFT_INPUT, CS423    
2249 WSS_SINGLE("Mono Playback Switch", 0,            
2250                 CS4231_MONO_CTRL, 7, 1, 1),      
2251 WSS_SINGLE("Mono Playback Volume", 0,            
2252                 CS4231_MONO_CTRL, 0, 15, 1),     
2253 WSS_SINGLE("Mono Output Playback Switch", 0,     
2254                 CS4231_MONO_CTRL, 6, 1, 1),      
2255 WSS_SINGLE("Mono Output Playback Bypass", 0,     
2256                 CS4231_MONO_CTRL, 5, 1, 0),      
2257 WSS_DOUBLE("Capture Volume", 0,                  
2258                 CS4231_LEFT_INPUT, CS4231_RIG    
2259 {                                                
2260         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,     
2261         .name = "Capture Source",                
2262         .info = snd_wss_info_mux,                
2263         .get = snd_wss_get_mux,                  
2264         .put = snd_wss_put_mux,                  
2265 },                                               
2266 WSS_DOUBLE("Mic Boost", 0,                       
2267                 CS4231_LEFT_INPUT, CS4231_RIG    
2268 WSS_SINGLE("Loopback Capture Switch", 0,         
2269                 CS4231_LOOPBACK, 0, 1, 0),       
2270 WSS_SINGLE("Loopback Capture Volume", 0,         
2271                 CS4231_LOOPBACK, 2, 63, 1)       
2272 };                                               
2273                                                  
2274 static struct snd_kcontrol_new snd_opti93x_co    
2275 WSS_DOUBLE("Master Playback Switch", 0,          
2276                 OPTi93X_OUT_LEFT, OPTi93X_OUT    
2277 WSS_DOUBLE("Master Playback Volume", 0,          
2278                 OPTi93X_OUT_LEFT, OPTi93X_OUT    
2279 WSS_DOUBLE("PCM Playback Switch", 0,             
2280                 CS4231_LEFT_OUTPUT, CS4231_RI    
2281 WSS_DOUBLE("PCM Playback Volume", 0,             
2282                 CS4231_LEFT_OUTPUT, CS4231_RI    
2283 WSS_DOUBLE("FM Playback Switch", 0,              
2284                 CS4231_AUX2_LEFT_INPUT, CS423    
2285 WSS_DOUBLE("FM Playback Volume", 0,              
2286                 CS4231_AUX2_LEFT_INPUT, CS423    
2287 WSS_DOUBLE("Line Playback Switch", 0,            
2288                 CS4231_LEFT_LINE_IN, CS4231_R    
2289 WSS_DOUBLE("Line Playback Volume", 0,            
2290                 CS4231_LEFT_LINE_IN, CS4231_R    
2291 WSS_DOUBLE("Mic Playback Switch", 0,             
2292                 OPTi93X_MIC_LEFT_INPUT, OPTi9    
2293 WSS_DOUBLE("Mic Playback Volume", 0,             
2294                 OPTi93X_MIC_LEFT_INPUT, OPTi9    
2295 WSS_DOUBLE("Mic Boost", 0,                       
2296                 CS4231_LEFT_INPUT, CS4231_RIG    
2297 WSS_DOUBLE("CD Playback Switch", 0,              
2298                 CS4231_AUX1_LEFT_INPUT, CS423    
2299 WSS_DOUBLE("CD Playback Volume", 0,              
2300                 CS4231_AUX1_LEFT_INPUT, CS423    
2301 WSS_DOUBLE("Aux Playback Switch", 0,             
2302                 OPTi931_AUX_LEFT_INPUT, OPTi9    
2303 WSS_DOUBLE("Aux Playback Volume", 0,             
2304                 OPTi931_AUX_LEFT_INPUT, OPTi9    
2305 WSS_DOUBLE("Capture Volume", 0,                  
2306                 CS4231_LEFT_INPUT, CS4231_RIG    
2307 {                                                
2308         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,     
2309         .name = "Capture Source",                
2310         .info = snd_wss_info_mux,                
2311         .get = snd_wss_get_mux,                  
2312         .put = snd_wss_put_mux,                  
2313 }                                                
2314 };                                               
2315                                                  
2316 int snd_wss_mixer(struct snd_wss *chip)          
2317 {                                                
2318         struct snd_card *card;                   
2319         unsigned int idx;                        
2320         int err;                                 
2321                                                  
2322         if (snd_BUG_ON(!chip || !chip->pcm))     
2323                 return -EINVAL;                  
2324                                                  
2325         card = chip->card;                       
2326                                                  
2327         strcpy(card->mixername, chip->pcm->na    
2328                                                  
2329         if (chip->hardware == WSS_HW_OPTI93X)    
2330                 for (idx = 0; idx < ARRAY_SIZ    
2331                         err = snd_ctl_add(car    
2332                                         snd_c    
2333                                                  
2334                         if (err < 0)             
2335                                 return err;      
2336                 }                                
2337         else if (chip->hardware & WSS_HW_AD18    
2338                 for (idx = 0; idx < ARRAY_SIZ    
2339                         err = snd_ctl_add(car    
2340                                         snd_c    
2341                                                  
2342                         if (err < 0)             
2343                                 return err;      
2344                 }                                
2345         else                                     
2346                 for (idx = 0; idx < ARRAY_SIZ    
2347                         err = snd_ctl_add(car    
2348                                         snd_c    
2349                                                  
2350                         if (err < 0)             
2351                                 return err;      
2352                 }                                
2353         return 0;                                
2354 }                                                
2355 EXPORT_SYMBOL(snd_wss_mixer);                    
2356                                                  
2357 const struct snd_pcm_ops *snd_wss_get_pcm_ops    
2358 {                                                
2359         return direction == SNDRV_PCM_STREAM_    
2360                 &snd_wss_playback_ops : &snd_    
2361 }                                                
2362 EXPORT_SYMBOL(snd_wss_get_pcm_ops);              
2363                                                  
2364 /*                                               
2365  *  INIT part                                    
2366  */                                              
2367                                                  
2368 static int __init alsa_wss_init(void)            
2369 {                                                
2370         return 0;                                
2371 }                                                
2372                                                  
2373 static void __exit alsa_wss_exit(void)           
2374 {                                                
2375 }                                                
2376                                                  
2377 module_init(alsa_wss_init);                      
2378 module_exit(alsa_wss_exit);                      
2379                                                  
  This page was automatically generated by the LXR engine.