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
;
51 struct work_struct change
;
54 #define MAKE_TIME(sec,usec) (((sec)<<12) + (50000+(usec/10)*(1<<12))/100000)
56 #define MAKE_RATIO(i,f) (((i)<<8) + ((500+(f)*(1<<8))/1000))
59 static const union tas_biquad_t tas3004_eq_unity
= {
60 .buf
= { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 },
64 static const struct tas_drce_t tas3004_drce_min
= {
66 .above
= { .val
= MAKE_RATIO(16,0), .expand
= 0 },
67 .below
= { .val
= MAKE_RATIO(2,0), .expand
= 0 },
69 .energy
= MAKE_TIME(0, 1700),
70 .attack
= MAKE_TIME(0, 1700),
71 .decay
= MAKE_TIME(0, 1700),
75 static const struct tas_drce_t tas3004_drce_max
= {
77 .above
= { .val
= MAKE_RATIO(1,500), .expand
= 1 },
78 .below
= { .val
= MAKE_RATIO(2,0), .expand
= 1 },
80 .energy
= MAKE_TIME(2,400000),
81 .attack
= MAKE_TIME(2,400000),
82 .decay
= MAKE_TIME(2,400000),
86 static const unsigned short time_constants
[]={
101 static const unsigned short above_threshold_compression_ratio
[]={
119 static const unsigned short above_threshold_expansion_ratio
[]={
130 static const unsigned short below_threshold_compression_ratio
[]={
141 static const unsigned short below_threshold_expansion_ratio
[]={
161 search( unsigned short val
,
162 const unsigned short *arr
,
165 * This could be a binary search, but for small tables,
166 * a linear search is likely to be faster
171 for (i
=0; i
< arrsize
; i
++)
178 return (arr
[i
]-val
< val
-arr
[i
-1]) ? i
: i
-1;
181 #define SEARCH(a, b) search(a, b, ARRAY_SIZE(b))
184 time_index(unsigned short time
)
186 return SEARCH(time
, time_constants
);
191 above_threshold_compression_index(unsigned short ratio
)
193 return SEARCH(ratio
, above_threshold_compression_ratio
);
198 above_threshold_expansion_index(unsigned short ratio
)
200 return SEARCH(ratio
, above_threshold_expansion_ratio
);
205 below_threshold_compression_index(unsigned short ratio
)
207 return SEARCH(ratio
, below_threshold_compression_ratio
);
212 below_threshold_expansion_index(unsigned short ratio
)
214 return SEARCH(ratio
, below_threshold_expansion_ratio
);
217 static inline unsigned char db_to_regval(short db
) {
220 r
=(db
+0x59a0) / 0x60;
222 if (r
< 0x91) return 0x91;
223 if (r
> 0xef) return 0xef;
227 static inline short quantize_db(short db
)
229 return db_to_regval(db
) * 0x60 - 0x59a0;
233 register_width(enum tas3004_reg_t 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
:
245 case TAS3004_REG_LEFT_LOUD_BIQUAD_GAIN
:
246 case TAS3004_REG_RIGHT_LOUD_BIQUAD_GAIN
:
249 case TAS3004_REG_DRC
:
250 case TAS3004_REG_VOLUME
:
253 case TAS3004_REG_LEFT_MIXER
:
254 case TAS3004_REG_RIGHT_MIXER
:
257 case TAS3004_REG_TEST
:
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
:
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
:
276 case TAS3004_REG_LEFT_LOUD_BIQUAD
:
277 case TAS3004_REG_RIGHT_LOUD_BIQUAD
:
286 tas3004_write_register( struct tas3004_data_t
*self
,
287 enum tas3004_reg_t reg_num
,
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
,
300 return tas_write_register(&self
->super
,
302 register_width(reg_num
),
309 tas3004_sync_register( struct tas3004_data_t
*self
,
310 enum tas3004_reg_t reg_num
)
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
,
318 register_width(reg_num
));
320 return tas_sync_register(&self
->super
,
322 register_width(reg_num
));
327 tas3004_read_register( struct tas3004_data_t
*self
,
328 enum tas3004_reg_t reg_num
,
332 return tas_read_register(&self
->super
,
334 register_width(reg_num
),
339 tas3004_fast_load(struct tas3004_data_t
*self
, int fast
)
342 self
->super
.shadow
[TAS3004_REG_MCR
][0] |= 0x80;
344 self
->super
.shadow
[TAS3004_REG_MCR
][0] &= 0x7f;
345 return tas3004_sync_register(self
,TAS3004_REG_MCR
);
349 tas3004_supported_mixers(struct tas3004_data_t
*self
)
351 return SOUND_MASK_VOLUME
|
362 tas3004_mixer_is_stereo(struct tas3004_data_t
*self
, int mixer
)
365 case SOUND_MIXER_VOLUME
:
366 case SOUND_MIXER_PCM
:
367 case SOUND_MIXER_ALTPCM
:
368 case SOUND_MIXER_IMIX
:
376 tas3004_stereo_mixers(struct tas3004_data_t
*self
)
378 uint r
= tas3004_supported_mixers(self
);
381 for (i
=1; i
<SOUND_MIXER_NRDEVICES
; i
++)
382 if (r
&(1<<i
) && !tas3004_mixer_is_stereo(self
,i
))
388 tas3004_get_mixer_level(struct tas3004_data_t
*self
, int mixer
, uint
*level
)
393 *level
= self
->super
.mixer
[mixer
];
399 tas3004_set_mixer_level(struct tas3004_data_t
*self
, int mixer
, uint level
)
402 tas_shadow_t
*shadow
;
409 shadow
= self
->super
.shadow
;
411 if (!tas3004_mixer_is_stereo(self
,mixer
))
412 level
= tas_mono_to_stereo(level
);
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
);
421 case SOUND_MIXER_IMIX
:
423 case SOUND_MIXER_ALTPCM
:
425 case SOUND_MIXER_PCM
:
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.
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
);
438 rc
=tas3004_sync_register(self
,TAS3004_REG_RIGHT_MIXER
);
439 /* tas3004_fast_load(self,0); */
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
);
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
);
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
);
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
);
467 case SOUND_MIXER_LINE
:
468 if (self
->super
.mixer
[SOUND_MIXER_MIC
] == 0) {
469 software_input_volume
= SW_INPUT_VOLUME_SCALE
* (level
&0xff);
479 self
->super
.mixer
[mixer
] = level
;
485 tas3004_leave_sleep(struct tas3004_data_t
*self
)
487 unsigned char mcr
= (1<<6)+(2<<4)+(2<<2);
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)
497 tas3004_fast_load(self
, 1);
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
);
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
);
515 tas3004_fast_load(self
, 0);
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
);
528 tas3004_enter_sleep(struct tas3004_data_t
*self
)
536 tas3004_sync_biquad( struct tas3004_data_t
*self
,
540 enum tas3004_reg_t reg
;
542 if (channel
>= TAS3004_BIQUAD_CHANNEL_COUNT
||
543 filter
>= TAS3004_BIQUAD_FILTER_COUNT
) return -EINVAL
;
545 reg
=( channel
? TAS3004_REG_RIGHT_BIQUAD0
: TAS3004_REG_LEFT_BIQUAD0
) + filter
;
547 return tas3004_sync_register(self
,reg
);
551 tas3004_write_biquad_shadow( struct tas3004_data_t
*self
,
554 const union tas_biquad_t
*biquad
)
556 tas_shadow_t
*shadow
=self
->super
.shadow
;
557 enum tas3004_reg_t reg
;
559 if (channel
>= TAS3004_BIQUAD_CHANNEL_COUNT
||
560 filter
>= TAS3004_BIQUAD_FILTER_COUNT
) return -EINVAL
;
562 reg
=( channel
? TAS3004_REG_RIGHT_BIQUAD0
: TAS3004_REG_LEFT_BIQUAD0
) + filter
;
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
);
574 tas3004_write_biquad( struct tas3004_data_t
*self
,
577 const union tas_biquad_t
*biquad
)
581 rc
=tas3004_write_biquad_shadow(self
, channel
, filter
, biquad
);
582 if (rc
< 0) return rc
;
584 return tas3004_sync_biquad(self
, channel
, filter
);
588 tas3004_write_biquad_list( struct tas3004_data_t
*self
,
591 struct tas_biquad_ctrl_t
*biquads
)
596 if (flags
& TAS_BIQUAD_FAST_LOAD
) tas3004_fast_load(self
,1);
598 for (i
=0; i
<filter_count
; i
++) {
599 rc
=tas3004_write_biquad(self
,
606 if (flags
& TAS_BIQUAD_FAST_LOAD
) tas3004_fast_load(self
,0);
612 tas3004_read_biquad( struct tas3004_data_t
*self
,
615 union tas_biquad_t
*biquad
)
617 tas_shadow_t
*shadow
=self
->super
.shadow
;
618 enum tas3004_reg_t reg
;
620 if (channel
>= TAS3004_BIQUAD_CHANNEL_COUNT
||
621 filter
>= TAS3004_BIQUAD_FILTER_COUNT
) return -EINVAL
;
623 reg
=( channel
? TAS3004_REG_RIGHT_BIQUAD0
: TAS3004_REG_LEFT_BIQUAD0
) + filter
;
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);
635 tas3004_eq_rw( struct tas3004_data_t
*self
,
639 void __user
*argp
= (void __user
*)arg
;
641 struct tas_biquad_ctrl_t biquad
;
643 if (copy_from_user((void *)&biquad
, argp
, sizeof(struct tas_biquad_ctrl_t
))) {
648 rc
=tas3004_write_biquad(self
, biquad
.channel
, biquad
.filter
, &biquad
.data
);
649 if (rc
!= 0) return rc
;
652 if (cmd
& SIOC_OUT
) {
653 rc
=tas3004_read_biquad(self
, biquad
.channel
, biquad
.filter
, &biquad
.data
);
654 if (rc
!= 0) return rc
;
656 if (copy_to_user(argp
, &biquad
, sizeof(struct tas_biquad_ctrl_t
))) {
665 tas3004_eq_list_rw( struct tas3004_data_t
*self
,
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
;
677 memset(sync_required
,0,sizeof(sync_required
));
679 if (copy_from_user(&filter_count
, &argp
->filter_count
, sizeof(int)))
682 if (copy_from_user(&flags
, &argp
->flags
, sizeof(int)))
688 for (i
=0; i
< filter_count
; i
++) {
689 if (copy_from_user(&biquad
, &argp
->biquads
[i
],
690 sizeof(struct tas_biquad_ctrl_t
))) {
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
;
700 if (cmd
& SIOC_OUT
) {
701 rc
=tas3004_read_biquad(self
, biquad
.channel
, biquad
.filter
, &biquad
.data
);
702 if (rc
!= 0) return rc
;
704 if (copy_to_user(&argp
->biquads
[i
], &biquad
,
705 sizeof(struct tas_biquad_ctrl_t
))) {
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.
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
;
728 if (flags
& TAS_BIQUAD_FAST_LOAD
)
729 tas3004_fast_load(self
,0);
736 tas3004_update_drce( struct tas3004_data_t
*self
,
738 struct tas_drce_t
*drce
)
740 tas_shadow_t
*shadow
;
742 shadow
=self
->super
.shadow
;
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;
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);
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);
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;
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);
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);
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
);
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);
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);
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);
801 if (flags
& TAS_DRCE_ENABLE
) {
802 self
->drce_state
.enable
= drce
->enable
;
805 if (!self
->drce_state
.enable
) {
806 shadow
[TAS3004_REG_DRC
][0] |= 0x01;
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
);
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]);
828 return tas3004_sync_register(self
, TAS3004_REG_DRC
);
832 tas3004_drce_rw( struct tas3004_data_t
*self
,
837 struct tas_drce_ctrl_t drce_ctrl
;
838 void __user
*argp
= (void __user
*)arg
;
840 if (copy_from_user(&drce_ctrl
, argp
, sizeof(struct tas_drce_ctrl_t
)))
844 printk("DRCE: input [ FLAGS:%x ENABLE:%x ABOVE:%x/%x BELOW:%x/%x THRESH:%x ENERGY:%x ATTACK:%x DECAY:%x\n",
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
);
856 rc
= tas3004_update_drce(self
, drce_ctrl
.flags
, &drce_ctrl
.data
);
857 if (rc
< 0) return rc
;
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
;
876 if (copy_to_user(argp
, &drce_ctrl
,
877 sizeof(struct tas_drce_ctrl_t
))) {
886 tas3004_update_device_parameters(struct tas3004_data_t
*self
)
893 if (self
->output_id
== TAS_OUTPUT_HEADPHONES
) {
894 /* turn on allPass when headphones are plugged in */
900 tas3004_write_register(self
, TAS3004_REG_MCR2
, &data
, WRITE_NORMAL
| FORCE_WRITE
);
902 for (i
=0; tas3004_eq_prefs
[i
]; i
++) {
903 struct tas_eq_pref_t
*eq
= tas3004_eq_prefs
[i
];
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
)) {
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
);
918 tas3004_device_change_handler(struct work_struct
*work
)
920 struct tas3004_data_t
*self
;
921 self
= container_of(work
, struct tas3004_data_t
, change
);
922 tas3004_update_device_parameters(self
);
926 tas3004_output_device_change( struct tas3004_data_t
*self
,
931 self
->device_id
=device_id
;
932 self
->output_id
=output_id
;
933 self
->speaker_id
=speaker_id
;
935 schedule_work(&self
->change
);
941 tas3004_device_ioctl( struct tas3004_data_t
*self
,
945 uint __user
*argp
= (void __user
*)arg
;
949 return tas3004_eq_rw(self
, cmd
, arg
);
951 case TAS_READ_EQ_LIST
:
952 case TAS_WRITE_EQ_LIST
:
953 return tas3004_eq_list_rw(self
, cmd
, arg
);
955 case TAS_READ_EQ_FILTER_COUNT
:
956 put_user(TAS3004_BIQUAD_FILTER_COUNT
, argp
);
959 case TAS_READ_EQ_CHANNEL_COUNT
:
960 put_user(TAS3004_BIQUAD_CHANNEL_COUNT
, argp
);
965 return tas3004_drce_rw(self
, cmd
, arg
);
967 case TAS_READ_DRCE_CAPS
:
968 put_user(TAS_DRCE_ENABLE
|
969 TAS_DRCE_ABOVE_RATIO
|
970 TAS_DRCE_BELOW_RATIO
|
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
;
983 if (copy_from_user(&drce_ctrl
, argp
,
984 sizeof(struct tas_drce_ctrl_t
))) {
988 if (cmd
== TAS_READ_DRCE_MIN
) {
989 drce_copy
=&tas3004_drce_min
;
991 drce_copy
=&tas3004_drce_max
;
994 if (drce_ctrl
.flags
& TAS_DRCE_ABOVE_RATIO
) {
995 drce_ctrl
.data
.above
=drce_copy
->above
;
997 if (drce_ctrl
.flags
& TAS_DRCE_BELOW_RATIO
) {
998 drce_ctrl
.data
.below
=drce_copy
->below
;
1000 if (drce_ctrl
.flags
& TAS_DRCE_THRESHOLD
) {
1001 drce_ctrl
.data
.threshold
=drce_copy
->threshold
;
1003 if (drce_ctrl
.flags
& TAS_DRCE_ENERGY
) {
1004 drce_ctrl
.data
.energy
=drce_copy
->energy
;
1006 if (drce_ctrl
.flags
& TAS_DRCE_ATTACK
) {
1007 drce_ctrl
.data
.attack
=drce_copy
->attack
;
1009 if (drce_ctrl
.flags
& TAS_DRCE_DECAY
) {
1010 drce_ctrl
.data
.decay
=drce_copy
->decay
;
1013 if (copy_to_user(argp
, &drce_ctrl
,
1014 sizeof(struct tas_drce_ctrl_t
))) {
1024 tas3004_init_mixer(struct tas3004_data_t
*self
)
1026 unsigned char mcr
= (1<<6)+(2<<4)+(2<<2);
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)
1033 tas3004_fast_load(self
, 1);
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
);
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
);
1051 tas3004_sync_register(self
, TAS3004_REG_DRC
);
1053 tas3004_sync_register(self
, TAS3004_REG_MCR2
);
1055 tas3004_fast_load(self
, 0);
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);
1062 tas3004_set_mixer_level(self
, SOUND_MIXER_BASS
, BASS_DEFAULT
);
1063 tas3004_set_mixer_level(self
, SOUND_MIXER_TREBLE
, TREBLE_DEFAULT
);
1065 tas3004_set_mixer_level(self
, SOUND_MIXER_LINE
,SW_INPUT_VOLUME_DEFAULT
);
1071 tas3004_uninit_mixer(struct tas3004_data_t
*self
)
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);
1078 tas3004_set_mixer_level(self
, SOUND_MIXER_BASS
, 0);
1079 tas3004_set_mixer_level(self
, SOUND_MIXER_TREBLE
, 0);
1081 tas3004_set_mixer_level(self
, SOUND_MIXER_LINE
, 0);
1087 tas3004_init(struct i2c_client
*client
)
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 };
1095 self
= kzalloc(sz
, GFP_KERNEL
);
1099 self
->super
.client
= client
;
1100 self
->super
.shadow
= (tas_shadow_t
*)(self
+1);
1101 self
->output_id
= TAS_OUTPUT_HEADPHONES
;
1103 dev_set_drvdata(&client
->dev
, self
);
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
,
1110 tas3004_write_register(self
, TAS3004_REG_MCR2
, &mcr2
, WRITE_SHADOW
);
1111 tas3004_write_register(self
, TAS3004_REG_DRC
, drce_init
, WRITE_SHADOW
);
1113 INIT_WORK(&self
->change
, tas3004_device_change_handler
);
1118 tas3004_uninit(struct tas3004_data_t
*self
)
1120 tas3004_uninit_mixer(self
);
1125 struct 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