blob: 82eaaca2db9a42a69ff39c790f87ef5b7e2f4b79 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
45struct 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
58static const union tas_biquad_t tas3004_eq_unity = {
59 .buf = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 },
60};
61
62
63static 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
74static 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
85static 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
100static 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
118static 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
129static 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
140static 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
159static inline int
160search( 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
182static inline int
183time_index(unsigned short time)
184{
185 return SEARCH(time, time_constants);
186}
187
188
189static inline int
190above_threshold_compression_index(unsigned short ratio)
191{
192 return SEARCH(ratio, above_threshold_compression_ratio);
193}
194
195
196static inline int
197above_threshold_expansion_index(unsigned short ratio)
198{
199 return SEARCH(ratio, above_threshold_expansion_ratio);
200}
201
202
203static inline int
204below_threshold_compression_index(unsigned short ratio)
205{
206 return SEARCH(ratio, below_threshold_compression_ratio);
207}
208
209
210static inline int
211below_threshold_expansion_index(unsigned short ratio)
212{
213 return SEARCH(ratio, below_threshold_expansion_ratio);
214}
215
216static 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
226static inline short quantize_db(short db)
227{
228 return db_to_regval(db) * 0x60 - 0x59a0;
229}
230
231static inline int
232register_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
284static int
285tas3004_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
307static int
308tas3004_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
325static int
326tas3004_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
337static inline int
338tas3004_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
347static uint
348tas3004_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
360static int
361tas3004_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
374static uint
375tas3004_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
386static int
387tas3004_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
397static int
398tas3004_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
483static int
484tas3004_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
526static int
527tas3004_enter_sleep(struct tas3004_data_t *self)
528{
529 if (!self)
530 return -1;
531 return 0;
532}
533
534static int
535tas3004_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
549static int
550tas3004_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
572static int
573tas3004_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
586static int
587tas3004_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
610static int
611tas3004_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
633static int
634tas3004_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
663static int
664tas3004_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
734static int
735tas3004_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
830static int
831tas3004_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
884static void
885tas3004_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
916static void
917tas3004_device_change_handler(void *self)
918{
919 if (!self) return;
920
921 tas3004_update_device_parameters((struct tas3004_data_t *)self);
922}
923
924static struct work_struct device_change;
925
926static int
927tas3004_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
941static int
942tas3004_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
1024static int
1025tas3004_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
1071static int
1072tas3004_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
1087static int
1088tas3004_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
1119static void
1120tas3004_uninit(struct tas3004_data_t *self)
1121{
1122 tas3004_uninit_mixer(self);
1123 kfree(self);
1124}
1125
1126
1127struct 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};