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