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 ]
  1 /*
  2  * Driver for the i2c/i2s based TA3004 sound chip used
  3  * on some Apple hardware. Also known as "snapper".
  4  *
  5  * Tobias Sargeant <tobias.sargeant@bigpond.com>
  6  * Based upon tas3001c.c by Christopher C. Chimelis <chris@debian.org>:
  7  *
  8  * Input support by Renzo Davoli <renzo@cs.unibo.it>
  9  *
 10  */
 11 
 12 #include <linux/module.h>
 13 #include <linux/slab.h>
 14 #include <linux/proc_fs.h>
 15 #include <linux/ioport.h>
 16 #include <linux/sysctl.h>
 17 #include <linux/types.h>
 18 #include <linux/i2c.h>
 19 #include <linux/init.h>
 20 #include <linux/soundcard.h>
 21 #include <linux/interrupt.h>
 22 #include <linux/workqueue.h>
 23 
 24 #include <asm/uaccess.h>
 25 #include <asm/errno.h>
 26 #include <asm/io.h>
 27 #include <asm/prom.h>
 28 
 29 #include "dmasound.h"
 30 #include "tas_common.h"
 31 #include "tas3004.h"
 32 
 33 #include "tas_ioctl.h"
 34 
 35 /* #define DEBUG_DRCE */
 36 
 37 #define TAS3004_BIQUAD_FILTER_COUNT  7
 38 #define TAS3004_BIQUAD_CHANNEL_COUNT 2
 39 
 40 #define VOL_DEFAULT     (100 * 4 / 5)
 41 #define INPUT_DEFAULT   (100 * 4 / 5)
 42 #define BASS_DEFAULT    (100 / 2)
 43 #define TREBLE_DEFAULT  (100 / 2)
 44 
 45 struct tas3004_data_t {
 46         struct tas_data_t super;
 47         int device_id;
 48         int output_id;
 49         int speaker_id;
 50         struct tas_drce_t drce_state;
 51 };
 52 
 53 #define MAKE_TIME(sec,usec) (((sec)<<12) + (50000+(usec/10)*(1<<12))/100000)
 54 
 55 #define MAKE_RATIO(i,f) (((i)<<8) + ((500+(f)*(1<<8))/1000))
 56 
 57 
 58 static const union tas_biquad_t tas3004_eq_unity = {
 59         .buf             = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 },
 60 };
 61 
 62 
 63 static const struct tas_drce_t tas3004_drce_min = {
 64         .enable         = 1,
 65         .above          = { .val = MAKE_RATIO(16,0), .expand = 0 },
 66         .below          = { .val = MAKE_RATIO(2,0), .expand = 0 },
 67         .threshold      = -0x59a0,
 68         .energy         = MAKE_TIME(0,  1700),
 69         .attack         = MAKE_TIME(0,  1700),
 70         .decay          = MAKE_TIME(0,  1700),
 71 };
 72 
 73 
 74 static const struct tas_drce_t tas3004_drce_max = {
 75         .enable         = 1,
 76         .above          = { .val = MAKE_RATIO(1,500), .expand = 1 },
 77         .below          = { .val = MAKE_RATIO(2,0), .expand = 1 },
 78         .threshold      = -0x0,
 79         .energy         = MAKE_TIME(2,400000),
 80         .attack         = MAKE_TIME(2,400000),
 81         .decay          = MAKE_TIME(2,400000),
 82 };
 83 
 84 
 85 static const unsigned short time_constants[]={
 86         MAKE_TIME(0,  1700),
 87         MAKE_TIME(0,  3500),
 88         MAKE_TIME(0,  6700),
 89         MAKE_TIME(0, 13000),
 90         MAKE_TIME(0, 26000),
 91         MAKE_TIME(0, 53000),
 92         MAKE_TIME(0,106000),
 93         MAKE_TIME(0,212000),
 94         MAKE_TIME(0,425000),
 95         MAKE_TIME(0,850000),
 96         MAKE_TIME(1,700000),
 97         MAKE_TIME(2,400000),
 98 };
 99 
