2 * Driver for the i2c/i2s based TA3004 sound chip used
3 * on some Apple hardware. Also known as "snapper".
5 * Tobias Sargeant <tobias.sargeant@bigpond.com>
6 * Based upon tas3001c.c by Christopher C. Chimelis <chris@debian.org>:
8 * Input support by Renzo Davoli <renzo@cs.unibo.it>
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>
24 #include <asm/uaccess.h>
25 #include <asm/errno.h>
30 #include "tas_common.h"
33 #include "tas_ioctl.h"
35 /* #define DEBUG_DRCE */
37 #define TAS3004_BIQUAD_FILTER_COUNT 7
38 #define TAS3004_BIQUAD_CHANNEL_COUNT 2
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)
45 struct tas3004_data_t
{
46 struct tas_data_t super
;
50 struct tas_drce_t drce_state
;
53 #define MAKE_TIME(sec,usec) (((sec)<<12) + (50000+(usec/10)*(1<<12))/100000)
55 #define MAKE_RATIO(i,f) (((i)<<8) + ((500+(f)*(1<<8))/1000))
58 static const union tas_biquad_t tas3004_eq_unity
= {
59 .buf
= { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 },
63 static const struct tas_drce_t tas3004_drce_min
= {
65 .above
= { .val
= MAKE_RATIO(16,0), .expand
= 0 },
66 .below
= { .val
= MAKE_RATIO(2,0), .expand
= 0 },
68 .energy
= MAKE_TIME(0, 1700),
69 .attack
= MAKE_TIME(0, 1700),
70 .decay
= MAKE_TIME(0, 1700),
74 static const struct tas_drce_t tas3004_drce_max
= {
76 .above
= { .val
= MAKE_RATIO(1,500), .expand
= 1 },
77 .below
= { .val
= MAKE_RATIO(2,0), .expand
= 1 },
79 .energy
= MAKE_TIME(2,400000),
80 .attack
= MAKE_TIME(2,400000),
81 .decay
= MAKE_TIME(2,400000),
85 static const unsigned short time_constants
[]={
100 static const unsigned short above_threshold_compression_ratio
[]={
118 static const unsigned short above_threshold_expansion_ratio
[]={
129 static const unsigned short below_threshold_compression_ratio
[]={
140 static const unsigned short below_threshold_expansion_ratio
[]={
160 search( unsigned short val
,
161 const unsigned short *arr
,
164 * This could be a binary search, but for small tables,
165 * a linear search is likely to be faster
170 for (i
=0; i
< arrsize
; i
++)
177 return (arr
[i
]-val
< val
-arr
[i
-1]) ? i
: i
-1;
180 #define SEARCH(a, b) search(a, b, ARRAY_SIZE(b))
183 time_index(unsigned short time
)
185 return SEARCH(time
, time_constants
);
190 above_threshold_compression_index(unsigned short ratio
)
192 return SEARCH(ratio
, above_threshold_compression_ratio
);
197 above_threshold_expansion_index(unsigned short ratio
)
199 return SEARCH(ratio
, above_threshold_expansion_ratio
);
204 below_threshold_compression_index(unsigned short ratio
)
206 return SEARCH(ratio
, below_threshold_compression_ratio
);
211 below_threshold_expansion_index(unsigned short ratio
)
213 return SEARCH(ratio
, below_threshold_expansion_ratio
);
216 static inline unsigned char db_to_regval(short db
) {
219 r
=(db
+0x59a0) / 0x60;
221 if (r
< 0x91) return 0x91;
222 if (r
> 0xef) return 0xef;
226 static inline short quantize_db(short db
)
228 return db_to_regval(db
) * 0x60 - 0x59a0;
232 register_width(enum tas3004_reg_t 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
:
244 case TAS3004_REG_LEFT_LOUD_BIQUAD_GAIN
:
245 case TAS3004_REG_RIGHT_LOUD_BIQUAD_GAIN
:
248 case TAS3004_REG_DRC
:
249 case TAS3004_REG_VOLUME
:
252 case TAS3004_REG_LEFT_MIXER
:
253 case TAS3004_REG_RIGHT_MIXER
:
256 case TAS3004_REG_TEST
:
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
:
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
:
275 case TAS3004_REG_LEFT_LOUD_BIQUAD
:
276 case TAS3004_REG_RIGHT_LOUD_BIQUAD
:
285 tas3004_write_register( struct tas3004_data_t
*self
,
286 enum tas3004_reg_t reg_num
,
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
,
299 return tas_write_register(&self
->super
,
301 register_width(reg_num
),
308 tas3004_sync_register( struct tas3004_data_t
*self
,
309 enum tas3004_reg_t reg_num
)
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
,
317 register_width(reg_num
));
319 return tas_sync_register(&self
->super
,
321 register_width(reg_num
));
326 tas3004_read_register( struct tas3004_data_t
*self
,
327 enum tas3004_reg_t reg_num
,
331 return tas_read_register(&self
->super
,
333 register_width(reg_num
),
338 tas3004_fast_load(struct tas3004_data_t
*self
, int fast
)
341 self
->super
.shadow
[TAS3004_REG_MCR
][0] |= 0x80;
343 self
->super
.shadow
[TAS3004_REG_MCR
][0] &= 0x7f;
344 return tas3004_sync_register(self
,TAS3004_REG_MCR
);
348 tas3004_supported_mixers(struct tas3004_data_t
*self
)
350 return SOUND_MASK_VOLUME
|
361 tas3004_mixer_is_stereo(struct tas3004_data_t
*self
, int mixer
)
364 case SOUND_MIXER_VOLUME
:
365 case SOUND_MIXER_PCM
:
366 case SOUND_MIXER_ALTPCM
:
367 case SOUND_MIXER_IMIX
:
375 tas3004_stereo_mixers(struct tas3004_data_t
*self
)
377 uint r
= tas3004_supported_mixers(self
);
380 for (i
=1; i
<SOUND_MIXER_NRDEVICES
; i
++)
381 if (r
&(1<<i
) && !tas3004_mixer_is_stereo(self
,i
))
387 tas3004_get_mixer_level(struct tas3004_data_t
*self
, int mixer
, uint
*level
)
392 *level
= self
->super
.mixer
[mixer
];
398 tas3004_set_mixer_level(struct tas3004_data_t
*self
, int mixer
, uint level
)
401 tas_shadow_t
*shadow
;
408 shadow
= self
->super
.shadow
;
410 if (!tas3004_mixer_is_stereo(self
,mixer
))
411 level
= tas_mono_to_stereo(level
);
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
);
420 case SOUND_MIXER_IMIX
:
422 case SOUND_MIXER_ALTPCM
:
424 case SOUND_MIXER_PCM
:
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.
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
);
437 rc
=tas3004_sync_register(self
,TAS3004_REG_RIGHT_MIXER
);
438 /* tas3004_fast_load(self,0); */
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
);
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
);
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
);
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
);
466 case SOUND_MIXER_LINE
:
467 if (self
->super
.mixer
[SOUND_MIXER_MIC
] == 0) {
468 software_input_volume
= SW_INPUT_VOLUME_SCALE
* (level
&0xff);
478 self
->super
.mixer
[mixer
] = level
;
484 tas3004_leave_sleep(struct tas3004_data_t
*self
)
486 unsigned char mcr
= (1<<6)+(2<<4)+(2<<2);
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)
496 tas3004_fast_load(self
, 1);
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
);
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
);
514 tas3004_fast_load(self
, 0);
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
);
527 tas3004_enter_sleep(struct tas3004_data_t
*self
)
535 tas3004_sync_biquad( struct tas3004_data_t
*self
,
539 enum tas3004_reg_t reg
;
541 if (channel
>= TAS3004_BIQUAD_CHANNEL_COUNT
||
542 filter
>= TAS3004_BIQUAD_FILTER_COUNT
) return -EINVAL
;
544 reg
=( channel
? TAS3004_REG_RIGHT_BIQUAD0
: TAS3004_REG_LEFT_BIQUAD0
) + filter
;
546 return tas3004_sync_register(self
,reg
);
550 tas3004_write_biquad_shadow( struct tas3004_data_t
*self
,
553 const union tas_biquad_t
*biquad
)
555 tas_shadow_t
*shadow
=self
->super
.shadow
;
556 enum tas3004_reg_t reg
;
558 if (channel
>= TAS3004_BIQUAD_CHANNEL_COUNT
||
559 filter
>= TAS3004_BIQUAD_FILTER_COUNT
) return -EINVAL
;
561 reg
=( channel
? TAS3004_REG_RIGHT_BIQUAD0
: TAS3004_REG_LEFT_BIQUAD0
) + filter
;
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
);
573 tas3004_write_biquad( struct tas3004_data_t
*self
,
576 const union tas_biquad_t
*biquad
)
580 rc
=tas3004_write_biquad_shadow(self
, channel
, filter
, biquad
);
581 if (rc
< 0) return rc
;
583 return tas3004_sync_biquad(self
, channel
, filter
);
587 tas3004_write_biquad_list( struct tas3004_data_t
*self
,
590 struct tas_biquad_ctrl_t
*biquads
)
595 if (flags
& TAS_BIQUAD_FAST_LOAD
) tas3004_fast_load(self
,1);
597 for (i
=0; i
<filter_count
; i
++) {
598 rc
=tas3004_write_biquad(self
,
605 if (flags
& TAS_BIQUAD_FAST_LOAD
) tas3004_fast_load(self
,0);
611 tas3004_read_biquad( struct tas3004_data_t
*self
,
614 union tas_biquad_t
*biquad
)
616 tas_shadow_t
*shadow
=self
->super
.shadow
;
617 enum tas3004_reg_t reg
;
619 if (channel
>= TAS3004_BIQUAD_CHANNEL_COUNT
||
620 filter
>= TAS3004_BIQUAD_FILTER_COUNT
) return -EINVAL
;
622 reg
=( channel
? TAS3004_REG_RIGHT_BIQUAD0
: TAS3004_REG_LEFT_BIQUAD0
) + filter
;
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);
634 tas3004_eq_rw( struct tas3004_data_t
*self
,
638 void __user
*argp
= (void __user
*)arg
;
640 struct tas_biquad_ctrl_t biquad
;
642 if (copy_from_user((void *)&biquad
, argp
, sizeof(struct tas_biquad_ctrl_t
))) {
647 rc
=tas3004_write_biquad(self
, biquad
.channel
, biquad
.filter
, &biquad
.data
);
648 if (rc
!= 0) return rc
;
651 if (cmd
& SIOC_OUT
) {
652 rc
=tas3004_read_biquad(self
, biquad
.channel
, biquad
.filter
, &biquad
.data
);
653 if (rc
!= 0) return rc
;
655 if (copy_to_user(argp
, &biquad
, sizeof(struct tas_biquad_ctrl_t
))) {
664 tas3004_eq_list_rw( struct tas3004_data_t
*self
,
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
;
676 memset(sync_required
,0,sizeof(sync_required
));
678 if (copy_from_user(&filter_count
, &argp
->filter_count
, sizeof(int)))
681 if (copy_from_user(&flags
, &argp
->flags
, sizeof(int)))
687 for (i
=0; i
< filter_count
; i
++) {
688 if (copy_from_user(&biquad
, &argp
->biquads
[i
],
689 sizeof(struct tas_biquad_ctrl_t
))) {
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
;
699 if (cmd
& SIOC_OUT
) {
700 rc
=tas3004_read_biquad(self
, biquad
.channel
, biquad
.filter
, &biquad
.data
);
701 if (rc
!= 0) return rc
;
703 if (copy_to_user(&argp
->biquads
[i
], &biquad
,
704 sizeof(struct tas_biquad_ctrl_t
))) {
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.
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
;
727 if (flags
& TAS_BIQUAD_FAST_LOAD
)
728 tas3004_fast_load(self
,0);
735 tas3004_update_drce( struct tas3004_data_t
*self
,
737 struct tas_drce_t
*drce
)
739 tas_shadow_t
*shadow
;
741 shadow
=self
->super
.shadow
;
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;
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);
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);
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;
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);
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);
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
);
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);
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);
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);
800 if (flags
& TAS_DRCE_ENABLE
) {
801 self
->drce_state
.enable
= drce
->enable
;
804 if (!self
->drce_state
.enable
) {
805 shadow
[TAS3004_REG_DRC
][0] |= 0x01;
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
);
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]);
827 return tas3004_sync_register(self
, TAS3004_REG_DRC
);
831 tas3004_drce_rw( struct tas3004_data_t
*self
,
836 struct tas_drce_ctrl_t drce_ctrl
;
837 void __user
*argp
= (void __user
*)arg
;
839 if (copy_from_user(&drce_ctrl
, argp
, sizeof(struct tas_drce_ctrl_t
)))
843 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
.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
);
855 rc
= tas3004_update_drce(self
, drce_ctrl
.flags
, &drce_ctrl
.data
);
856 if (rc
< 0) return rc
;
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
;
875 if (copy_to_user(argp
, &drce_ctrl
,
876 sizeof(struct tas_drce_ctrl_t
))) {
885 tas3004_update_device_parameters(struct tas3004_data_t
*self
)
892 if (self
->output_id
== TAS_OUTPUT_HEADPHONES
) {
893 /* turn on allPass when headphones are plugged in */
899 tas3004_write_register(self
, TAS3004_REG_MCR2
, &data
, WRITE_NORMAL
| FORCE_WRITE
);
901 for (i
=0; tas3004_eq_prefs
[i
]; i
++) {
902 struct tas_eq_pref_t
*eq
= tas3004_eq_prefs
[i
];
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
)) {
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
);
917 tas3004_device_change_handler(void *self
)
921 tas3004_update_device_parameters((struct tas3004_data_t
*)self
);
924 static struct work_struct device_change
;
927 tas3004_output_device_change( struct tas3004_data_t
*self
,
932 self
->device_id
=device_id
;
933 self
->output_id
=output_id
;
934 self
->speaker_id
=speaker_id
;
936 schedule_work(&device_change
);
942 tas3004_device_ioctl( struct tas3004_data_t
*self
,
946 uint __user
*argp
= (void __user
*)arg
;
950 return tas3004_eq_rw(self
, cmd
, arg
);
952 case TAS_READ_EQ_LIST
:
953 case TAS_WRITE_EQ_LIST
:
954 return tas3004_eq_list_rw(self
, cmd
, arg
);
956 case TAS_READ_EQ_FILTER_COUNT
:
957 put_user(TAS3004_BIQUAD_FILTER_COUNT
, argp
);
960 case TAS_READ_EQ_CHANNEL_COUNT
:
961 put_user(TAS3004_BIQUAD_CHANNEL_COUNT
, argp
);
966 return tas3004_drce_rw(self
, cmd
, arg
);
968 case TAS_READ_DRCE_CAPS
:
969 put_user(TAS_DRCE_ENABLE
|
970 TAS_DRCE_ABOVE_RATIO
|
971 TAS_DRCE_BELOW_RATIO
|
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
;
984 if (copy_from_user(&drce_ctrl
, argp
,
985 sizeof(struct tas_drce_ctrl_t
))) {
989 if (cmd
== TAS_READ_DRCE_MIN
) {
990 drce_copy
=&tas3004_drce_min
;
992 drce_copy
=&tas3004_drce_max
;
995 if (drce_ctrl
.flags
& TAS_DRCE_ABOVE_RATIO
) {
996 drce_ctrl
.data
.above
=drce_copy
->above
;
998 if (drce_ctrl
.flags
& TAS_DRCE_BELOW_RATIO
) {
999 drce_ctrl
.data
.below
=drce_copy
->below
;
1001 if (drce_ctrl
.flags
& TAS_DRCE_THRESHOLD
) {
1002 drce_ctrl
.data
.threshold
=drce_copy
->threshold
;
1004 if (drce_ctrl
.flags
& TAS_DRCE_ENERGY
) {
1005 drce_ctrl
.data
.energy
=drce_copy
->energy
;
1007 if (drce_ctrl
.flags
& TAS_DRCE_ATTACK
) {
1008 drce_ctrl
.data
.attack
=drce_copy
->attack
;
1010 if (drce_ctrl
.flags
& TAS_DRCE_DECAY
) {
1011 drce_ctrl
.data
.decay
=drce_copy
->decay
;
1014 if (copy_to_user(argp
, &drce_ctrl
,
1015 sizeof(struct tas_drce_ctrl_t
))) {
1025 tas3004_init_mixer(struct tas3004_data_t
*self
)
1027 unsigned char mcr
= (1<<6)+(2<<4)+(2<<2);
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)
1034 tas3004_fast_load(self
, 1);
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
);
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
);
1052 tas3004_sync_register(self
, TAS3004_REG_DRC
);
1054 tas3004_sync_register(self
, TAS3004_REG_MCR2
);
1056 tas3004_fast_load(self
, 0);
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);
1063 tas3004_set_mixer_level(self
, SOUND_MIXER_BASS
, BASS_DEFAULT
);
1064 tas3004_set_mixer_level(self
, SOUND_MIXER_TREBLE
, TREBLE_DEFAULT
);
1066 tas3004_set_mixer_level(self
, SOUND_MIXER_LINE
,SW_INPUT_VOLUME_DEFAULT
);
1072 tas3004_uninit_mixer(struct tas3004_data_t
*self
)
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);
1079 tas3004_set_mixer_level(self
, SOUND_MIXER_BASS
, 0);
1080 tas3004_set_mixer_level(self
, SOUND_MIXER_TREBLE
, 0);
1082 tas3004_set_mixer_level(self
, SOUND_MIXER_LINE
, 0);
1088 tas3004_init(struct i2c_client
*client
)
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 };
1096 self
= kmalloc(sz
, GFP_KERNEL
);
1099 memset(self
, 0, sz
);
1101 self
->super
.client
= client
;
1102 self
->super
.shadow
= (tas_shadow_t
*)(self
+1);
1103 self
->output_id
= TAS_OUTPUT_HEADPHONES
;
1105 dev_set_drvdata(&client
->dev
, self
);
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
,
1112 tas3004_write_register(self
, TAS3004_REG_MCR2
, &mcr2
, WRITE_SHADOW
);
1113 tas3004_write_register(self
, TAS3004_REG_DRC
, drce_init
, WRITE_SHADOW
);
1115 INIT_WORK(&device_change
, tas3004_device_change_handler
, self
);
1120 tas3004_uninit(struct tas3004_data_t
*self
)
1122 tas3004_uninit_mixer(self
);
1127 struct tas_driver_hooks_t tas3004_hooks
= {
1128 .init
= (tas_hook_init_t
)tas3004_init
,
1129 .post_init
= (tas_hook_post_init_t
)tas3004_init_mixer
,
1130 .uninit
= (tas_hook_uninit_t
)tas3004_uninit
,
1131 .get_mixer_level
= (tas_hook_get_mixer_level_t
)tas3004_get_mixer_level
,
1132 .set_mixer_level
= (tas_hook_set_mixer_level_t
)tas3004_set_mixer_level
,
1133 .enter_sleep
= (tas_hook_enter_sleep_t
)tas3004_enter_sleep
,
1134 .leave_sleep
= (tas_hook_leave_sleep_t
)tas3004_leave_sleep
,
1135 .supported_mixers
= (tas_hook_supported_mixers_t
)tas3004_supported_mixers
,
1136 .mixer_is_stereo
= (tas_hook_mixer_is_stereo_t
)tas3004_mixer_is_stereo
,
1137 .stereo_mixers
= (tas_hook_stereo_mixers_t
)tas3004_stereo_mixers
,
1138 .output_device_change
= (tas_hook_output_device_change_t
)tas3004_output_device_change
,
1139 .device_ioctl
= (tas_hook_device_ioctl_t
)tas3004_device_ioctl