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  *   TODO:
  9  *   -----
 10  *   * Enable control over input line 2 (is this connected?)
 11  *   * Implement sleep support (at least mute everything and
 12  *   * set gains to minimum during sleep)
 13  *   * Look into some of Darwin's tweaks regarding the mute
 14  *   * lines (delays & different behaviour on some HW)
 15  *
 16  */
 17 
 18 #include <linux/module.h>
 19 #include <linux/slab.h>
 20 #include <linux/proc_fs.h>
 21 #include <linux/ioport.h>
 22 #include <linux/sysctl.h>
 23 #include <linux/types.h>
 24 #include <linux/i2c.h>
 25 #include <linux/init.h>
 26 #include <linux/soundcard.h>
 27 #include <linux/workqueue.h>
 28 #include <asm/uaccess.h>
 29 #include <asm/errno.h>
 30 #include <asm/io.h>
 31 #include <asm/prom.h>
 32 
 33 #include "dmasound.h"
 34 #include "tas_common.h"
 35 #include "tas3001c.h"
 36 
 37 #include "tas_ioctl.h"
 38 
 39 #define TAS3001C_BIQUAD_FILTER_COUNT  6
 40 #define TAS3001C_BIQUAD_CHANNEL_COUNT 2
 41 
 42 #define VOL_DEFAULT     (100 * 4 / 5)
 43 #define INPUT_DEFAULT   (100 * 4 / 5)
 44 #define BASS_DEFAULT    (100 / 2)
 45 #define TREBLE_DEFAULT  (100 / 2)
 46 
 47 struct tas3001c_data_t {
 48         struct tas_data_t super;
 49         int device_id;
 50         int output_id;
 51         int speaker_id;
 52         struct tas_drce_t drce_state;
 53 };
 54 
 55 
 56 static const union tas_biquad_t
 57 tas3001c_eq_unity={
 58         .buf = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 }
 59 };
 60 
 61 
 62 static inline unsigned char db_to_regval(short db) {
 63         int r=0;
 64 
 65         r=(db+0x59a0) / 0x60;
 66 
 67         if (r < 0x91) return 0x91;
 68         if (r > 0xef) return 0xef;
 69         return r;
 70 }
 71 
 72 static inline short quantize_db(short db) {
 73         return db_to_regval(db) * 0x60 - 0x59a0;
 74 }
 75 
 76 
 77 static inline int
 78 register_width(enum tas3001c_reg_t r)
 79 {
 80         switch(r) {
 81         case TAS3001C_REG_MCR:
 82         case TAS3001C_REG_TREBLE:
 83         case TAS3001C_REG_BASS:
 84                 return 1;
 85 
 86         case TAS3001C_REG_DRC:
 87                 return 2;
 88 
 89         case TAS3001C_REG_MIXER1:
 90         case TAS3001C_REG_MIXER2:
 91                 return 3;
 92 
 93         case TAS3001C_REG_VOLUME:
 94                 return 6;
 95 
 96         case TAS3001C_REG_LEFT_BIQUAD0:
 97         case TAS3001C_REG_LEFT_BIQUAD1:
 98         case TAS3001C_REG_LEFT_BIQUAD2:
 99         case TAS3001C_REG_LEFT_BIQUAD3:
100         case TAS3001C_REG_LEFT_BIQUAD4:
101         case TAS3001C_REG_LEFT_BIQUAD5:
102         case TAS3001C_REG_LEFT_BIQUAD6:
103 
104         case TAS3001C_REG_RIGHT_BIQUAD0:
105         case TAS3001C_REG_RIGHT_BIQUAD1:
106         case TAS3001C_REG_RIGHT_BIQUAD2:
107         case TAS3001C_REG_RIGHT_BIQUAD3:
108         case TAS3001C_REG_RIGHT_BIQUAD4:
109         case TAS3001C_REG_RIGHT_BIQUAD5:
110         case TAS3001C_REG_RIGHT_BIQUAD6:
111                 return 15;
112 
113         default:
114                 return 0;
115         }
116 }
117 
118 static int
119 tas3001c_write_register(        struct tas3001c_data_t *self,
120                                 enum tas3001c_reg_t reg_num,
121                                 char *data,
122                                 uint write_mode)
123 {
124         if (reg_num==TAS3001C_REG_MCR ||
125             reg_num==TAS3001C_REG_BASS ||
126             reg_num==TAS3001C_REG_TREBLE) {
127                 return tas_write_byte_register(&self->super,
128                                                (uint)reg_num,
129                                                *data,
130                                                write_mode);
131         } else {
132                 return tas_write_register(&self->super,
133                                           (uint)reg_num,
134                                           register_width(reg_num),
135                                           data,
136                                           write_mode);
137         }
138 }
139 
140 static int
141 tas3001c_sync_register( struct tas3001c_data_t *self,
142                         enum tas3001c_reg_t reg_num)
143 {
144         if (reg_num==TAS3001C_REG_MCR ||
145             reg_num==TAS3001C_REG_BASS ||
146             reg_num==TAS3001C_REG_TREBLE) {
147                 return tas_sync_byte_register(&self->super,
148                                               (uint)reg_num,
149                                               register_width(reg_num));
150         } else {
151                 return tas_sync_register(&self->super,
152                                          (uint)reg_num,
153                                          register_width(reg_num));
154         }
155 }
156 
157 static int
158 tas3001c_read_register( struct tas3001c_data_t *self,
159                         enum tas3001c_reg_t reg_num,
160                         char *data,
161                         uint write_mode)
162 {
163         return tas_read_register(&self->super,
164                                  (uint)reg_num,
165                                  register_width(reg_num),
166                                  data);
167 }
168 
169 static inline int
170 tas3001c_fast_load(struct tas3001c_data_t *self, int fast)
171 {
172         if (fast)
173                 self->super.shadow[TAS3001C_REG_MCR][0] |= 0x80;
174         else
175                 self->super.shadow[TAS3001C_REG_MCR][0] &= 0x7f;
176         return tas3001c_sync_register(self,TAS3001C_REG_MCR);
177 }
178 
179 static uint
180 tas3001c_supported_mixers(struct tas3001c_data_t *self)
181 {
182         return SOUND_MASK_VOLUME |
183                 SOUND_MASK_PCM |
184                 SOUND_MASK_ALTPCM |
185                 SOUND_MASK_TREBLE |
186                 SOUND_MASK_BASS;
187 }
188 
189 static int
190 tas3001c_mixer_is_stereo(struct tas3001c_data_t *self,int mixer)
191 {
192         switch(mixer) {
193         case SOUND_MIXER_VOLUME:
194                 return 1;
195         default:
196                 return 0;
197         }
198 }
199 
200 static uint
201 tas3001c_stereo_mixers(struct tas3001c_data_t *self)
202 {
203         uint r=tas3001c_supported_mixers(self);
204         uint i;
205         
206         for (i=1; i<SOUND_MIXER_NRDEVICES; i++)
207                 if (r&(1<<i) && !tas3001c_mixer_is_stereo(self,i))
208                         r &= ~(1<<i);
209         return r;
210 }
211 
212 static int
213 tas3001c_get_mixer_level(struct tas3001c_data_t *self,int mixer,uint *level)
214 {
215         if (!self)
216                 return -1;
217                 
218         *level=self->super.mixer[mixer];
219         
220         return 0;
221 }
222 
223 static int
224 tas3001c_set_mixer_level(struct tas3001c_data_t *self,int mixer,uint level)
225 {
226         int rc;
227         tas_shadow_t *shadow;
228 
229         uint temp;
230         uint offset=0;
231 
232         if (!self)
233                 return -1;
234                 
235         shadow=self->super.shadow;
236 
237         if (!tas3001c_mixer_is_stereo(self,mixer))
238                 level = tas_mono_to_stereo(level);
239 
240         switch(mixer) {
241         case SOUND_MIXER_VOLUME:
242                 temp = tas3001c_gain.master[level&0xff];
243                 shadow[TAS3001C_REG_VOLUME][0] = (temp >> 16) & 0xff;
244                 shadow[TAS3001C_REG_VOLUME][1] = (temp >> 8)  & 0xff;
245                 shadow[TAS3001C_REG_VOLUME][2] = (temp >> 0)  & 0xff;
246                 temp = tas3001c_gain.master[(level>>8)&0xff];
247                 shadow[TAS3001C_REG_VOLUME][3] = (temp >> 16) & 0xff;
248                 shadow[TAS3001C_REG_VOLUME][4] = (temp >> 8)  & 0xff;
249                 shadow[TAS3001C_REG_VOLUME][5] = (temp >> 0)  & 0xff;
250                 rc = tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
251                 break;
252         case SOUND_MIXER_ALTPCM:
253                 /* tas3001c_fast_load(self, 1); */
254                 level = tas_mono_to_stereo(level);
255                 temp = tas3001c_gain.mixer[level&0xff];
256                 shadow[TAS3001C_REG_MIXER2][offset+0] = (temp >> 16) & 0xff;
257                 shadow[TAS3001C_REG_MIXER2][offset+1] = (temp >> 8)  & 0xff;
258                 shadow[TAS3001C_REG_MIXER2][offset+2] = (temp >> 0)  & 0xff;
259                 rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
260                 /* tas3001c_fast_load(self, 0); */
261                 break;
262         case SOUND_MIXER_PCM:
263                 /* tas3001c_fast_load(self, 1); */
264                 level = tas_mono_to_stereo(level);
265                 temp = tas3001c_gain.mixer[level&0xff];
266                 shadow[TAS3001C_REG_MIXER1][offset+0] = (temp >> 16) & 0xff;
267                 shadow[TAS3001C_REG_MIXER1][offset+1] = (temp >> 8)  & 0xff;
268                 shadow[TAS3001C_REG_MIXER1][offset+2] = (temp >> 0)  & 0xff;
269                 rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
270                 /* tas3001c_fast_load(self, 0); */
271                 break;
272         case SOUND_MIXER_TREBLE:
273                 temp = tas3001c_gain.treble[level&0xff];
274                 shadow[TAS3001C_REG_TREBLE][0]=temp&0xff;
275                 rc = tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
276                 break;
277         case SOUND_MIXER_BASS:
278                 temp = tas3001c_gain.bass[level&0xff];
279                 shadow[TAS3001C_REG_BASS][0]=temp&0xff;
280                 rc = tas3001c_sync_register(self,TAS3001C_REG_BASS);
281                 break;
282         default:
283                 rc = -1;
284                 break;
285         }
286         if (rc < 0)
287                 return rc;
288         self->super.mixer[mixer]=level;
289         return 0;
290 }
291 
292 static int
293 tas3001c_leave_sleep(struct tas3001c_data_t *self)
294 {
295         unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
296 
297         if (!self)
298                 return -1;
299 
300         /* Make sure something answers on the i2c bus */
301         if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr,
302             WRITE_NORMAL|FORCE_WRITE) < 0)
303                 return -1;
304 
305         tas3001c_fast_load(self, 1);
306 
307         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0);
308         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1);
309         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2);
310         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3);
311         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4);
312         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5);
313 
314         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0);
315         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1);
316         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2);
317         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3);
318         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4);
319         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5);
320 
321         tas3001c_fast_load(self, 0);
322 
323         (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
324         (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
325         (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
326         (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
327         (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
328 
329         return 0;
330 }
331 
332 static int
333 tas3001c_enter_sleep(struct tas3001c_data_t *self)
334 {
335         /* Stub for now, but I have the details on low-power mode */
336         if (!self)
337                 return -1; 
338         return 0;
339 }
340 
341 static int
342 tas3001c_sync_biquad(   struct tas3001c_data_t *self,
343                         u_int channel,
344                         u_int filter)
345 {
346         enum tas3001c_reg_t reg;
347 
348         if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
349             filter  >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
350 
351         reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
352 
353         return tas3001c_sync_register(self,reg);
354 }
355 
356 static int
357 tas3001c_write_biquad_shadow(   struct tas3001c_data_t *self,
358                                 u_int channel,
359                                 u_int filter,
360                                 const union tas_biquad_t *biquad)
361 {
362         tas_shadow_t *shadow=self->super.shadow;
363         enum tas3001c_reg_t reg;
364 
365         if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
366             filter  >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
367 
368         reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
369 
370         SET_4_20(shadow[reg], 0,biquad->coeff.b0);
371         SET_4_20(shadow[reg], 3,biquad->coeff.b1);
372         SET_4_20(shadow[reg], 6,biquad->coeff.b2);
373         SET_4_20(shadow[reg], 9,biquad->coeff.a1);
374         SET_4_20(shadow[reg],12,biquad->coeff.a2);
375 
376         return 0;
377 }
378 
379 static int
380 tas3001c_write_biquad(  struct tas3001c_data_t *self,
381                         u_int channel,
382                         u_int filter,
383                         const union tas_biquad_t *biquad)
384 {
385         int rc;
386 
387         rc=tas3001c_write_biquad_shadow(self, channel, filter, biquad);
388         if (rc < 0) return rc;
389 
390         return tas3001c_sync_biquad(self, channel, filter);
391 }
392 
393 static int
394 tas3001c_write_biquad_list(     struct tas3001c_data_t *self,
395                                 u_int filter_count,
396                                 u_int flags,
397                                 struct tas_biquad_ctrl_t *biquads)
398 {
399         int i;
400         int rc;
401 
402         if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1);
403 
404         for (i=0; i<filter_count; i++) {
405                 rc=tas3001c_write_biquad(self,
406                                          biquads[i].channel,
407                                          biquads[i].filter,
408                                          &biquads[i].data);
409                 if (rc < 0) break;
410         }
411 
412         if (flags & TAS_BIQUAD_FAST_LOAD) {
413                 tas3001c_fast_load(self,0);
414 
415                 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
416                 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
417                 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
418                 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
419                 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
420         }
421 
422         return rc;
423 }
424 
425 static int
426 tas3001c_read_biquad(   struct tas3001c_data_t *self,
427                         u_int channel,
428                         u_int filter,
429                         union tas_biquad_t *biquad)
430 {
431         tas_shadow_t *shadow=self->super.shadow;
432         enum tas3001c_reg_t reg;
433 
434         if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
435             filter  >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
436 
437         reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
438 
439         biquad->coeff.b0=GET_4_20(shadow[reg], 0);
440         biquad->coeff.b1=GET_4_20(shadow[reg], 3);
441         biquad->coeff.b2=GET_4_20(shadow[reg], 6);
442         biquad->coeff.a1=GET_4_20(shadow[reg], 9);
443         biquad->coeff.a2=GET_4_20(shadow[reg],12);
444         
445         return 0;       
446 }
447 
448 static int
449 tas3001c_eq_rw( struct tas3001c_data_t *self,
450                 u_int cmd,
451                 u_long arg)
452 {
453         int rc;
454         struct tas_biquad_ctrl_t biquad;
455         void __user *argp = (void __user *)arg;
456 
457         if (copy_from_user(&biquad, argp, sizeof(struct tas_biquad_ctrl_t))) {
458                 return -EFAULT;
459         }
460 
461         if (cmd & SIOC_IN) {
462                 rc=tas3001c_write_biquad(self, biquad.channel, biquad.filter, &biquad.data);
463                 if (rc != 0) return rc;
464         }
465 
466         if (cmd & SIOC_OUT) {
467                 rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
468                 if (rc != 0) return rc;
469 
470                 if (copy_to_user(argp, &biquad, sizeof(struct tas_biquad_ctrl_t))) {
471                         return -EFAULT;
472                 }
473 
474         }
475         return 0;
476 }
477 
478 static int
479 tas3001c_eq_list_rw(    struct tas3001c_data_t *self,
480                         u_int cmd,
481                         u_long arg)
482 {
483         int rc;
484         int filter_count;
485         int flags;
486         int i,j;
487         char sync_required[2][6];
488         struct tas_biquad_ctrl_t biquad;
489         struct tas_biquad_ctrl_list_t __user *argp = (void __user *)arg;
490 
491         memset(sync_required,0,sizeof(sync_required));
492 
493         if (copy_from_user(&filter_count, &argp->filter_count, sizeof(int)))
494                 return -EFAULT;
495 
496         if (copy_from_user(&flags, &argp->flags, sizeof(int)))
497                 return -EFAULT;
498 
499         if (cmd & SIOC_IN) {
500         }
501 
502         for (i=0; i < filter_count; i++) {
503                 if (copy_from_user(&biquad, &argp->biquads[i],
504                                    sizeof(struct tas_biquad_ctrl_t))) {
505                         return -EFAULT;
506                 }
507 
508                 if (cmd & SIOC_IN) {
509                         sync_required[biquad.channel][biquad.filter]=1;
510                         rc=tas3001c_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data);
511                         if (rc != 0) return rc;
512                 }
513 
514                 if (cmd & SIOC_OUT) {
515                         rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
516                         if (rc != 0) return rc;
517 
518                         if (copy_to_user(&argp->biquads[i], &biquad,
519                                          sizeof(struct tas_biquad_ctrl_t))) {
520                                 return -EFAULT;
521                         }
522                 }
523         }
524 
525         if (cmd & SIOC_IN) {
526                 if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1);
527                 for (i=0; i<2; i++) {
528                         for (j=0; j<6; j++) {
529                                 if (sync_required[i][j]) {
530                                         rc=tas3001c_sync_biquad(self, i, j);
531                                         if (rc < 0) return rc;
532                                 }
533                         }
534                 }
535                 if (flags & TAS_BIQUAD_FAST_LOAD) {
536                         tas3001c_fast_load(self,0);
537                         /* now we need to set up the mixers again,
538                            because leaving fast mode resets them. */
539                         (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
540                         (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
541                         (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
542                         (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
543                         (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
544                 }
545         }
546 
547         return 0;
548 }
549 
550 static int
551 tas3001c_update_drce(   struct tas3001c_data_t *self,
552                         int flags,
553                         struct tas_drce_t *drce)
554 {
555         tas_shadow_t *shadow;
556         shadow=self->super.shadow;
557 
558         shadow[TAS3001C_REG_DRC][1] = 0xc1;
559 
560         if (flags & TAS_DRCE_THRESHOLD) {
561                 self->drce_state.threshold=quantize_db(drce->threshold);
562                 shadow[TAS3001C_REG_DRC][2] = db_to_regval(self->drce_state.threshold);
563         }
564 
565         if (flags & TAS_DRCE_ENABLE) {
566                 self->drce_state.enable = drce->enable;
567         }
568 
569         if (!self->drce_state.enable) {
570                 shadow[TAS3001C_REG_DRC][0] = 0xf0;
571         }
572 
573 #ifdef DEBUG_DRCE
574         printk("DRCE IOCTL: set [ ENABLE:%x THRESH:%x\n",
575                self->drce_state.enable,
576                self->drce_state.threshold);
577 
578         printk("DRCE IOCTL: reg [ %02x %02x ]\n",
579                (unsigned char)shadow[TAS3001C_REG_DRC][0],
580                (unsigned char)shadow[TAS3001C_REG_DRC][1]);
581 #endif
582 
583         return tas3001c_sync_register(self, TAS3001C_REG_DRC);
584 }
585 
586 static int
587 tas3001c_drce_rw(       struct tas3001c_data_t *self,
588                         u_int cmd,
589                         u_long arg)
590 {
591         int rc;
592         struct tas_drce_ctrl_t drce_ctrl;
593         void __user *argp = (void __user *)arg;
594 
595         if (copy_from_user(&drce_ctrl, argp, sizeof(struct tas_drce_ctrl_t)))
596                 return -EFAULT;
597 
598 #ifdef DEBUG_DRCE
599         printk("DRCE IOCTL: input [ FLAGS:%x ENABLE:%x THRESH:%x\n",
600                drce_ctrl.flags,
601                drce_ctrl.data.enable,
602                drce_ctrl.data.threshold);
603 #endif
604 
605         if (cmd & SIOC_IN) {
606                 rc = tas3001c_update_drce(self, drce_ctrl.flags, &drce_ctrl.data);
607                 if (rc < 0)
608                         return rc;
609         }
610 
611         if (cmd & SIOC_OUT) {
612                 if (drce_ctrl.flags & TAS_DRCE_ENABLE)
613                         drce_ctrl.data.enable = self->drce_state.enable;
614 
615                 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD)
616                         drce_ctrl.data.threshold = self->drce_state.threshold;
617 
618                 if (copy_to_user(argp, &drce_ctrl,
619                                  sizeof(struct tas_drce_ctrl_t))) {
620                         return -EFAULT;
621                 }
622         }
623 
624         return 0;
625 }
626 
627 static void
628 tas3001c_update_device_parameters(struct tas3001c_data_t *self)
629 {
630         int i,j;
631 
632         if (!self) return;
633 
634         if (self->output_id == TAS_OUTPUT_HEADPHONES) {
635                 tas3001c_fast_load(self, 1);
636 
637                 for (i=0; i<TAS3001C_BIQUAD_CHANNEL_COUNT; i++) {
638                         for (j=0; j<TAS3001C_BIQUAD_FILTER_COUNT; j++) {
639                                 tas3001c_write_biquad(self, i, j, &tas3001c_eq_unity);
640                         }
641                 }
642 
643                 tas3001c_fast_load(self, 0);
644 
645                 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
646                 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
647                 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
648                 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
649                 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
650 
651                 return;
652         }
653 
654         for (i=0; tas3001c_eq_prefs[i]; i++) {
655                 struct tas_eq_pref_t *eq = tas3001c_eq_prefs[i];
656 
657                 if (eq->device_id == self->device_id &&
658                     (eq->output_id == 0 || eq->output_id == self->output_id) &&
659                     (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) {
660 
661                         tas3001c_update_drce(self, TAS_DRCE_ALL, eq->drce);
662                         tas3001c_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads);
663 
664                         break;
665                 }
666         }
667 }
668 
669 static void
670 tas3001c_device_change_handler(void *self)
671 {
672         if (self)
673                 tas3001c_update_device_parameters(self);
674 }
675 
676 static struct work_struct device_change;
677 
678 static int
679 tas3001c_output_device_change(  struct tas3001c_data_t *self,
680                                 int device_id,
681                                 int output_id,
682                                 int speaker_id)
683 {
684         self->device_id=device_id;
685         self->output_id=output_id;
686         self->speaker_id=speaker_id;
687 
688         schedule_work(&device_change);
689         return 0;
690 }
691 
692 static int
693 tas3001c_device_ioctl(  struct tas3001c_data_t *self,
694                         u_int cmd,
695                         u_long arg)
696 {
697         uint __user *argp = (void __user *)arg;
698         switch (cmd) {
699         case TAS_READ_EQ:
700         case TAS_WRITE_EQ:
701                 return tas3001c_eq_rw(self, cmd, arg);
702 
703         case TAS_READ_EQ_LIST:
704         case TAS_WRITE_EQ_LIST:
705                 return tas3001c_eq_list_rw(self, cmd, arg);
706 
707         case TAS_READ_EQ_FILTER_COUNT:
708                 put_user(TAS3001C_BIQUAD_FILTER_COUNT, argp);
709                 return 0;
710 
711         case TAS_READ_EQ_CHANNEL_COUNT:
712                 put_user(TAS3001C_BIQUAD_CHANNEL_COUNT, argp);
713                 return 0;
714 
715         case TAS_READ_DRCE:
716         case TAS_WRITE_DRCE:
717                 return tas3001c_drce_rw(self, cmd, arg);
718 
719         case TAS_READ_DRCE_CAPS:
720                 put_user(TAS_DRCE_ENABLE | TAS_DRCE_THRESHOLD, argp);
721                 return 0;
722 
723         case TAS_READ_DRCE_MIN:
724         case TAS_READ_DRCE_MAX: {
725                 struct tas_drce_ctrl_t drce_ctrl;
726 
727                 if (copy_from_user(&drce_ctrl, argp,
728                                    sizeof(struct tas_drce_ctrl_t))) {
729                         return -EFAULT;
730                 }
731 
732                 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) {
733                         if (cmd == TAS_READ_DRCE_MIN) {
734                                 drce_ctrl.data.threshold=-36<<8;
735                         } else {
736                                 drce_ctrl.data.threshold=-6<<8;
737                         }
738                 }
739 
740                 if (copy_to_user(argp, &drce_ctrl,
741                                  sizeof(struct tas_drce_ctrl_t))) {
742                         return -EFAULT;
743                 }
744         }
745         }
746 
747         return -EINVAL;
748 }
749 
750 static int
751 tas3001c_init_mixer(struct tas3001c_data_t *self)
752 {
753         unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
754 
755         /* Make sure something answers on the i2c bus */
756         if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr,
757             WRITE_NORMAL|FORCE_WRITE) < 0)
758                 return -1;
759 
760         tas3001c_fast_load(self, 1);
761 
762         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0);
763         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1);
764         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2);
765         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3);
766         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4);
767         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5);
768         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD6);
769 
770         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0);
771         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1);
772         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2);
773         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3);
774         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4);
775         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5);
776         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD6);
777 
778         tas3001c_fast_load(self, 0);
779 
780         tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, VOL_DEFAULT<<8 | VOL_DEFAULT);
781         tas3001c_set_mixer_level(self, SOUND_MIXER_PCM, INPUT_DEFAULT<<8 | INPUT_DEFAULT);
782         tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0);
783 
784         tas3001c_set_mixer_level(self, SOUND_MIXER_BASS, BASS_DEFAULT);
785         tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, TREBLE_DEFAULT);
786 
787         return 0;
788 }
789 
790 static int
791 tas3001c_uninit_mixer(struct tas3001c_data_t *self)
792 {
793         tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, 0);
794         tas3001c_set_mixer_level(self, SOUND_MIXER_PCM,    0);
795         tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0);
796 
797         tas3001c_set_mixer_level(self, SOUND_MIXER_BASS,   0);
798         tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, 0);
799 
800         return 0;
801 }
802 
803 static int
804 tas3001c_init(struct i2c_client *client)
805 {
806         struct tas3001c_data_t *self;
807         size_t sz = sizeof(*self) + (TAS3001C_REG_MAX*sizeof(tas_shadow_t));
808         int i, j;
809 
810         self = kmalloc(sz, GFP_KERNEL);
811         if (!self)
812                 return -ENOMEM;
813         memset(self, 0, sz);
814 
815         self->super.client = client;
816         self->super.shadow = (tas_shadow_t *)(self+1);
817         self->output_id = TAS_OUTPUT_HEADPHONES;
818 
819         dev_set_drvdata(&client->dev, self);
820 
821         for (i = 0; i < TAS3001C_BIQUAD_CHANNEL_COUNT; i++)
822                 for (j = 0; j < TAS3001C_BIQUAD_FILTER_COUNT; j++)
823                         tas3001c_write_biquad_shadow(self, i, j,
824                                 &tas3001c_eq_unity);
825 
826         INIT_WORK(&device_change, tas3001c_device_change_handler, self);
827         return 0;
828 }
829 
830 static void
831 tas3001c_uninit(struct tas3001c_data_t *self)
832 {
833         tas3001c_uninit_mixer(self);
834         kfree(self);
835 }
836 
837 struct tas_driver_hooks_t tas3001c_hooks = {
838         .init                   = (tas_hook_init_t)tas3001c_init,
839         .post_init              = (tas_hook_post_init_t)tas3001c_init_mixer,
840         .uninit                 = (tas_hook_uninit_t)tas3001c_uninit,
841         .get_mixer_level        = (tas_hook_get_mixer_level_t)tas3001c_get_mixer_level,
842         .set_mixer_level        = (tas_hook_set_mixer_level_t)tas3001c_set_mixer_level,
843         .enter_sleep            = (tas_hook_enter_sleep_t)tas3001c_enter_sleep,
844         .leave_sleep            = (tas_hook_leave_sleep_t)tas3001c_leave_sleep,
845         .supported_mixers       = (tas_hook_supported_mixers_t)tas3001c_supported_mixers,
846         .mixer_is_stereo        = (tas_hook_mixer_is_stereo_t)tas3001c_mixer_is_stereo,
847         .stereo_mixers          = (tas_hook_stereo_mixers_t)tas3001c_stereo_mixers,
848         .output_device_change   = (tas_hook_output_device_change_t)tas3001c_output_device_change,
849         .device_ioctl           = (tas_hook_device_ioctl_t)tas3001c_device_ioctl
850 };
851 
  This page was automatically generated by the LXR engine.