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

TOMOYO Linux Cross Reference
Linux/sound/ppc/awacs.c

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

Diff markup

Differences between /sound/ppc/awacs.c (Version linux-6.11.5) and /sound/ppc/awacs.c (Version unix-v6-master)


  1 // SPDX-License-Identifier: GPL-2.0-or-later        1 
  2 /*                                                
  3  * PMac AWACS lowlevel functions                  
  4  *                                                
  5  * Copyright (c) by Takashi Iwai <tiwai@suse.d    
  6  * code based on dmasound.c.                      
  7  */                                               
  8                                                   
  9                                                   
 10 #include <linux/io.h>                             
 11 #include <asm/nvram.h>                            
 12 #include <linux/init.h>                           
 13 #include <linux/delay.h>                          
 14 #include <linux/of.h>                             
 15 #include <linux/slab.h>                           
 16 #include <sound/core.h>                           
 17 #include "pmac.h"                                 
 18                                                   
 19                                                   
 20 #ifdef CONFIG_ADB_CUDA                            
 21 #define PMAC_AMP_AVAIL                            
 22 #endif                                            
 23                                                   
 24 #ifdef PMAC_AMP_AVAIL                             
 25 struct awacs_amp {                                
 26         unsigned char amp_master;                 
 27         unsigned char amp_vol[2][2];              
 28         unsigned char amp_tone[2];                
 29 };                                                
 30                                                   
 31 #define CHECK_CUDA_AMP() (sys_ctrler == SYS_CT    
 32                                                   
 33 #endif /* PMAC_AMP_AVAIL */                       
 34                                                   
 35                                                   
 36 static void snd_pmac_screamer_wait(struct snd_    
 37 {                                                 
 38         long timeout = 2000;                      
 39         while (!(in_le32(&chip->awacs->codec_s    
 40                 mdelay(1);                        
 41                 if (! --timeout) {                
 42                         snd_printd("snd_pmac_s    
 43                         break;                    
 44                 }                                 
 45         }                                         
 46 }                                                 
 47                                                   
 48 /*                                                
 49  * write AWACS register                           
 50  */                                               
 51 static void                                       
 52 snd_pmac_awacs_write(struct snd_pmac *chip, in    
 53 {                                                 
 54         long timeout = 5000000;                   
 55                                                   
 56         if (chip->model == PMAC_SCREAMER)         
 57                 snd_pmac_screamer_wait(chip);     
 58         out_le32(&chip->awacs->codec_ctrl, val    
 59         while (in_le32(&chip->awacs->codec_ctr    
 60                 if (! --timeout) {                
 61                         snd_printd("snd_pmac_a    
 62                         break;                    
 63                 }                                 
 64         }                                         
 65 }                                                 
 66                                                   
 67 static void                                       
 68 snd_pmac_awacs_write_reg(struct snd_pmac *chip    
 69 {                                                 
 70         snd_pmac_awacs_write(chip, val | (reg     
 71         chip->awacs_reg[reg] = val;               
 72 }                                                 
 73                                                   
 74 static void                                       
 75 snd_pmac_awacs_write_noreg(struct snd_pmac *ch    
 76 {                                                 
 77         snd_pmac_awacs_write(chip, val | (reg     
 78 }                                                 
 79                                                   
 80 #ifdef CONFIG_PM                                  
 81 /* Recalibrate chip */                            
 82 static void screamer_recalibrate(struct snd_pm    
 83 {                                                 
 84         if (chip->model != PMAC_SCREAMER)         
 85                 return;                           
 86                                                   
 87         /* Sorry for the horrible delays... I     
 88          * by making the whole PM process asyn    
 89          */                                       
 90         snd_pmac_awacs_write_noreg(chip, 1, ch    
 91         if (chip->manufacturer == 0x1)            
 92                 /* delay for broken crystal pa    
 93                 msleep(750);                      
 94         snd_pmac_awacs_write_noreg(chip, 1,       
 95                                    chip->awacs    
 96                                    MASK_CMUTE     
 97         snd_pmac_awacs_write_noreg(chip, 1, ch    
 98         snd_pmac_awacs_write_noreg(chip, 6, ch    
 99 }                                                 
100                                                   
101 #else                                             
102 #define screamer_recalibrate(chip) /* NOP */      
103 #endif                                            
104                                                   
105                                                   
106 /*                                                
107  * additional callback to set the pcm format      
108  */                                               
109 static void snd_pmac_awacs_set_format(struct s    
110 {                                                 
111         chip->awacs_reg[1] &= ~MASK_SAMPLERATE    
112         chip->awacs_reg[1] |= chip->rate_index    
113         snd_pmac_awacs_write_reg(chip, 1, chip    
114 }                                                 
115                                                   
116                                                   
117 /*                                                
118  * AWACS volume callbacks                         
119  */                                               
120 /*                                                
121  * volumes: 0-15 stereo                           
122  */                                               
123 static int snd_pmac_awacs_info_volume(struct s    
124                                       struct s    
125 {                                                 
126         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTE    
127         uinfo->count = 2;                         
128         uinfo->value.integer.min = 0;             
129         uinfo->value.integer.max = 15;            
130         return 0;                                 
131 }                                                 
132                                                   
133 static int snd_pmac_awacs_get_volume(struct sn    
134                                      struct sn    
135 {                                                 
136         struct snd_pmac *chip = snd_kcontrol_c    
137         int reg = kcontrol->private_value & 0x    
138         int lshift = (kcontrol->private_value     
139         int inverted = (kcontrol->private_valu    
140         unsigned long flags;                      
141         int vol[2];                               
142                                                   
143         spin_lock_irqsave(&chip->reg_lock, fla    
144         vol[0] = (chip->awacs_reg[reg] >> lshi    
145         vol[1] = chip->awacs_reg[reg] & 0xf;      
146         spin_unlock_irqrestore(&chip->reg_lock    
147         if (inverted) {                           
148                 vol[0] = 0x0f - vol[0];           
149                 vol[1] = 0x0f - vol[1];           
150         }                                         
151         ucontrol->value.integer.value[0] = vol    
152         ucontrol->value.integer.value[1] = vol    
153         return 0;                                 
154 }                                                 
155                                                   
156 static int snd_pmac_awacs_put_volume(struct sn    
157                                      struct sn    
158 {                                                 
159         struct snd_pmac *chip = snd_kcontrol_c    
160         int reg = kcontrol->private_value & 0x    
161         int lshift = (kcontrol->private_value     
162         int inverted = (kcontrol->private_valu    
163         int val, oldval;                          
164         unsigned long flags;                      
165         unsigned int vol[2];                      
166                                                   
167         vol[0] = ucontrol->value.integer.value    
168         vol[1] = ucontrol->value.integer.value    
169         if (vol[0] > 0x0f || vol[1] > 0x0f)       
170                 return -EINVAL;                   
171         if (inverted) {                           
172                 vol[0] = 0x0f - vol[0];           
173                 vol[1] = 0x0f - vol[1];           
174         }                                         
175         vol[0] &= 0x0f;                           
176         vol[1] &= 0x0f;                           
177         spin_lock_irqsave(&chip->reg_lock, fla    
178         oldval = chip->awacs_reg[reg];            
179         val = oldval & ~(0xf | (0xf << lshift)    
180         val |= vol[0] << lshift;                  
181         val |= vol[1];                            
182         if (oldval != val)                        
183                 snd_pmac_awacs_write_reg(chip,    
184         spin_unlock_irqrestore(&chip->reg_lock    
185         return oldval != reg;                     
186 }                                                 
187                                                   
188                                                   
189 #define AWACS_VOLUME(xname, xreg, xshift, xinv    
190 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name =    
191   .info = snd_pmac_awacs_info_volume, \           
192   .get = snd_pmac_awacs_get_volume, \             
193   .put = snd_pmac_awacs_put_volume, \             
194   .private_value = (xreg) | ((xshift) << 8) |     
195                                                   
196 /*                                                
197  * mute master/ogain for AWACS: mono              
198  */                                               
199 static int snd_pmac_awacs_get_switch(struct sn    
200                                      struct sn    
201 {                                                 
202         struct snd_pmac *chip = snd_kcontrol_c    
203         int reg = kcontrol->private_value & 0x    
204         int shift = (kcontrol->private_value >    
205         int invert = (kcontrol->private_value     
206         int val;                                  
207         unsigned long flags;                      
208                                                   
209         spin_lock_irqsave(&chip->reg_lock, fla    
210         val = (chip->awacs_reg[reg] >> shift)     
211         spin_unlock_irqrestore(&chip->reg_lock    
212         if (invert)                               
213                 val = 1 - val;                    
214         ucontrol->value.integer.value[0] = val    
215         return 0;                                 
216 }                                                 
217                                                   
218 static int snd_pmac_awacs_put_switch(struct sn    
219                                      struct sn    
220 {                                                 
221         struct snd_pmac *chip = snd_kcontrol_c    
222         int reg = kcontrol->private_value & 0x    
223         int shift = (kcontrol->private_value >    
224         int invert = (kcontrol->private_value     
225         int mask = 1 << shift;                    
226         int val, changed;                         
227         unsigned long flags;                      
228                                                   
229         spin_lock_irqsave(&chip->reg_lock, fla    
230         val = chip->awacs_reg[reg] & ~mask;       
231         if (ucontrol->value.integer.value[0] !    
232                 val |= mask;                      
233         changed = chip->awacs_reg[reg] != val;    
234         if (changed)                              
235                 snd_pmac_awacs_write_reg(chip,    
236         spin_unlock_irqrestore(&chip->reg_lock    
237         return changed;                           
238 }                                                 
239                                                   
240 #define AWACS_SWITCH(xname, xreg, xshift, xinv    
241 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name =    
242   .info = snd_pmac_boolean_mono_info, \           
243   .get = snd_pmac_awacs_get_switch, \             
244   .put = snd_pmac_awacs_put_switch, \             
245   .private_value = (xreg) | ((xshift) << 8) |     
246                                                   
247                                                   
248 #ifdef PMAC_AMP_AVAIL                             
249 /*                                                
250  * controls for perch/whisper extension cards,    
251  *                                                
252  * TDA7433 connected via i2c address 0x45 (= 0    
253  * accessed through cuda                          
254  */                                               
255 static void awacs_set_cuda(int reg, int val)      
256 {                                                 
257         struct adb_request req;                   
258         cuda_request(&req, NULL, 5, CUDA_PACKE    
259                         reg, val);                
260         while (! req.complete)                    
261                 cuda_poll();                      
262 }                                                 
263                                                   
264 /*                                                
265  * level = 0 - 14, 7 = 0 dB                       
266  */                                               
267 static void awacs_amp_set_tone(struct awacs_am    
268 {                                                 
269         amp->amp_tone[0] = bass;                  
270         amp->amp_tone[1] = treble;                
271         if (bass > 7)                             
272                 bass = (14 - bass) + 8;           
273         if (treble > 7)                           
274                 treble = (14 - treble) + 8;       
275         awacs_set_cuda(2, (bass << 4) | treble    
276 }                                                 
277                                                   
278 /*                                                
279  * vol = 0 - 31 (attenuation), 32 = mute bit,     
280  */                                               
281 static int awacs_amp_set_vol(struct awacs_amp     
282                              int lvol, int rvo    
283 {                                                 
284         if (do_check && amp->amp_vol[index][0]    
285                         amp->amp_vol[index][1]    
286                 return 0;                         
287         awacs_set_cuda(3 + index, lvol);          
288         awacs_set_cuda(5 + index, rvol);          
289         amp->amp_vol[index][0] = lvol;            
290         amp->amp_vol[index][1] = rvol;            
291         return 1;                                 
292 }                                                 
293                                                   
294 /*                                                
295  * 0 = -79 dB, 79 = 0 dB, 99 = +20 dB             
296  */                                               
297 static void awacs_amp_set_master(struct awacs_    
298 {                                                 
299         amp->amp_master = vol;                    
300         if (vol <= 79)                            
301                 vol = 32 + (79 - vol);            
302         else                                      
303                 vol = 32 - (vol - 79);            
304         awacs_set_cuda(1, vol);                   
305 }                                                 
306                                                   
307 static void awacs_amp_free(struct snd_pmac *ch    
308 {                                                 
309         struct awacs_amp *amp = chip->mixer_da    
310         if (!amp)                                 
311                 return;                           
312         kfree(amp);                               
313         chip->mixer_data = NULL;                  
314         chip->mixer_free = NULL;                  
315 }                                                 
316                                                   
317                                                   
318 /*                                                
319  * mixer controls                                 
320  */                                               
321 static int snd_pmac_awacs_info_volume_amp(stru    
322                                           stru    
323 {                                                 
324         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTE    
325         uinfo->count = 2;                         
326         uinfo->value.integer.min = 0;             
327         uinfo->value.integer.max = 31;            
328         return 0;                                 
329 }                                                 
330                                                   
331 static int snd_pmac_awacs_get_volume_amp(struc    
332                                          struc    
333 {                                                 
334         struct snd_pmac *chip = snd_kcontrol_c    
335         int index = kcontrol->private_value;      
336         struct awacs_amp *amp = chip->mixer_da    
337                                                   
338         ucontrol->value.integer.value[0] = 31     
339         ucontrol->value.integer.value[1] = 31     
340         return 0;                                 
341 }                                                 
342                                                   
343 static int snd_pmac_awacs_put_volume_amp(struc    
344                                          struc    
345 {                                                 
346         struct snd_pmac *chip = snd_kcontrol_c    
347         int index = kcontrol->private_value;      
348         int vol[2];                               
349         struct awacs_amp *amp = chip->mixer_da    
350                                                   
351         vol[0] = (31 - (ucontrol->value.intege    
352                 | (amp->amp_vol[index][0] & 32    
353         vol[1] = (31 - (ucontrol->value.intege    
354                 | (amp->amp_vol[index][1] & 32    
355         return awacs_amp_set_vol(amp, index, v    
356 }                                                 
357                                                   
358 static int snd_pmac_awacs_get_switch_amp(struc    
359                                          struc    
360 {                                                 
361         struct snd_pmac *chip = snd_kcontrol_c    
362         int index = kcontrol->private_value;      
363         struct awacs_amp *amp = chip->mixer_da    
364                                                   
365         ucontrol->value.integer.value[0] = (am    
366                                         ? 0 :     
367         ucontrol->value.integer.value[1] = (am    
368                                         ? 0 :     
369         return 0;                                 
370 }                                                 
371                                                   
372 static int snd_pmac_awacs_put_switch_amp(struc    
373                                          struc    
374 {                                                 
375         struct snd_pmac *chip = snd_kcontrol_c    
376         int index = kcontrol->private_value;      
377         int vol[2];                               
378         struct awacs_amp *amp = chip->mixer_da    
379                                                   
380         vol[0] = (ucontrol->value.integer.valu    
381                 | (amp->amp_vol[index][0] & 31    
382         vol[1] = (ucontrol->value.integer.valu    
383                 | (amp->amp_vol[index][1] & 31    
384         return awacs_amp_set_vol(amp, index, v    
385 }                                                 
386                                                   
387 static int snd_pmac_awacs_info_tone_amp(struct    
388                                         struct    
389 {                                                 
390         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTE    
391         uinfo->count = 1;                         
392         uinfo->value.integer.min = 0;             
393         uinfo->value.integer.max = 14;            
394         return 0;                                 
395 }                                                 
396                                                   
397 static int snd_pmac_awacs_get_tone_amp(struct     
398                                        struct     
399 {                                                 
400         struct snd_pmac *chip = snd_kcontrol_c    
401         int index = kcontrol->private_value;      
402         struct awacs_amp *amp = chip->mixer_da    
403                                                   
404         ucontrol->value.integer.value[0] = amp    
405         return 0;                                 
406 }                                                 
407                                                   
408 static int snd_pmac_awacs_put_tone_amp(struct     
409                                        struct     
410 {                                                 
411         struct snd_pmac *chip = snd_kcontrol_c    
412         int index = kcontrol->private_value;      
413         struct awacs_amp *amp = chip->mixer_da    
414         unsigned int val;                         
415                                                   
416         val = ucontrol->value.integer.value[0]    
417         if (val > 14)                             
418                 return -EINVAL;                   
419         if (val != amp->amp_tone[index]) {        
420                 amp->amp_tone[index] = val;       
421                 awacs_amp_set_tone(amp, amp->a    
422                 return 1;                         
423         }                                         
424         return 0;                                 
425 }                                                 
426                                                   
427 static int snd_pmac_awacs_info_master_amp(stru    
428                                           stru    
429 {                                                 
430         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTE    
431         uinfo->count = 1;                         
432         uinfo->value.integer.min = 0;             
433         uinfo->value.integer.max = 99;            
434         return 0;                                 
435 }                                                 
436                                                   
437 static int snd_pmac_awacs_get_master_amp(struc    
438                                          struc    
439 {                                                 
440         struct snd_pmac *chip = snd_kcontrol_c    
441         struct awacs_amp *amp = chip->mixer_da    
442                                                   
443         ucontrol->value.integer.value[0] = amp    
444         return 0;                                 
445 }                                                 
446                                                   
447 static int snd_pmac_awacs_put_master_amp(struc    
448                                          struc    
449 {                                                 
450         struct snd_pmac *chip = snd_kcontrol_c    
451         struct awacs_amp *amp = chip->mixer_da    
452         unsigned int val;                         
453                                                   
454         val = ucontrol->value.integer.value[0]    
455         if (val > 99)                             
456                 return -EINVAL;                   
457         if (val != amp->amp_master) {             
458                 amp->amp_master = val;            
459                 awacs_amp_set_master(amp, amp-    
460                 return 1;                         
461         }                                         
462         return 0;                                 
463 }                                                 
464                                                   
465 #define AMP_CH_SPK      0                         
466 #define AMP_CH_HD       1                         
467                                                   
468 static const struct snd_kcontrol_new snd_pmac_    
469         { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,    
470           .name = "Speaker Playback Volume",      
471           .info = snd_pmac_awacs_info_volume_a    
472           .get = snd_pmac_awacs_get_volume_amp    
473           .put = snd_pmac_awacs_put_volume_amp    
474           .private_value = AMP_CH_SPK,            
475         },                                        
476         { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,    
477           .name = "Headphone Playback Volume",    
478           .info = snd_pmac_awacs_info_volume_a    
479           .get = snd_pmac_awacs_get_volume_amp    
480           .put = snd_pmac_awacs_put_volume_amp    
481           .private_value = AMP_CH_HD,             
482         },                                        
483         { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,    
484           .name = "Tone Control - Bass",          
485           .info = snd_pmac_awacs_info_tone_amp    
486           .get = snd_pmac_awacs_get_tone_amp,     
487           .put = snd_pmac_awacs_put_tone_amp,     
488           .private_value = 0,                     
489         },                                        
490         { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,    
491           .name = "Tone Control - Treble",        
492           .info = snd_pmac_awacs_info_tone_amp    
493           .get = snd_pmac_awacs_get_tone_amp,     
494           .put = snd_pmac_awacs_put_tone_amp,     
495           .private_value = 1,                     
496         },                                        
497         { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,    
498           .name = "Amp Master Playback Volume"    
499           .info = snd_pmac_awacs_info_master_a    
500           .get = snd_pmac_awacs_get_master_amp    
501           .put = snd_pmac_awacs_put_master_amp    
502         },                                        
503 };                                                
504                                                   
505 static const struct snd_kcontrol_new snd_pmac_    
506         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,      
507         .name = "Headphone Playback Switch",      
508         .info = snd_pmac_boolean_stereo_info,     
509         .get = snd_pmac_awacs_get_switch_amp,     
510         .put = snd_pmac_awacs_put_switch_amp,     
511         .private_value = AMP_CH_HD,               
512 };                                                
513                                                   
514 static const struct snd_kcontrol_new snd_pmac_    
515         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,      
516         .name = "Speaker Playback Switch",        
517         .info = snd_pmac_boolean_stereo_info,     
518         .get = snd_pmac_awacs_get_switch_amp,     
519         .put = snd_pmac_awacs_put_switch_amp,     
520         .private_value = AMP_CH_SPK,              
521 };                                                
522                                                   
523 #endif /* PMAC_AMP_AVAIL */                       
524                                                   
525                                                   
526 /*                                                
527  * mic boost for screamer                         
528  */                                               
529 static int snd_pmac_screamer_mic_boost_info(st    
530                                             st    
531 {                                                 
532         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTE    
533         uinfo->count = 1;                         
534         uinfo->value.integer.min = 0;             
535         uinfo->value.integer.max = 3;             
536         return 0;                                 
537 }                                                 
538                                                   
539 static int snd_pmac_screamer_mic_boost_get(str    
540                                            str    
541 {                                                 
542         struct snd_pmac *chip = snd_kcontrol_c    
543         int val = 0;                              
544         unsigned long flags;                      
545                                                   
546         spin_lock_irqsave(&chip->reg_lock, fla    
547         if (chip->awacs_reg[6] & MASK_MIC_BOOS    
548                 val |= 2;                         
549         if (chip->awacs_reg[0] & MASK_GAINLINE    
550                 val |= 1;                         
551         spin_unlock_irqrestore(&chip->reg_lock    
552         ucontrol->value.integer.value[0] = val    
553         return 0;                                 
554 }                                                 
555                                                   
556 static int snd_pmac_screamer_mic_boost_put(str    
557                                            str    
558 {                                                 
559         struct snd_pmac *chip = snd_kcontrol_c    
560         int changed = 0;                          
561         int val0, val6;                           
562         unsigned long flags;                      
563                                                   
564         spin_lock_irqsave(&chip->reg_lock, fla    
565         val0 = chip->awacs_reg[0] & ~MASK_GAIN    
566         val6 = chip->awacs_reg[6] & ~MASK_MIC_    
567         if (ucontrol->value.integer.value[0] &    
568                 val0 |= MASK_GAINLINE;            
569         if (ucontrol->value.integer.value[0] &    
570                 val6 |= MASK_MIC_BOOST;           
571         if (val0 != chip->awacs_reg[0]) {         
572                 snd_pmac_awacs_write_reg(chip,    
573                 changed = 1;                      
574         }                                         
575         if (val6 != chip->awacs_reg[6]) {         
576                 snd_pmac_awacs_write_reg(chip,    
577                 changed = 1;                      
578         }                                         
579         spin_unlock_irqrestore(&chip->reg_lock    
580         return changed;                           
581 }                                                 
582                                                   
583 /*                                                
584  * lists of mixer elements                        
585  */                                               
586 static const struct snd_kcontrol_new snd_pmac_    
587         AWACS_SWITCH("Master Capture Switch",     
588         AWACS_VOLUME("Master Capture Volume",     
589 /*      AWACS_SWITCH("Unknown Playback Switch"    
590 };                                                
591                                                   
592 static const struct snd_kcontrol_new snd_pmac_    
593         AWACS_VOLUME("Master Playback Volume",    
594         AWACS_VOLUME("Play-through Playback Vo    
595         AWACS_SWITCH("Line Capture Switch", 0,    
596         AWACS_SWITCH("CD Capture Switch", 0, S    
597 };                                                
598                                                   
599 static const struct snd_kcontrol_new snd_pmac_    
600         AWACS_VOLUME("Line out Playback Volume    
601 };                                                
602                                                   
603 static const struct snd_kcontrol_new snd_pmac_    
604         AWACS_VOLUME("Play-through Playback Vo    
605         AWACS_SWITCH("CD Capture Switch", 0, S    
606 };                                                
607                                                   
608 static const struct snd_kcontrol_new snd_pmac_    
609         AWACS_VOLUME("Line out Playback Volume    
610         AWACS_VOLUME("Master Playback Volume",    
611         AWACS_SWITCH("CD Capture Switch", 0, S    
612         AWACS_SWITCH("Line Capture Switch", 0,    
613 };                                                
614                                                   
615 static const struct snd_kcontrol_new snd_pmac_    
616         AWACS_VOLUME("Line out Playback Volume    
617         AWACS_SWITCH("CD Capture Switch", 0, S    
618         AWACS_SWITCH("Line Capture Switch", 0,    
619 };                                                
620                                                   
621 static const struct snd_kcontrol_new snd_pmac_    
622         AWACS_VOLUME("Headphone Playback Volum    
623 };                                                
624                                                   
625 static const struct snd_kcontrol_new snd_pmac_    
626         AWACS_VOLUME("Master Playback Volume",    
627         AWACS_SWITCH("CD Capture Switch", 0, S    
628 };                                                
629                                                   
630 /* FIXME: is this correct order?                  
631  * screamer (powerbook G3 pismo) seems to have    
632  */                                               
633 static const struct snd_kcontrol_new snd_pmac_    
634         AWACS_SWITCH("Line Capture Switch", 0,    
635         AWACS_SWITCH("Mic Capture Switch", 0,     
636 };                                                
637                                                   
638 static const struct snd_kcontrol_new snd_pmac_    
639         AWACS_SWITCH("Line Capture Switch", 0,    
640         AWACS_SWITCH("Mic Capture Switch", 0,     
641 };                                                
642                                                   
643 static const struct snd_kcontrol_new snd_pmac_    
644         AWACS_SWITCH("CD Capture Switch", 0, S    
645 };                                                
646                                                   
647 static const struct snd_kcontrol_new snd_pmac_    
648 AWACS_SWITCH("Master Playback Switch", 1, SHIF    
649                                                   
650 static const struct snd_kcontrol_new snd_pmac_    
651 AWACS_SWITCH("Line out Playback Switch", 1, SH    
652                                                   
653 static const struct snd_kcontrol_new snd_pmac_    
654 AWACS_SWITCH("Headphone Playback Switch", 1, S    
655                                                   
656 static const struct snd_kcontrol_new snd_pmac_    
657         AWACS_SWITCH("Mic Boost Capture Switch    
658 };                                                
659                                                   
660 static const struct snd_kcontrol_new snd_pmac_    
661         { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,    
662           .name = "Mic Boost Capture Volume",     
663           .info = snd_pmac_screamer_mic_boost_    
664           .get = snd_pmac_screamer_mic_boost_g    
665           .put = snd_pmac_screamer_mic_boost_p    
666         },                                        
667 };                                                
668                                                   
669 static const struct snd_kcontrol_new snd_pmac_    
670 {                                                 
671         AWACS_SWITCH("Line Boost Capture Switc    
672 };                                                
673                                                   
674 static const struct snd_kcontrol_new snd_pmac_    
675 {                                                 
676         AWACS_SWITCH("Line Boost Capture Switc    
677         AWACS_SWITCH("CD Boost Capture Switch"    
678 };                                                
679                                                   
680 static const struct snd_kcontrol_new snd_pmac_    
681 {                                                 
682         AWACS_SWITCH("Line Boost Capture Switc    
683         AWACS_SWITCH("Mic Boost Capture Switch    
684 };                                                
685                                                   
686 static const struct snd_kcontrol_new snd_pmac_    
687         AWACS_VOLUME("Speaker Playback Volume"    
688 };                                                
689                                                   
690 static const struct snd_kcontrol_new snd_pmac_    
691 AWACS_SWITCH("Speaker Playback Switch", 1, SHI    
692                                                   
693 static const struct snd_kcontrol_new snd_pmac_    
694 AWACS_SWITCH("Speaker Playback Switch", 1, SHI    
695                                                   
696 static const struct snd_kcontrol_new snd_pmac_    
697 AWACS_SWITCH("Speaker Playback Switch", 1, SHI    
698                                                   
699                                                   
700 /*                                                
701  * add new mixer elements to the card             
702  */                                               
703 static int build_mixers(struct snd_pmac *chip,    
704                         const struct snd_kcont    
705 {                                                 
706         int i, err;                               
707                                                   
708         for (i = 0; i < nums; i++) {              
709                 err = snd_ctl_add(chip->card,     
710                 if (err < 0)                      
711                         return err;               
712         }                                         
713         return 0;                                 
714 }                                                 
715                                                   
716                                                   
717 /*                                                
718  * restore all registers                          
719  */                                               
720 static void awacs_restore_all_regs(struct snd_    
721 {                                                 
722         snd_pmac_awacs_write_noreg(chip, 0, ch    
723         snd_pmac_awacs_write_noreg(chip, 1, ch    
724         snd_pmac_awacs_write_noreg(chip, 2, ch    
725         snd_pmac_awacs_write_noreg(chip, 4, ch    
726         if (chip->model == PMAC_SCREAMER) {       
727                 snd_pmac_awacs_write_noreg(chi    
728                 snd_pmac_awacs_write_noreg(chi    
729                 snd_pmac_awacs_write_noreg(chi    
730         }                                         
731 }                                                 
732                                                   
733 #ifdef CONFIG_PM                                  
734 static void snd_pmac_awacs_suspend(struct snd_    
735 {                                                 
736         snd_pmac_awacs_write_noreg(chip, 1, (c    
737                                              |    
738 }                                                 
739                                                   
740 static void snd_pmac_awacs_resume(struct snd_p    
741 {                                                 
742         if (of_machine_is_compatible("PowerBoo    
743             || of_machine_is_compatible("Power    
744                 msleep(100);                      
745                 snd_pmac_awacs_write_reg(chip,    
746                         chip->awacs_reg[1] & ~    
747                 msleep(300);                      
748         }                                         
749                                                   
750         awacs_restore_all_regs(chip);             
751         if (chip->model == PMAC_SCREAMER) {       
752                 /* reset power bits in reg 6 *    
753                 mdelay(5);                        
754                 snd_pmac_awacs_write_noreg(chi    
755         }                                         
756         screamer_recalibrate(chip);               
757 #ifdef PMAC_AMP_AVAIL                             
758         if (chip->mixer_data) {                   
759                 struct awacs_amp *amp = chip->    
760                 awacs_amp_set_vol(amp, 0,         
761                                   amp->amp_vol    
762                 awacs_amp_set_vol(amp, 1,         
763                                   amp->amp_vol    
764                 awacs_amp_set_tone(amp, amp->a    
765                 awacs_amp_set_master(amp, amp-    
766         }                                         
767 #endif                                            
768 }                                                 
769 #endif /* CONFIG_PM */                            
770                                                   
771 #define IS_PM7500 (of_machine_is_compatible("A    
772                 || of_machine_is_compatible("A    
773                 || of_machine_is_compatible("A    
774 #define IS_PM5500 (of_machine_is_compatible("A    
775 #define IS_BEIGE (of_machine_is_compatible("AA    
776 #define IS_IMAC1 (of_machine_is_compatible("Po    
777 #define IS_IMAC2 (of_machine_is_compatible("Po    
778                 || of_machine_is_compatible("P    
779 #define IS_G4AGP (of_machine_is_compatible("Po    
780 #define IS_LOMBARD (of_machine_is_compatible("    
781                                                   
782 static int imac1, imac2;                          
783                                                   
784 #ifdef PMAC_SUPPORT_AUTOMUTE                      
785 /*                                                
786  * auto-mute stuffs                               
787  */                                               
788 static int snd_pmac_awacs_detect_headphone(str    
789 {                                                 
790         return (in_le32(&chip->awacs->codec_st    
791 }                                                 
792                                                   
793 #ifdef PMAC_AMP_AVAIL                             
794 static int toggle_amp_mute(struct awacs_amp *a    
795 {                                                 
796         int vol[2];                               
797         vol[0] = amp->amp_vol[index][0] & 31;     
798         vol[1] = amp->amp_vol[index][1] & 31;     
799         if (mute) {                               
800                 vol[0] |= 32;                     
801                 vol[1] |= 32;                     
802         }                                         
803         return awacs_amp_set_vol(amp, index, v    
804 }                                                 
805 #endif                                            
806                                                   
807 static void snd_pmac_awacs_update_automute(str    
808 {                                                 
809         if (chip->auto_mute) {                    
810 #ifdef PMAC_AMP_AVAIL                             
811                 if (chip->mixer_data) {           
812                         struct awacs_amp *amp     
813                         int changed;              
814                         if (snd_pmac_awacs_det    
815                                 changed = togg    
816                                 changed |= tog    
817                         } else {                  
818                                 changed = togg    
819                                 changed |= tog    
820                         }                         
821                         if (do_notify && ! cha    
822                                 return;           
823                 } else                            
824 #endif                                            
825                 {                                 
826                         int reg = chip->awacs_    
827                                 | (MASK_HDMUTE    
828                         if (imac1) {              
829                                 reg &= ~MASK_S    
830                                 reg |= MASK_PA    
831                         } else if (imac2) {       
832                                 reg &= ~MASK_S    
833                                 reg &= ~MASK_P    
834                         }                         
835                         if (snd_pmac_awacs_det    
836                                 reg &= ~MASK_H    
837                         else if (imac1)           
838                                 reg &= ~MASK_P    
839                         else if (imac2)           
840                                 reg |= MASK_PA    
841                         else                      
842                                 reg &= ~MASK_S    
843                         if (do_notify && reg =    
844                                 return;           
845                         snd_pmac_awacs_write_r    
846                 }                                 
847                 if (do_notify) {                  
848                         snd_ctl_notify(chip->c    
849                                        &chip->    
850                         snd_ctl_notify(chip->c    
851                                        &chip->    
852                         snd_ctl_notify(chip->c    
853                                        &chip->    
854                 }                                 
855         }                                         
856 }                                                 
857 #endif /* PMAC_SUPPORT_AUTOMUTE */                
858                                                   
859                                                   
860 /*                                                
861  * initialize chip                                
862  */                                               
863 int                                               
864 snd_pmac_awacs_init(struct snd_pmac *chip)        
865 {                                                 
866         int pm7500 = IS_PM7500;                   
867         int pm5500 = IS_PM5500;                   
868         int beige = IS_BEIGE;                     
869         int g4agp = IS_G4AGP;                     
870         int lombard = IS_LOMBARD;                 
871         int imac;                                 
872         int err, vol;                             
873         struct snd_kcontrol *vmaster_sw, *vmas    
874         struct snd_kcontrol *master_vol, *spea    
875                                                   
876         imac1 = IS_IMAC1;                         
877         imac2 = IS_IMAC2;                         
878         imac = imac1 || imac2;                    
879         /* looks like MASK_GAINLINE triggers s    
880          * as start-up                            
881          */                                       
882         chip->awacs_reg[0] = MASK_MUX_CD | 0xf    
883         chip->awacs_reg[1] = MASK_CMUTE | MASK    
884         /* FIXME: Only machines with external     
885         if (chip->has_iic || chip->device_id =    
886             /* chip->_device_id == 0x8 || */      
887             chip->device_id == 0xb)               
888                 chip->awacs_reg[1] |= MASK_PAR    
889         /* get default volume from nvram */       
890         // vol = (~nvram_read_byte(0x1308) & 7    
891         // vol = ((pmac_xpram_read( 8 ) & 7 )     
892         vol = 0x0f; /* no, on alsa, muted as d    
893         vol = vol + (vol << 6);                   
894         chip->awacs_reg[2] = vol;                 
895         chip->awacs_reg[4] = vol;                 
896         if (chip->model == PMAC_SCREAMER) {       
897                 /* FIXME: screamer has loopthr    
898                 chip->awacs_reg[5] = vol;         
899                 /* FIXME: maybe should be vol     
900                 chip->awacs_reg[6] = MASK_MIC_    
901                 chip->awacs_reg[7] = 0;           
902         }                                         
903                                                   
904         awacs_restore_all_regs(chip);             
905         chip->manufacturer = (in_le32(&chip->a    
906         screamer_recalibrate(chip);               
907                                                   
908         chip->revision = (in_le32(&chip->awacs    
909 #ifdef PMAC_AMP_AVAIL                             
910         if (chip->revision == 3 && chip->has_i    
911                 struct awacs_amp *amp = kzallo    
912                 if (! amp)                        
913                         return -ENOMEM;           
914                 chip->mixer_data = amp;           
915                 chip->mixer_free = awacs_amp_f    
916                 /* mute and zero vol */           
917                 awacs_amp_set_vol(amp, 0, 63,     
918                 awacs_amp_set_vol(amp, 1, 63,     
919                 awacs_amp_set_tone(amp, 7, 7);    
920                 awacs_amp_set_master(amp, 79);    
921         }                                         
922 #endif /* PMAC_AMP_AVAIL */                       
923                                                   
924         if (chip->hp_stat_mask == 0) {            
925                 /* set headphone-jack detectio    
926                 switch (chip->model) {            
927                 case PMAC_AWACS:                  
928                         chip->hp_stat_mask = p    
929                                 : MASK_LOCONN;    
930                         break;                    
931                 case PMAC_SCREAMER:               
932                         switch (chip->device_i    
933                         case 0x08:                
934                         case 0x0B:                
935                                 chip->hp_stat_    
936                                         ? MASK    
937                                         MASK_H    
938                                         MASK_H    
939                                         : MASK    
940                                 break;            
941                         case 0x00:                
942                         case 0x05:                
943                                 chip->hp_stat_    
944                                 break;            
945                         default:                  
946                                 chip->hp_stat_    
947                                 break;            
948                         }                         
949                         break;                    
950                 default:                          
951                         snd_BUG();                
952                         break;                    
953                 }                                 
954         }                                         
955                                                   
956         /*                                        
957          * build mixers                           
958          */                                       
959         strcpy(chip->card->mixername, "PowerMa    
960                                                   
961         err = build_mixers(chip, ARRAY_SIZE(sn    
962                                 snd_pmac_awacs    
963         if (err < 0)                              
964                 return err;                       
965         if (beige || g4agp)                       
966                 ;                                 
967         else if (chip->model == PMAC_SCREAMER     
968                 err = build_mixers(chip, ARRAY    
969                                    snd_pmac_sc    
970         else if (!pm7500)                         
971                 err = build_mixers(chip, ARRAY    
972                                    snd_pmac_aw    
973         if (err < 0)                              
974                 return err;                       
975         if (pm5500) {                             
976                 err = build_mixers(chip,          
977                                    ARRAY_SIZE(    
978                                    snd_pmac_aw    
979                 if (err < 0)                      
980                         return err;               
981         }                                         
982         master_vol = NULL;                        
983         if (pm7500)                               
984                 err = build_mixers(chip,          
985                                    ARRAY_SIZE(    
986                                    snd_pmac_aw    
987         else if (pm5500)                          
988                 err = snd_ctl_add(chip->card,     
989                     (master_vol = snd_ctl_new1    
990                                                   
991         else if (beige)                           
992                 err = build_mixers(chip,          
993                                    ARRAY_SIZE(    
994                                    snd_pmac_sc    
995         else if (imac || lombard) {               
996                 err = snd_ctl_add(chip->card,     
997                     (master_vol = snd_ctl_new1    
998                                                   
999                 if (err < 0)                      
1000                         return err;              
1001                 err = build_mixers(chip,         
1002                                    ARRAY_SIZE    
1003                                    snd_pmac_s    
1004         } else if (g4agp)                        
1005                 err = build_mixers(chip,         
1006                                    ARRAY_SIZE    
1007                                    snd_pmac_s    
1008         else                                     
1009                 err = build_mixers(chip,         
1010                                    ARRAY_SIZE    
1011                                    snd_pmac_a    
1012         if (err < 0)                             
1013                 return err;                      
1014         chip->master_sw_ctl = snd_ctl_new1((p    
1015                         ? &snd_pmac_awacs_mas    
1016                         : pm5500                 
1017                         ? &snd_pmac_awacs_mas    
1018                         : &snd_pmac_awacs_mas    
1019         err = snd_ctl_add(chip->card, chip->m    
1020         if (err < 0)                             
1021                 return err;                      
1022 #ifdef PMAC_AMP_AVAIL                            
1023         if (chip->mixer_data) {                  
1024                 /* use amplifier.  the signal    
1025                  * to the amp.  the amp has i    
1026                  * volumes and mute switches,    
1027                  * screamer registers.           
1028                  * in this case, it seems the    
1029                  */                              
1030                 err = build_mixers(chip, ARRA    
1031                                         snd_p    
1032                 if (err < 0)                     
1033                         return err;              
1034                 /* overwrite */                  
1035                 chip->master_sw_ctl = snd_ctl    
1036                                                  
1037                 err = snd_ctl_add(chip->card,    
1038                 if (err < 0)                     
1039                         return err;              
1040                 chip->speaker_sw_ctl = snd_ct    
1041                                                  
1042                 err = snd_ctl_add(chip->card,    
1043                 if (err < 0)                     
1044                         return err;              
1045         } else                                   
1046 #endif /* PMAC_AMP_AVAIL */                      
1047         {                                        
1048                 /* route A = headphone, route    
1049                 err = snd_ctl_add(chip->card,    
1050                     (speaker_vol = snd_ctl_ne    
1051                                                  
1052                 if (err < 0)                     
1053                         return err;              
1054                 chip->speaker_sw_ctl = snd_ct    
1055                                 ? &snd_pmac_a    
1056                                 : imac2          
1057                                 ? &snd_pmac_a    
1058                                 : &snd_pmac_a    
1059                 err = snd_ctl_add(chip->card,    
1060                 if (err < 0)                     
1061                         return err;              
1062         }                                        
1063                                                  
1064         if (pm5500 || imac || lombard) {         
1065                 vmaster_sw = snd_ctl_make_vir    
1066                         "Master Playback Swit    
1067                 err = snd_ctl_add_follower_un    
1068                                                  
1069                 if (err < 0)                     
1070                         return err;              
1071                 err = snd_ctl_add_follower_un    
1072                                                  
1073                 if (err < 0)                     
1074                         return err;              
1075                 err = snd_ctl_add(chip->card,    
1076                 if (err < 0)                     
1077                         return err;              
1078                 vmaster_vol = snd_ctl_make_vi    
1079                         "Master Playback Volu    
1080                 err = snd_ctl_add_follower(vm    
1081                 if (err < 0)                     
1082                         return err;              
1083                 err = snd_ctl_add_follower(vm    
1084                 if (err < 0)                     
1085                         return err;              
1086                 err = snd_ctl_add(chip->card,    
1087                 if (err < 0)                     
1088                         return err;              
1089         }                                        
1090                                                  
1091         if (beige || g4agp)                      
1092                 err = build_mixers(chip,         
1093                                 ARRAY_SIZE(sn    
1094                                 snd_pmac_scre    
1095         else if (imac)                           
1096                 err = build_mixers(chip,         
1097                                 ARRAY_SIZE(sn    
1098                                 snd_pmac_scre    
1099         else if (chip->model == PMAC_SCREAMER    
1100                 err = build_mixers(chip,         
1101                                 ARRAY_SIZE(sn    
1102                                 snd_pmac_scre    
1103         else if (pm7500)                         
1104                 err = build_mixers(chip,         
1105                                 ARRAY_SIZE(sn    
1106                                 snd_pmac_awac    
1107         else                                     
1108                 err = build_mixers(chip, ARRA    
1109                                 snd_pmac_awac    
1110         if (err < 0)                             
1111                 return err;                      
1112                                                  
1113         /*                                       
1114          * set lowlevel callbacks                
1115          */                                      
1116         chip->set_format = snd_pmac_awacs_set    
1117 #ifdef CONFIG_PM                                 
1118         chip->suspend = snd_pmac_awacs_suspen    
1119         chip->resume = snd_pmac_awacs_resume;    
1120 #endif                                           
1121 #ifdef PMAC_SUPPORT_AUTOMUTE                     
1122         err = snd_pmac_add_automute(chip);       
1123         if (err < 0)                             
1124                 return err;                      
1125         chip->detect_headphone = snd_pmac_awa    
1126         chip->update_automute = snd_pmac_awac    
1127         snd_pmac_awacs_update_automute(chip,     
1128 #endif                                           
1129         if (chip->model == PMAC_SCREAMER) {      
1130                 snd_pmac_awacs_write_noreg(ch    
1131                 snd_pmac_awacs_write_noreg(ch    
1132         }                                        
1133                                                  
1134         return 0;                                
1135 }                                                
1136                                                  

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

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

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

sflogo.php