fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / sound / oss / dmasound / tas3001c.c
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         struct work_struct change;
54 };
55
56
57 static const union tas_biquad_t
58 tas3001c_eq_unity={
59         .buf = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 }
60 };
61
62
63 static inline unsigned char db_to_regval(short db) {
64         int r=0;
65
66         r=(db+0x59a0) / 0x60;
67
68         if (r < 0x91) return 0x91;
69         if (r > 0xef) return 0xef;
70         return r;
71 }
72
73 static inline short quantize_db(short db) {
74         return db_to_regval(db) * 0x60 - 0x59a0;
75 }
76
77
78 static inline int
79 register_width(enum tas3001c_reg_t r)
80 {
81         switch(r) {
82         case TAS3001C_REG_MCR:
83         case TAS3001C_REG_TREBLE:
84         case TAS3001C_REG_BASS:
85                 return 1;
86
87         case TAS3001C_REG_DRC:
88                 return 2;
89
90         case TAS3001C_REG_MIXER1:
91         case TAS3001C_REG_MIXER2:
92                 return 3;
93
94         case TAS3001C_REG_VOLUME:
95                 return 6;
96
97         case TAS3001C_REG_LEFT_BIQUAD0:
98         case TAS3001C_REG_LEFT_BIQUAD1:
99         case TAS3001C_REG_LEFT_BIQUAD2:
100         case TAS3001C_REG_LEFT_BIQUAD3:
101         case TAS3001C_REG_LEFT_BIQUAD4:
102         case TAS3001C_REG_LEFT_BIQUAD5:
103         case TAS3001C_REG_LEFT_BIQUAD6:
104
105         case TAS3001C_REG_RIGHT_BIQUAD0:
106         case TAS3001C_REG_RIGHT_BIQUAD1:
107         case TAS3001C_REG_RIGHT_BIQUAD2:
108         case TAS3001C_REG_RIGHT_BIQUAD3:
109         case TAS3001C_REG_RIGHT_BIQUAD4:
110         case TAS3001C_REG_RIGHT_BIQUAD5:
111         case TAS3001C_REG_RIGHT_BIQUAD6:
112                 return 15;
113
114         default:
115                 return 0;
116         }
117 }
118
119 static int
120 tas3001c_write_register(        struct tas3001c_data_t *self,
121                                 enum tas3001c_reg_t reg_num,
122                                 char *data,
123                                 uint write_mode)
124 {
125         if (reg_num==TAS3001C_REG_MCR ||
126             reg_num==TAS3001C_REG_BASS ||
127             reg_num==TAS3001C_REG_TREBLE) {
128                 return tas_write_byte_register(&self->super,
129                                                (uint)reg_num,
130                                                *data,
131                                                write_mode);
132         } else {
133                 return tas_write_register(&self->super,
134                                           (uint)reg_num,
135                                           register_width(reg_num),
136                                           data,
137                                           write_mode);
138         }
139 }
140
141 static int
142 tas3001c_sync_register( struct tas3001c_data_t *self,
143                         enum tas3001c_reg_t reg_num)
144 {
145         if (reg_num==TAS3001C_REG_MCR ||
146             reg_num==TAS3001C_REG_BASS ||
147             reg_num==TAS3001C_REG_TREBLE) {
148                 return tas_sync_byte_register(&self->super,
149                                               (uint)reg_num,
150                                               register_width(reg_num));
151         } else {
152                 return tas_sync_register(&self->super,
153                                          (uint)reg_num,
154                                          register_width(reg_num));
155         }
156 }
157
158 static int
159 tas3001c_read_register( struct tas3001c_data_t *self,
160                         enum tas3001c_reg_t reg_num,
161                         char *data,
162                         uint write_mode)
163 {
164         return tas_read_register(&self->super,
165                                  (uint)reg_num,
166                                  register_width(reg_num),
167                                  data);
168 }
169
170 static inline int
171 tas3001c_fast_load(struct tas3001c_data_t *self, int fast)
172 {
173         if (fast)
174                 self->super.shadow[TAS3001C_REG_MCR][0] |= 0x80;
175         else
176                 self->super.shadow[TAS3001C_REG_MCR][0] &= 0x7f;
177         return tas3001c_sync_register(self,TAS3001C_REG_MCR);
178 }
179
180 static uint
181 tas3001c_supported_mixers(struct tas3001c_data_t *self)
182 {
183         return SOUND_MASK_VOLUME |
184                 SOUND_MASK_PCM |
185                 SOUND_MASK_ALTPCM |
186                 SOUND_MASK_TREBLE |
187                 SOUND_MASK_BASS;
188 }
189
190 static int
191 tas3001c_mixer_is_stereo(struct tas3001c_data_t *self,int mixer)
192 {
193         switch(mixer) {
194         case SOUND_MIXER_VOLUME:
195                 return 1;
196         default:
197                 return 0;
198         }
199 }
200
201 static uint
202 tas3001c_stereo_mixers(struct tas3001c_data_t *self)
203 {
204         uint r=tas3001c_supported_mixers(self);
205         uint i;
206         
207         for (i=1; i<SOUND_MIXER_NRDEVICES; i++)
208                 if (r&(1<<i) && !tas3001c_mixer_is_stereo(self,i))
209                         r &= ~(1<<i);
210         return r;
211 }
212
213 static int
214 tas3001c_get_mixer_level(struct tas3001c_data_t *self,int mixer,uint *level)
215 {
216         if (!self)
217                 return -1;
218                 
219         *level=self->super.mixer[mixer];
220         
221         return 0;
222 }
223
224 static int
225 tas3001c_set_mixer_level(struct tas3001c_data_t *self,int mixer,uint level)
226 {
227         int rc;
228         tas_shadow_t *shadow;
229
230         uint temp;
231         uint offset=0;
232
233         if (!self)
234                 return -1;
235                 
236         shadow=self->super.shadow;
237
238         if (!tas3001c_mixer_is_stereo(self,mixer))
239                 level = tas_mono_to_stereo(level);
240
241         switch(mixer) {
242         case SOUND_MIXER_VOLUME:
243                 temp = tas3001c_gain.master[level&0xff];
244                 shadow[TAS3001C_REG_VOLUME][0] = (temp >> 16) & 0xff;
245                 shadow[TAS3001C_REG_VOLUME][1] = (temp >> 8)  & 0xff;
246                 shadow[TAS3001C_REG_VOLUME][2] = (temp >> 0)  & 0xff;
247                 temp = tas3001c_gain.master[(level>>8)&0xff];
248                 shadow[TAS3001C_REG_VOLUME][3] = (temp >> 16) & 0xff;
249                 shadow[TAS3001C_REG_VOLUME][4] = (temp >> 8)  & 0xff;
250                 shadow[TAS3001C_REG_VOLUME][5] = (temp >> 0)  & 0xff;
251                 rc = tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
252                 break;
253         case SOUND_MIXER_ALTPCM:
254                 /* tas3001c_fast_load(self, 1); */
255                 level = tas_mono_to_stereo(level);
256                 temp = tas3001c_gain.mixer[level&0xff];
257                 shadow[TAS3001C_REG_MIXER2][offset+0] = (temp >> 16) & 0xff;
258                 shadow[TAS3001C_REG_MIXER2][offset+1] = (temp >> 8)  & 0xff;
259                 shadow[TAS3001C_REG_MIXER2][offset+2] = (temp >> 0)  & 0xff;
260                 rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
261                 /* tas3001c_fast_load(self, 0); */
262                 break;
263         case SOUND_MIXER_PCM:
264                 /* tas3001c_fast_load(self, 1); */
265                 level = tas_mono_to_stereo(level);
266                 temp = tas3001c_gain.mixer[level&0xff];
267                 shadow[TAS3001C_REG_MIXER1][offset+0] = (temp >> 16) & 0xff;
268                 shadow[TAS3001C_REG_MIXER1][offset+1] = (temp >> 8)  & 0xff;
269                 shadow[TAS3001C_REG_MIXER1][offset+2] = (temp >> 0)  & 0xff;
270                 rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
271                 /* tas3001c_fast_load(self, 0); */
272                 break;
273         case SOUND_MIXER_TREBLE:
274                 temp = tas3001c_gain.treble[level&0xff];
275                 shadow[TAS3001C_REG_TREBLE][0]=temp&0xff;
276                 rc = tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
277                 break;
278         case SOUND_MIXER_BASS:
279                 temp = tas3001c_gain.bass[level&0xff];
280                 shadow[TAS3001C_REG_BASS][0]=temp&0xff;
281                 rc = tas3001c_sync_register(self,TAS3001C_REG_BASS);
282                 break;
283         default:
284                 rc = -1;
285                 break;
286         }
287         if (rc < 0)
288                 return rc;
289         self->super.mixer[mixer]=level;
290         return 0;
291 }
292
293 static int
294 tas3001c_leave_sleep(struct tas3001c_data_t *self)
295 {
296         unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
297
298         if (!self)
299                 return -1;
300
301         /* Make sure something answers on the i2c bus */
302         if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr,
303             WRITE_NORMAL|FORCE_WRITE) < 0)
304                 return -1;
305
306         tas3001c_fast_load(self, 1);
307
308         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0);
309         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1);
310         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2);
311         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3);
312         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4);
313         (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5);
314
315         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0);
316         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1);
317         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2);
318         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3);
319         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4);
320         (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5);
321
322         tas3001c_fast_load(self, 0);
323
324         (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
325         (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
326         (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
327         (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
328         (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
329
330         return 0;
331 }
332
333 static int
334 tas3001c_enter_sleep(struct tas3001c_data_t *self)
335 {
336         /* Stub for now, but I have the details on low-power mode */
337         if (!self)
338                 return -1; 
339         return 0;
340 }
341
342 static int
343 tas3001c_sync_biquad(   struct tas3001c_data_t *self,
344                         u_int channel,
345                         u_int filter)
346 {
347         enum tas3001c_reg_t reg;
348
349         if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
350             filter  >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
351
352         reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
353
354         return tas3001c_sync_register(self,reg);
355 }
356
357 static int
358 tas3001c_write_biquad_shadow(   struct tas3001c_data_t *self,
359                                 u_int channel,
360                                 u_int filter,
361                                 const union tas_biquad_t *biquad)
362 {
363         tas_shadow_t *shadow=self->super.shadow;
364         enum tas3001c_reg_t reg;
365
366         if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
367             filter  >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
368
369         reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
370
371         SET_4_20(shadow[reg], 0,biquad->coeff.b0);
372         SET_4_20(shadow[reg], 3,biquad->coeff.b1);
373         SET_4_20(shadow[reg], 6,biquad->coeff.b2);
374         SET_4_20(shadow[reg], 9,biquad->coeff.a1);
375         SET_4_20(shadow[reg],12,biquad->coeff.a2);
376
377         return 0;
378 }
379
380 static int
381 tas3001c_write_biquad(  struct tas3001c_data_t *self,
382                         u_int channel,
383                         u_int filter,
384                         const union tas_biquad_t *biquad)
385 {
386         int rc;
387
388         rc=tas3001c_write_biquad_shadow(self, channel, filter, biquad);
389         if (rc < 0) return rc;
390
391         return tas3001c_sync_biquad(self, channel, filter);
392 }
393
394 static int
395 tas3001c_write_biquad_list(     struct tas3001c_data_t *self,
396                                 u_int filter_count,
397                                 u_int flags,
398                                 struct tas_biquad_ctrl_t *biquads)
399 {
400         int i;
401         int rc;
402
403         if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1);
404
405         for (i=0; i<filter_count; i++) {
406                 rc=tas3001c_write_biquad(self,
407                                          biquads[i].channel,
408                                          biquads[i].filter,
409                                          &biquads[i].data);
410                 if (rc < 0) break;
411         }
412
413         if (flags & TAS_BIQUAD_FAST_LOAD) {
414                 tas3001c_fast_load(self,0);
415
416                 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
417                 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
418                 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
419                 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
420                 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
421         }
422
423         return rc;
424 }
425
426 static int
427 tas3001c_read_biquad(   struct tas3001c_data_t *self,
428                         u_int channel,
429                         u_int filter,
430                         union tas_biquad_t *biquad)
431 {
432         tas_shadow_t *shadow=self->super.shadow;
433         enum tas3001c_reg_t reg;
434
435         if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
436             filter  >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
437
438         reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
439
440         biquad->coeff.b0=GET_4_20(shadow[reg], 0);
441         biquad->coeff.b1=GET_4_20(shadow[reg], 3);
442         biquad->coeff.b2=GET_4_20(shadow[reg], 6);
443         biquad->coeff.a1=GET_4_20(shadow[reg], 9);
444         biquad->coeff.a2=GET_4_20(shadow[reg],12);
445         
446         return 0;       
447 }
448
449 static int
450 tas3001c_eq_rw( struct tas3001c_data_t *self,
451                 u_int cmd,
452                 u_long arg)
453 {
454         int rc;
455         struct tas_biquad_ctrl_t biquad;
456         void __user *argp = (void __user *)arg;
457
458         if (copy_from_user(&biquad, argp, sizeof(struct tas_biquad_ctrl_t))) {
459                 return -EFAULT;
460         }
461
462         if (cmd & SIOC_IN) {
463                 rc=tas3001c_write_biquad(self, biquad.channel, biquad.filter, &biquad.data);
464                 if (rc != 0) return rc;
465         }
466
467         if (cmd & SIOC_OUT) {
468                 rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
469                 if (rc != 0) return rc;
470
471                 if (copy_to_user(argp, &biquad, sizeof(struct tas_biquad_ctrl_t))) {
472                         return -EFAULT;
473                 }
474
475         }
476         return 0;
477 }
478
479 static int
480 tas3001c_eq_list_rw(    struct tas3001c_data_t *self,
481                         u_int cmd,
482                         u_long arg)
483 {
484         int rc;
485         int filter_count;
486         int flags;
487         int i,j;
488         char sync_required[2][6];
489         struct tas_biquad_ctrl_t biquad;
490         struct tas_biquad_ctrl_list_t __user *argp = (void __user *)arg;
491
492         memset(sync_required,0,sizeof(sync_required));
493
494         if (copy_from_user(&filter_count, &argp->filter_count, sizeof(int)))
495                 return -EFAULT;
496
497         if (copy_from_user(&flags, &argp->flags, sizeof(int)))
498                 return -EFAULT;
499
500         if (cmd & SIOC_IN) {
501         }
502
503         for (i=0; i < filter_count; i++) {
504                 if (copy_from_user(&biquad, &argp->biquads[i],
505                                    sizeof(struct tas_biquad_ctrl_t))) {
506                         return -EFAULT;
507                 }
508
509                 if (cmd & SIOC_IN) {
510                         sync_required[biquad.channel][biquad.filter]=1;
511                         rc=tas3001c_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data);
512                         if (rc != 0) return rc;
513                 }
514
515                 if (cmd & SIOC_OUT) {
516                         rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
517                         if (rc != 0) return rc;
518
519                         if (copy_to_user(&argp->biquads[i], &biquad,
520                                          sizeof(struct tas_biquad_ctrl_t))) {
521                                 return -EFAULT;
522                         }
523                 }
524         }
525
526         if (cmd & SIOC_IN) {
527                 if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1);
528                 for (i=0; i<2; i++) {
529                         for (j=0; j<6; j++) {
530                                 if (sync_required[i][j]) {
531                                         rc=tas3001c_sync_biquad(self, i, j);
532                                         if (rc < 0) return rc;
533                                 }
534                         }
535                 }
536                 if (flags & TAS_BIQUAD_FAST_LOAD) {
537                         tas3001c_fast_load(self,0);
538                         /* now we need to set up the mixers again,
539                            because leaving fast mode resets them. */
540                         (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
541                         (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
542                         (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
543                         (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
544                         (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
545                 }
546         }
547
548         return 0;
549 }
550
551 static int
552 tas3001c_update_drce(   struct tas3001c_data_t *self,
553                         int flags,
554                         struct tas_drce_t *drce)
555 {
556         tas_shadow_t *shadow;
557         shadow=self->super.shadow;
558
559         shadow[TAS3001C_REG_DRC][1] = 0xc1;
560
561         if (flags & TAS_DRCE_THRESHOLD) {
562                 self->drce_state.threshold=quantize_db(drce->threshold);
563                 shadow[TAS3001C_REG_DRC][2] = db_to_regval(self->drce_state.threshold);
564         }
565
566         if (flags & TAS_DRCE_ENABLE) {
567                 self->drce_state.enable = drce->enable;
568         }
569
570         if (!self->drce_state.enable) {
571                 shadow[TAS3001C_REG_DRC][0] = 0xf0;
572         }
573
574 #ifdef DEBUG_DRCE
575         printk("DRCE IOCTL: set [ ENABLE:%x THRESH:%x\n",
576                self->drce_state.enable,
577                self->drce_state.threshold);
578
579         printk("DRCE IOCTL: reg [ %02x %02x ]\n",
580                (unsigned char)shadow[TAS3001C_REG_DRC][0],
581                (unsigned char)shadow[TAS3001C_REG_DRC][1]);
582 #endif
583
584         return tas3001c_sync_register(self, TAS3001C_REG_DRC);
585 }
586
587 static int
588 tas3001c_drce_rw(       struct tas3001c_data_t *self,
589                         u_int cmd,
590                         u_long arg)
591 {
592         int rc;
593         struct tas_drce_ctrl_t drce_ctrl;
594         void __user *argp = (void __user *)arg;
595
596         if (copy_from_user(&drce_ctrl, argp, sizeof(struct tas_drce_ctrl_t)))
597                 return -EFAULT;
598
599 #ifdef DEBUG_DRCE
600         printk("DRCE IOCTL: input [ FLAGS:%x ENABLE:%x THRESH:%x\n",
601                drce_ctrl.flags,
602                drce_ctrl.data.enable,
603                drce_ctrl.data.threshold);
604 #endif
605
606         if (cmd & SIOC_IN) {
607                 rc = tas3001c_update_drce(self, drce_ctrl.flags, &drce_ctrl.data);
608                 if (rc < 0)
609                         return rc;
610         }
611
612         if (cmd & SIOC_OUT) {
613                 if (drce_ctrl.flags & TAS_DRCE_ENABLE)
614                         drce_ctrl.data.enable = self->drce_state.enable;
615
616                 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD)
617                         drce_ctrl.data.threshold = self->drce_state.threshold;
618
619                 if (copy_to_user(argp, &drce_ctrl,
620                                  sizeof(struct tas_drce_ctrl_t))) {
621                         return -EFAULT;
622                 }
623         }
624
625         return 0;
626 }
627
628 static void
629 tas3001c_update_device_parameters(struct tas3001c_data_t *self)
630 {
631         int i,j;
632
633         if (!self) return;
634
635         if (self->output_id == TAS_OUTPUT_HEADPHONES) {
636                 tas3001c_fast_load(self, 1);
637
638                 for (i=0; i<TAS3001C_BIQUAD_CHANNEL_COUNT; i++) {
639                         for (j=0; j<TAS3001C_BIQUAD_FILTER_COUNT; j++) {
640                                 tas3001c_write_biquad(self, i, j, &tas3001c_eq_unity);
641                         }
642                 }
643
644                 tas3001c_fast_load(self, 0);
645
646                 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
647                 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
648                 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
649                 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
650                 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
651
652                 return;
653         }
654
655         for (i=0; tas3001c_eq_prefs[i]; i++) {
656                 struct tas_eq_pref_t *eq = tas3001c_eq_prefs[i];
657
658                 if (eq->device_id == self->device_id &&
659                     (eq->output_id == 0 || eq->output_id == self->output_id) &&
660                     (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) {
661
662                         tas3001c_update_drce(self, TAS_DRCE_ALL, eq->drce);
663                         tas3001c_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads);
664
665                         break;
666                 }
667         }
668 }
669
670 static void
671 tas3001c_device_change_handler(struct work_struct *work)
672 {
673         struct tas3001c_data_t *self;
674         self = container_of(work, struct tas3001c_data_t, change);
675         tas3001c_update_device_parameters(self);
676 }
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(&self->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(&self->change, tas3001c_device_change_handler);
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 };