100 static const unsigned short above_threshold_compression_ratio[]={
101         MAKE_RATIO( 1, 70),
102         MAKE_RATIO( 1,140),
103         MAKE_RATIO( 1,230),
104         MAKE_RATIO( 1,330),
105         MAKE_RATIO( 1,450),
106         MAKE_RATIO( 1,600),
107         MAKE_RATIO( 1,780),
108         MAKE_RATIO( 2,  0),
109         MAKE_RATIO( 2,290),
110         MAKE_RATIO( 2,670),
111         MAKE_RATIO( 3,200),
112         MAKE_RATIO( 4,  0),
113         MAKE_RATIO( 5,330),
114         MAKE_RATIO( 8,  0),
115         MAKE_RATIO(16,  0),
116 };
117 
118 static const unsigned short above_threshold_expansion_ratio[]={
119         MAKE_RATIO(1, 60),
120         MAKE_RATIO(1,130),
121         MAKE_RATIO(1,190),
122         MAKE_RATIO(1,250),
123         MAKE_RATIO(1,310),
124         MAKE_RATIO(1,380),
125         MAKE_RATIO(1,440),
126         MAKE_RATIO(1,500)
127 };
128 
129 static const unsigned short below_threshold_compression_ratio[]={
130         MAKE_RATIO(1, 70),
131         MAKE_RATIO(1,140),
132         MAKE_RATIO(1,230),
133         MAKE_RATIO(1,330),
134         MAKE_RATIO(1,450),
135         MAKE_RATIO(1,600),
136         MAKE_RATIO(1,780),
137         MAKE_RATIO(2,  0)
138 };
139 
140 static const unsigned short below_threshold_expansion_ratio[]={
141         MAKE_RATIO(1, 60),
142         MAKE_RATIO(1,130),
143         MAKE_RATIO(1,190),
144         MAKE_RATIO(1,250),
145         MAKE_RATIO(1,310),
146         MAKE_RATIO(1,380),
147         MAKE_RATIO(1,440),
148         MAKE_RATIO(1,500),
149         MAKE_RATIO(1,560),
150         MAKE_RATIO(1,630),
151         MAKE_RATIO(1,690),
152         MAKE_RATIO(1,750),
153         MAKE_RATIO(1,810),
154         MAKE_RATIO(1,880),
155         MAKE_RATIO(1,940),
156         MAKE_RATIO(2,  0)
157 };
158 
159 static inline int
160 search( unsigned short val,
161         const unsigned short *arr,
162         const int arrsize) {
163         /*
164          * This could be a binary search, but for small tables,
165          * a linear search is likely to be faster
166          */
167 
168         int i;
169 
170         for (i=0; i < arrsize; i++)
171                 if (arr[i] >= val)
172                         goto _1;
173         return arrsize-1;
174  _1:
175         if (i == 0)
176                 return 0;
177         return (arr[i]-val < val-arr[i-1]) ? i : i-1;
178 }
179 
180 #define SEARCH(a, b) search(a, b, ARRAY_SIZE(b))
181 
182 static inline int
183 time_index(unsigned short time)
184 {
185         return SEARCH(time, time_constants);
186 }
187 
188 
189 static inline int
190 above_threshold_compression_index(unsigned short ratio)
191 {
192         return SEARCH(ratio, above_threshold_compression_ratio);
193 }
194 
195 
196 static inline int
197 above_threshold_expansion_index(unsigned short ratio)
198 {
199         return SEARCH(ratio, above_threshold_expansion_ratio);
200 }
201 
202 
203 static inline int
204 below_threshold_compression_index(unsigned short ratio)
205 {
206         return SEARCH(ratio, below_threshold_compression_ratio);
207 }
208 
209 
210 static inline int
211 below_threshold_expansion_index(unsigned short ratio)
212 {
213         return SEARCH(ratio, below_threshold_expansion_ratio);
214 }
215 
216 static inline unsigned char db_to_regval(short db) {
217         int r=0;
218 
219         r=(db+0x59a0) / 0x60;
220 
221         if (r < 0x91) return 0x91;
222         if (r > 0xef) return 0xef;
223         return r;
224 }
225 
226 static inline short quantize_db(short db)
227 {
228         return db_to_regval(db) * 0x60 - 0x59a0;
229 }
230 
231 static inline int
232 register_width(enum tas3004_reg_t r)
233 {
234         switch(r) {
235         case TAS3004_REG_MCR:
236         case TAS3004_REG_TREBLE:
237         case TAS3004_REG_BASS:
238         case TAS3004_REG_ANALOG_CTRL:
239         case TAS3004_REG_TEST1:
240         case TAS3004_REG_TEST2:
241         case TAS3004_REG_MCR2:
242                 return 1;
243 
244         case TAS3004_REG_LEFT_LOUD_BIQUAD_GAIN:
245         case TAS3004_REG_RIGHT_LOUD_BIQUAD_GAIN:
246                 return 3;
247 
248         case TAS3004_REG_DRC:
249         case TAS3004_REG_VOLUME:
250                 return 6;
251 
252         case TAS3004_REG_LEFT_MIXER:
253         case TAS3004_REG_RIGHT_MIXER:
254                 return 9;
255 
256         case TAS3004_REG_TEST:
257                 return 10;
258 
259         case TAS3004_REG_LEFT_BIQUAD0:
260         case TAS3004_REG_LEFT_BIQUAD1:
261         case TAS3004_REG_LEFT_BIQUAD2:
262         case TAS3004_REG_LEFT_BIQUAD3:
263         case TAS3004_REG_LEFT_BIQUAD4:
264         case TAS3004_REG_LEFT_BIQUAD5:
265         case TAS3004_REG_LEFT_BIQUAD6:
266 
267         case TAS3004_REG_RIGHT_BIQUAD0:
268         case TAS3004_REG_RIGHT_BIQUAD1:
269         case TAS3004_REG_RIGHT_BIQUAD2:
270         case TAS3004_REG_RIGHT_BIQUAD3:
271         case TAS3004_REG_RIGHT_BIQUAD4:
272         case TAS3004_REG_RIGHT_BIQUAD5:
273         case TAS3004_REG_RIGHT_BIQUAD6:
274 
275         case TAS3004_REG_LEFT_LOUD_BIQUAD:
276         case TAS3004_REG_RIGHT_LOUD_BIQUAD:
277                 return 15;
278 
279         default:
280                 return 0;
281         }
282 }
283 
284 static int
285 tas3004_write_register( struct tas3004_data_t *self,
286                         enum tas3004_reg_t reg_num,
287                         char *data,
288                         uint write_mode)
289 {
290         if (reg_num==TAS3004_REG_MCR ||
291             reg_num==TAS3004_REG_BASS ||
292             reg_num==TAS3004_REG_TREBLE ||
293             reg_num==TAS3004_REG_ANALOG_CTRL) {
294                 return tas_write_byte_register(&self->super,
295                                                (uint)reg_num,
296                                                *data,
297                                                write_mode);
298         } else {
299                 return tas_write_register(&self->super,
300                                           (uint)reg_num,
301                                           register_width(reg_num),
302                                           data,
303                                           write_mode);
304         }
305 }
306 
307 static int
308 tas3004_sync_register(  struct tas3004_data_t *self,
309                         enum tas3004_reg_t reg_num)
310 {
311         if (reg_num==TAS3004_REG_MCR ||
312             reg_num==TAS3004_REG_BASS ||
313             reg_num==TAS3004_REG_TREBLE ||
314             reg_num==TAS3004_REG_ANALOG_CTRL) {
315                 return tas_sync_byte_register(&self->super,
316                                               (uint)reg_num,
317                                               register_width(reg_num));
318         } else {
319                 return tas_sync_register(&self->super,
320                                          (uint)reg_num,
321                                          register_width(reg_num));
322         }
323 }
324 
325 static int
326 tas3004_read_register(  struct tas3004_data_t *self,
327                         enum tas3004_reg_t reg_num,
328                         char *data,
329                         uint write_mode)
330 {
331         return tas_read_register(&self->super,
332                                  (uint)reg_num,
333                                  register_width(reg_num),
334                                  data);
335 }
336 
337 static inline int
338 tas3004_fast_load(struct tas3004_data_t *self, int fast)
339 {
340         if (fast)
341                 self->super.shadow[TAS3004_REG_MCR][0] |= 0x80;
342         else
343                 self->super.shadow[TAS3004_REG_MCR][0] &= 0x7f;
344         return tas3004_sync_register(self,TAS3004_REG_MCR);
345 }
346 
347 static uint
348 tas3004_supported_mixers(struct tas3004_data_t *self)
349 {
350         return SOUND_MASK_VOLUME |
351                 SOUND_MASK_PCM |
352                 SOUND_MASK_ALTPCM |
353                 SOUND_MASK_IMIX |
354                 SOUND_MASK_TREBLE |
355                 SOUND_MASK_BASS |
356                 SOUND_MASK_MIC |
357                 SOUND_MASK_LINE;
358 }
359 
360 static int
361 tas3004_mixer_is_stereo(struct tas3004_data_t *self, int mixer)
362 {
363         switch(mixer) {
364         case SOUND_MIXER_VOLUME:
365         case SOUND_MIXER_PCM:
366         case SOUND_MIXER_ALTPCM:
367         case SOUND_MIXER_IMIX:
368                 return 1;
369         default:
370                 return 0;
371         }
372 }
373 
374 static uint
375 tas3004_stereo_mixers(struct tas3004_data_t *self)
376 {
377         uint r = tas3004_supported_mixers(self);
378         uint i;
379         
380         for (i=1; i<SOUND_MIXER_NRDEVICES; i++)
381                 if (r&(1<<i) && !tas3004_mixer_is_stereo(self,i))
382                         r &= ~(1<<i);
383         return r;
384 }
385 
386 static int
387 tas3004_get_mixer_level(struct tas3004_data_t *self, int mixer, uint *level)
388 {
389         if (!self)
390                 return -1;
391 
392         *level = self->super.mixer[mixer];
393 
394         return 0;
395 }
396 
397 static int
398 tas3004_set_mixer_level(struct tas3004_data_t *self, int mixer, uint level)
399 {
400         int rc;
401         tas_shadow_t *shadow;
402         uint temp;
403         uint offset=0;
404 
405         if (!self)
406                 return -1;
407 
408         shadow = self->super.shadow;
409 
410         if (!tas3004_mixer_is_stereo(self,mixer))
411                 level = tas_mono_to_stereo(level);
412         switch(mixer) {
413         case SOUND_MIXER_VOLUME:
414                 temp = tas3004_gain.master[level&0xff];
415                 SET_4_20(shadow[TAS3004_REG_VOLUME], 0, temp);
416                 temp = tas3004_gain.master[(level>>8)&0xff];
417                 SET_4_20(shadow[TAS3004_REG_VOLUME], 3, temp);
418                 rc = tas3004_sync_register(self,TAS3004_REG_VOLUME);
419                 break;
420         case SOUND_MIXER_IMIX:
421                 offset += 3;
422         case SOUND_MIXER_ALTPCM:
423                 offset += 3;
424         case SOUND_MIXER_PCM:
425                 /*
426                  * Don't load these in fast mode. The documentation
427                  * says it can be done in either mode, but testing it
428                  * shows that fast mode produces ugly clicking.
429                 */
430                 /* tas3004_fast_load(self,1); */
431                 temp = tas3004_gain.mixer[level&0xff];
432                 SET_4_20(shadow[TAS3004_REG_LEFT_MIXER], offset, temp);
433                 temp = tas3004_gain.mixer[(level>>8)&0xff];
434                 SET_4_20(shadow[TAS3004_REG_RIGHT_MIXER], offset, temp);
435                 rc = tas3004_sync_register(self,TAS3004_REG_LEFT_MIXER);
436                 if (rc == 0)
437                         rc=tas3004_sync_register(self,TAS3004_REG_RIGHT_MIXER);
438                 /* tas3004_fast_load(self,0); */
439                 break;
440         case SOUND_MIXER_TREBLE:
441                 temp = tas3004_gain.treble[level&0xff];
442                 shadow[TAS3004_REG_TREBLE][0]=temp&0xff;
443                 rc = tas3004_sync_register(self,TAS3004_REG_TREBLE);
444                 break;
445         case SOUND_MIXER_BASS:
446                 temp = tas3004_gain.bass[level&0xff];
447                 shadow[TAS3004_REG_BASS][0]=temp&0xff;
448                 rc = tas3004_sync_register(self,TAS3004_REG_BASS);
449                 break;
450         case SOUND_MIXER_MIC:
451                 if ((level&0xff)>0) {
452                         software_input_volume = SW_INPUT_VOLUME_SCALE * (level&0xff);
453                         if (self->super.mixer[mixer] == 0) {
454                                 self->super.mixer[SOUND_MIXER_LINE] = 0;
455                                 shadow[TAS3004_REG_ANALOG_CTRL][0]=0xc2;
456                                 rc = tas3004_sync_register(self,TAS3004_REG_ANALOG_CTRL);
457                         } else rc=0;
458                 } else {
459                         self->super.mixer[SOUND_MIXER_LINE] = SW_INPUT_VOLUME_DEFAULT;
460                         software_input_volume = SW_INPUT_VOLUME_SCALE *
461                                 (self->super.mixer[SOUND_MIXER_LINE]&0xff);
462                         shadow[TAS3004_REG_ANALOG_CTRL][0]=0x00;
463                         rc = tas3004_sync_register(self,TAS3004_REG_ANALOG_CTRL);
464                 }
465                 break;
466         case SOUND_MIXER_LINE:
467                 if (self->super.mixer[SOUND_MIXER_MIC] == 0) {
468                         software_input_volume = SW_INPUT_VOLUME_SCALE * (level&0xff);
469                         rc=0;
470                 }
471                 break;
472         default:
473                 rc = -1;
474                 break;
475         }
476         if (rc < 0)
477                 return rc;
478         self->super.mixer[mixer] = level;
479         
480         return 0;
481 }
482 
483 static int
484 tas3004_leave_sleep(struct tas3004_data_t *self)
485 {
486         unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
487 
488         if (!self)
489                 return -1;
490 
491         /* Make sure something answers on the i2c bus */
492         if (tas3004_write_register(self, TAS3004_REG_MCR, &mcr,
493             WRITE_NORMAL | FORCE_WRITE) < 0)
494                 return -1;
495 
496         tas3004_fast_load(self, 1);
497 
498         (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD0);
499         (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD1);
500         (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD2);
501         (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD3);
502         (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD4);
503         (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD5);
504         (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD6);
505 
506         (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD0);
507         (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD1);
508         (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD2);
509         (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD3);
510         (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD4);
511         (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD5);
512         (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD6);
513 
514         tas3004_fast_load(self, 0);
515 
516         (void)tas3004_sync_register(self,TAS3004_REG_VOLUME);
517         (void)tas3004_sync_register(self,TAS3004_REG_LEFT_MIXER);
518         (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_MIXER);
519         (void)tas3004_sync_register(self,TAS3004_REG_TREBLE);
520         (void)tas3004_sync_register(self,TAS3004_REG_BASS);
521         (void)tas3004_sync_register(self,TAS3004_REG_ANALOG_CTRL);
522 
523         return 0;
524 }
525 
526 static int
527 tas3004_enter_sleep(struct tas3004_data_t *self)
528 {
529         if (!self)
530                 return -1; 
531         return 0;
532 }
533 
534 static int
535 tas3004_sync_biquad(    struct tas3004_data_t *self,
536                         u_int channel,
537                         u_int filter)
538 {
539         enum tas3004_reg_t reg;
540 
541         if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT ||
542             filter  >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL;
543 
544         reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter;
545 
546         return tas3004_sync_register(self,reg);
547 }
548 
549 static int
550 tas3004_write_biquad_shadow(    struct tas3004_data_t *self,
551                                 u_int channel,
552                                 u_int filter,
553                                 const union tas_biquad_t *biquad)
554 {
555         tas_shadow_t *shadow=self->super.shadow;
556         enum tas3004_reg_t reg;
557 
558         if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT ||
559             filter  >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL;
560 
561         reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter;
562 
563         SET_4_20(shadow[reg], 0,biquad->coeff.b0);
564         SET_4_20(shadow[reg], 3,biquad->coeff.b1);
565         SET_4_20(shadow[reg], 6,biquad->coeff.b2);
566         SET_4_20(shadow[reg], 9,biquad->coeff.a1);
567         SET_4_20(shadow[reg],12,biquad->coeff.a2);
568 
569         return 0;
570 }
571 
572 static int
573 tas3004_write_biquad(   struct tas3004_data_t *self,
574                         u_int channel,
575                         u_int filter,
576                         const union tas_biquad_t *biquad)
577 {
578         int rc;
579 
580         rc=tas3004_write_biquad_shadow(self, channel, filter, biquad);
581         if (rc < 0) return rc;
582 
583         return tas3004_sync_biquad(self, channel, filter);
584 }
585 
586 static int
587 tas3004_write_biquad_list(      struct tas3004_data_t *self,
588                                 u_int filter_count,
589                                 u_int flags,
590                                 struct tas_biquad_ctrl_t *biquads)
591 {
592         int i;
593         int rc;
594 
595         if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,1);
596 
597         for (i=0; i<filter_count; i++) {
598                 rc=tas3004_write_biquad(self,
599                                         biquads[i].channel,
600                                         biquads[i].filter,
601                                         &biquads[i].data);
602                 if (rc < 0) break;
603         }
604 
605         if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,0);
606 
607         return rc;
608 }
609 
610 static int
611 tas3004_read_biquad(    struct tas3004_data_t *self,
612                         u_int channel,
613                         u_int filter,
614                         union tas_biquad_t *biquad)
615 {
616         tas_shadow_t *shadow=self->super.shadow;
617         enum tas3004_reg_t reg;
618 
619         if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT ||
620             filter  >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL;
621 
622         reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter;
623 
624         biquad->coeff.b0=GET_4_20(shadow[reg], 0);
625         biquad->coeff.b1=GET_4_20(shadow[reg], 3);
626         biquad->coeff.b2=GET_4_20(shadow[reg], 6);
627         biquad->coeff.a1=GET_4_20(shadow[reg], 9);
628         biquad->coeff.a2=GET_4_20(shadow[reg],12);
629         
630         return 0;       
631 }
632 
633 static int
634 tas3004_eq_rw(  struct tas3004_data_t *self,
635                 u_int cmd,
636                 u_long arg)
637 {
638         void __user *argp = (void __user *)arg;
639         int rc;
640         struct tas_biquad_ctrl_t biquad;
641 
642         if (copy_from_user((void *)&biquad, argp, sizeof(struct tas_biquad_ctrl_t))) {
643                 return -EFAULT;
644         }
645 
646         if (cmd & SIOC_IN) {
647                 rc=tas3004_write_biquad(self, biquad.channel, biquad.filter, &biquad.data);
648                 if (rc != 0) return rc;
649         }
650 
651         if (cmd & SIOC_OUT) {
652                 rc=tas3004_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
653                 if (rc != 0) return rc;
654 
655                 if (copy_to_user(argp, &biquad, sizeof(struct tas_biquad_ctrl_t))) {
656                         return -EFAULT;
657                 }
658 
659         }
660         return 0;
661 }
662 
663 static int
664 tas3004_eq_list_rw(     struct tas3004_data_t *self,
665                         u_int cmd,
666                         u_long arg)
667 {
668         int rc = 0;
669         int filter_count;
670         int flags;
671         int i,j;
672         char sync_required[TAS3004_BIQUAD_CHANNEL_COUNT][TAS3004_BIQUAD_FILTER_COUNT];
673         struct tas_biquad_ctrl_t biquad;
674         struct tas_biquad_ctrl_list_t __user *argp = (void __user *)arg;
675 
676         memset(sync_required,0,sizeof(sync_required));
677 
678         if (copy_from_user(&filter_count, &argp->filter_count, sizeof(int)))
679                 return -EFAULT;
680 
681         if (copy_from_user(&flags, &argp->flags, sizeof(int)))
682                 return -EFAULT;
683 
684         if (cmd & SIOC_IN) {
685         }
686 
687         for (i=0; i < filter_count; i++) {
688                 if (copy_from_user(&biquad, &argp->biquads[i],
689                                    sizeof(struct tas_biquad_ctrl_t))) {
690                         return -EFAULT;
691                 }
692 
693                 if (cmd & SIOC_IN) {
694                         sync_required[biquad.channel][biquad.filter]=1;
695                         rc=tas3004_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data);
696                         if (rc != 0) return rc;
697                 }
698 
699                 if (cmd & SIOC_OUT) {
700                         rc=tas3004_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
701                         if (rc != 0) return rc;
702 
703                         if (copy_to_user(&argp->biquads[i], &biquad,
704                                          sizeof(struct tas_biquad_ctrl_t))) {
705                                 return -EFAULT;
706                         }
707                 }
708         }
709 
710         if (cmd & SIOC_IN) {
711                 /*
712                  * This is OK for the tas3004. For the
713                  * tas3001c, going into fast load mode causes
714                  * the treble and bass to be reset to 0dB, and
715                  * volume controls to be muted.
716                  */
717                 if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,1);
718                 for (i=0; i<TAS3004_BIQUAD_CHANNEL_COUNT; i++) {
719                         for (j=0; j<TAS3004_BIQUAD_FILTER_COUNT; j++) {
720                                 if (sync_required[i][j]) {
721                                         rc=tas3004_sync_biquad(self, i, j);
722                                         if (rc < 0) goto out;
723                                 }
724                         }
725                 }
726         out:
727                 if (flags & TAS_BIQUAD_FAST_LOAD)
728                         tas3004_fast_load(self,0);
729         }
730 
731         return rc;
732 }
733 
734 static int
735 tas3004_update_drce(    struct tas3004_data_t *self,
736                         int flags,
737                         struct tas_drce_t *drce)
738 {
739         tas_shadow_t *shadow;
740         int i;
741         shadow=self->super.shadow;
742 
743         if (flags & TAS_DRCE_ABOVE_RATIO) {
744                 self->drce_state.above.expand = drce->above.expand;
745                 if (drce->above.val == (1<<8)) {
746                         self->drce_state.above.val = 1<<8;
747                         shadow[TAS3004_REG_DRC][0] = 0x02;
748                                         
749                 } else if (drce->above.expand) {
750                         i=above_threshold_expansion_index(drce->above.val);
751                         self->drce_state.above.val=above_threshold_expansion_ratio[i];
752                         shadow[TAS3004_REG_DRC][0] = 0x0a + (i<<3);
753                 } else {
754                         i=above_threshold_compression_index(drce->above.val);
755                         self->drce_state.above.val=above_threshold_compression_ratio[i];
756                         shadow[TAS3004_REG_DRC][0] = 0x08 + (i<<3);
757                 }
758         }
759 
760         if (flags & TAS_DRCE_BELOW_RATIO) {
761                 self->drce_state.below.expand = drce->below.expand;
762                 if (drce->below.val == (1<<8)) {
763                         self->drce_state.below.val = 1<<8;
764                         shadow[TAS3004_REG_DRC][1] = 0x02;
765                                         
766                 } else if (drce->below.expand) {
767                         i=below_threshold_expansion_index(drce->below.val);
768                         self->drce_state.below.val=below_threshold_expansion_ratio[i];
769                         shadow[TAS3004_REG_DRC][1] = 0x08 + (i<<3);
770                 } else {
771                         i=below_threshold_compression_index(drce->below.val);
772                         self->drce_state.below.val=below_threshold_compression_ratio[i];
773                         shadow[TAS3004_REG_DRC][1] = 0x0a + (i<<3);
774                 }
775         }
776 
777         if (flags & TAS_DRCE_THRESHOLD) {
778                 self->drce_state.threshold=quantize_db(drce->threshold);
779                 shadow[TAS3004_REG_DRC][2] = db_to_regval(self->drce_state.threshold);
780         }
781 
782         if (flags & TAS_DRCE_ENERGY) {
783                 i=time_index(drce->energy);
784                 self->drce_state.energy=time_constants[i];
785                 shadow[TAS3004_REG_DRC][3] = 0x40 + (i<<4);
786         }
787 
788         if (flags & TAS_DRCE_ATTACK) {
789                 i=time_index(drce->attack);
790                 self->drce_state.attack=time_constants[i];
791                 shadow[TAS3004_REG_DRC][4] = 0x40 + (i<<4);
792         }
793 
794         if (flags & TAS_DRCE_DECAY) {
795                 i=time_index(drce->decay);
796                 self->drce_state.decay=time_constants[i];
797                 shadow[TAS3004_REG_DRC][5] = 0x40 + (i<<4);
798         }
799 
800         if (flags & TAS_DRCE_ENABLE) {
801                 self->drce_state.enable = drce->enable;
802         }
803 
804         if (!self->drce_state.enable) {
805                 shadow[TAS3004_REG_DRC][0] |= 0x01;
806         }
807 
808 #ifdef DEBUG_DRCE
809         printk("DRCE: set [ ENABLE:%x ABOVE:%x/%x BELOW:%x/%x THRESH:%x ENERGY:%x ATTACK:%x DECAY:%x\n",
810                self->drce_state.enable,
811                self->drce_state.above.expand,self->drce_state.above.val,
812                self->drce_state.below.expand,self->drce_state.below.val,
813                self->drce_state.threshold,
814                self->drce_state.energy,
815                self->drce_state.attack,
816                self->drce_state.decay);
817 
818         printk("DRCE: reg [ %02x %02x %02x %02x %02x %02x ]\n",
819                (unsigned char)shadow[TAS3004_REG_DRC][0],
820                (unsigned char)shadow[TAS3004_REG_DRC][1],
821                (unsigned char)shadow[TAS3004_REG_DRC][2],
822                (unsigned char)shadow[TAS3004_REG_DRC][3],
823                (unsigned char)shadow[TAS3004_REG_DRC][4],
824                (unsigned char)shadow[TAS3004_REG_DRC][5]);
825 #endif
826 
827         return tas3004_sync_register(self, TAS3004_REG_DRC);
828 }
829 
830 static int
831 tas3004_drce_rw(        struct tas3004_data_t *self,
832                         u_int cmd,
833                         u_long arg)
834 {
835         int rc;
836         struct tas_drce_ctrl_t drce_ctrl;
837         void __user *argp = (void __user *)arg;
838 
839         if (copy_from_user(&drce_ctrl, argp, sizeof(struct tas_drce_ctrl_t)))
840                 return -EFAULT;
841 
842 #ifdef DEBUG_DRCE
843         printk("DRCE: input [ FLAGS:%x ENABLE:%x ABOVE:%x/%x BELOW:%x/%x THRESH:%x ENERGY:%x ATTACK:%x DECAY:%x\n",
844                drce_ctrl.flags,
845                drce_ctrl.data.enable,
846                drce_ctrl.data.above.expand,drce_ctrl.data.above.val,
847                drce_ctrl.data.below.expand,drce_ctrl.data.below.val,
848                drce_ctrl.data.threshold,
849                drce_ctrl.data.energy,
850                drce_ctrl.data.attack,
851                drce_ctrl.data.decay);
852 #endif
853 
854         if (cmd & SIOC_IN) {
855                 rc = tas3004_update_drce(self, drce_ctrl.flags, &drce_ctrl.data);
856                 if (rc < 0) return rc;
857         }
858 
859         if (cmd & SIOC_OUT) {
860                 if (drce_ctrl.flags & TAS_DRCE_ENABLE)
861                         drce_ctrl.data.enable = self->drce_state.enable;
862                 if (drce_ctrl.flags & TAS_DRCE_ABOVE_RATIO)
863                         drce_ctrl.data.above = self->drce_state.above;
864                 if (drce_ctrl.flags & TAS_DRCE_BELOW_RATIO)
865                         drce_ctrl.data.below = self->drce_state.below;
866                 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD)
867                         drce_ctrl.data.threshold = self->drce_state.threshold;
868                 if (drce_ctrl.flags & TAS_DRCE_ENERGY)
869                         drce_ctrl.data.energy = self->drce_state.energy;
870                 if (drce_ctrl.flags & TAS_DRCE_ATTACK)
871                         drce_ctrl.data.attack = self->drce_state.attack;
872                 if (drce_ctrl.flags & TAS_DRCE_DECAY)
873                         drce_ctrl.data.decay = self->drce_state.decay;
874 
875                 if (copy_to_user(argp, &drce_ctrl,
876                                  sizeof(struct tas_drce_ctrl_t))) {
877                         return -EFAULT;
878                 }
879         }
880 
881         return 0;
882 }
883 
884 static void
885 tas3004_update_device_parameters(struct tas3004_data_t *self)
886 {
887         char data;
888         int i;
889 
890         if (!self) return;
891 
892         if (self->output_id == TAS_OUTPUT_HEADPHONES) {
893                 /* turn on allPass when headphones are plugged in */
894                 data = 0x02;
895         } else {
896                 data = 0x00;
897         }
898 
899         tas3004_write_register(self, TAS3004_REG_MCR2, &data, WRITE_NORMAL | FORCE_WRITE);
900 
901         for (i=0; tas3004_eq_prefs[i]; i++) {
902                 struct tas_eq_pref_t *eq = tas3004_eq_prefs[i];
903 
904                 if (eq->device_id == self->device_id &&
905                     (eq->output_id == 0 || eq->output_id == self->output_id) &&
906                     (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) {
907 
908                         tas3004_update_drce(self, TAS_DRCE_ALL, eq->drce);
909                         tas3004_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads);
910 
911                         break;
912                 }
913         }
914 }
915 
916 static void
917 tas3004_device_change_handler(void *self)
918 {
919         if (!self) return;
920 
921         tas3004_update_device_parameters((struct tas3004_data_t *)self);
922 }
923 
924 static struct work_struct device_change;
925 
926 static int
927 tas3004_output_device_change(   struct tas3004_data_t *self,
928                                 int device_id,
929                                 int output_id,
930                                 int speaker_id)
931 {
932         self->device_id=device_id;
933         self->output_id=output_id;
934         self->speaker_id=speaker_id;
935 
936         schedule_work(&device_change);
937 
938         return 0;
939 }
940 
941 static int
942 tas3004_device_ioctl(   struct tas3004_data_t *self,
943                         u_int cmd,
944                         u_long arg)
945 {
946         uint __user *argp = (void __user *)arg;
947         switch (cmd) {
948         case TAS_READ_EQ:
949         case TAS_WRITE_EQ:
950                 return tas3004_eq_rw(self, cmd, arg);
951 
952         case TAS_READ_EQ_LIST:
953         case TAS_WRITE_EQ_LIST:
954                 return tas3004_eq_list_rw(self, cmd, arg);
955 
956         case TAS_READ_EQ_FILTER_COUNT:
957                 put_user(TAS3004_BIQUAD_FILTER_COUNT, argp);
958                 return 0;
959 
960         case TAS_READ_EQ_CHANNEL_COUNT:
961                 put_user(TAS3004_BIQUAD_CHANNEL_COUNT, argp);
962                 return 0;
963 
964         case TAS_READ_DRCE:
965         case TAS_WRITE_DRCE:
966                 return tas3004_drce_rw(self, cmd, arg);
967 
968         case TAS_READ_DRCE_CAPS:
969                 put_user(TAS_DRCE_ENABLE         |
970                          TAS_DRCE_ABOVE_RATIO    |
971                          TAS_DRCE_BELOW_RATIO    |
972                          TAS_DRCE_THRESHOLD      |
973                          TAS_DRCE_ENERGY         |
974                          TAS_DRCE_ATTACK         |
975                          TAS_DRCE_DECAY,
976                          argp);
977                 return 0;
978 
979         case TAS_READ_DRCE_MIN:
980         case TAS_READ_DRCE_MAX: {
981                 struct tas_drce_ctrl_t drce_ctrl;
982                 const struct tas_drce_t *drce_copy;
983 
984                 if (copy_from_user(&drce_ctrl, argp,
985                                    sizeof(struct tas_drce_ctrl_t))) {
986                         return -EFAULT;
987                 }
988 
989                 if (cmd == TAS_READ_DRCE_MIN) {
990                         drce_copy=&tas3004_drce_min;
991                 } else {
992                         drce_copy=&tas3004_drce_max;
993                 }
994 
995                 if (drce_ctrl.flags & TAS_DRCE_ABOVE_RATIO) {
996                         drce_ctrl.data.above=drce_copy->above;
997                 }
998                 if (drce_ctrl.flags & TAS_DRCE_BELOW_RATIO) {
999                         drce_ctrl.data.below=drce_copy->below;
1000                 }
1001                 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) {
1002                         drce_ctrl.data.threshold=drce_copy->threshold;
1003                 }
1004                 if (drce_ctrl.flags & TAS_DRCE_ENERGY) {
1005                         drce_ctrl.data.energy=drce_copy->energy;
1006                 }
1007                 if (drce_ctrl.flags & TAS_DRCE_ATTACK) {
1008                         drce_ctrl.data.attack=drce_copy->attack;
1009                 }
1010                 if (drce_ctrl.flags & TAS_DRCE_DECAY) {
1011                         drce_ctrl.data.decay=drce_copy->decay;
1012                 }
1013 
1014                 if (copy_to_user(argp, &drce_ctrl,
1015                                  sizeof(struct tas_drce_ctrl_t))) {
1016                         return -EFAULT;
1017                 }
1018         }
1019         }
1020 
1021         return -EINVAL;
1022 }
1023 
1024 static int
1025 tas3004_init_mixer(struct tas3004_data_t *self)
1026 {
1027         unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
1028 
1029         /* Make sure something answers on the i2c bus */
1030         if (tas3004_write_register(self, TAS3004_REG_MCR, &mcr,
1031             WRITE_NORMAL | FORCE_WRITE) < 0)
1032                 return -1;
1033 
1034         tas3004_fast_load(self, 1);
1035 
1036         (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD0);
1037         (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD1);
1038         (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD2);
1039         (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD3);
1040         (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD4);
1041         (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD5);
1042         (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD6);
1043 
1044         (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD0);
1045         (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD1);
1046         (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD2);
1047         (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD3);
1048         (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD4);
1049         (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD5);
1050         (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD6);
1051 
1052         tas3004_sync_register(self, TAS3004_REG_DRC);
1053 
1054         tas3004_sync_register(self, TAS3004_REG_MCR2);
1055 
1056         tas3004_fast_load(self, 0);
1057 
1058         tas3004_set_mixer_level(self, SOUND_MIXER_VOLUME, VOL_DEFAULT<<8 | VOL_DEFAULT);
1059         tas3004_set_mixer_level(self, SOUND_MIXER_PCM, INPUT_DEFAULT<<8 | INPUT_DEFAULT);
1060         tas3004_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0);
1061         tas3004_set_mixer_level(self, SOUND_MIXER_IMIX, 0);
1062 
1063         tas3004_set_mixer_level(self, SOUND_MIXER_BASS, BASS_DEFAULT);
1064         tas3004_set_mixer_level(self, SOUND_MIXER_TREBLE, TREBLE_DEFAULT);
1065 
1066         tas3004_set_mixer_level(self, SOUND_MIXER_LINE,SW_INPUT_VOLUME_DEFAULT);
1067 
1068         return 0;
1069 }
1070 
1071 static int
1072 tas3004_uninit_mixer(struct tas3004_data_t *self)
1073 {
1074         tas3004_set_mixer_level(self, SOUND_MIXER_VOLUME, 0);
1075         tas3004_set_mixer_level(self, SOUND_MIXER_PCM, 0);
1076         tas3004_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0);
1077         tas3004_set_mixer_level(self, SOUND_MIXER_IMIX, 0);
1078 
1079         tas3004_set_mixer_level(self, SOUND_MIXER_BASS, 0);
1080         tas3004_set_mixer_level(self, SOUND_MIXER_TREBLE, 0);
1081 
1082         tas3004_set_mixer_level(self, SOUND_MIXER_LINE, 0);
1083 
1084         return 0;
1085 }
1086 
1087 static int
1088 tas3004_init(struct i2c_client *client)
1089 {
1090         struct tas3004_data_t *self;
1091         size_t sz = sizeof(*self) + (TAS3004_REG_MAX*sizeof(tas_shadow_t));
1092         char drce_init[] = { 0x69, 0x22, 0x9f, 0xb0, 0x60, 0xa0 };
1093         char mcr2 = 0;
1094         int i, j;
1095 
1096         self = kmalloc(sz, GFP_KERNEL);
1097         if (!self)
1098                 return -ENOMEM;
1099         memset(self, 0, sz);
1100 
1101         self->super.client = client;
1102         self->super.shadow = (tas_shadow_t *)(self+1);
1103         self->output_id = TAS_OUTPUT_HEADPHONES;
1104 
1105         dev_set_drvdata(&client->dev, self);
1106 
1107         for (i = 0; i < TAS3004_BIQUAD_CHANNEL_COUNT; i++)
1108                 for (j = 0; j<TAS3004_BIQUAD_FILTER_COUNT; j++)
1109                         tas3004_write_biquad_shadow(self, i, j,
1110                                         &tas3004_eq_unity);
1111 
1112         tas3004_write_register(self, TAS3004_REG_MCR2, &mcr2, WRITE_SHADOW);
1113         tas3004_write_register(self, TAS3004_REG_DRC, drce_init, WRITE_SHADOW);
1114 
1115         INIT_WORK(&device_change, tas3004_device_change_handler, self);
1116         return 0;
1117 }
1118 
1119 static void 
1120 tas3004_uninit(struct tas3004_data_t *self)
1121 {
1122         tas3004_uninit_mixer(self);
1123         kfree(self);
1124 }
1125 
1126 
1127 struct tas_driver_hooks_t tas3004_hooks = {
1128         .init                   = (tas_hook_init_t)tas3004_init,
1129         .post_init              = (tas_hook_post_init_t)tas3004_init_mixer,
1130         .uninit                 = (tas_hook_uninit_t)tas3004_uninit,
1131         .get_mixer_level        = (tas_hook_get_mixer_level_t)tas3004_get_mixer_level,
1132         .set_mixer_level        = (tas_hook_set_mixer_level_t)tas3004_set_mixer_level,
1133         .enter_sleep            = (tas_hook_enter_sleep_t)tas3004_enter_sleep,
1134         .leave_sleep            = (tas_hook_leave_sleep_t)tas3004_leave_sleep,
1135         .supported_mixers       = (tas_hook_supported_mixers_t)tas3004_supported_mixers,
1136         .mixer_is_stereo        = (tas_hook_mixer_is_stereo_t)tas3004_mixer_is_stereo,
1137         .stereo_mixers          = (tas_hook_stereo_mixers_t)tas3004_stereo_mixers,
1138         .output_device_change   = (tas_hook_output_device_change_t)tas3004_output_device_change,
1139         .device_ioctl           = (tas_hook_device_ioctl_t)tas3004_device_ioctl
1140 };
1141 
  This page was automatically generated by the LXR engine.