diff options
Diffstat (limited to 'sound/aoa/codecs/snd-aoa-codec-tas.c')
-rw-r--r-- | sound/aoa/codecs/snd-aoa-codec-tas.c | 331 |
1 files changed, 306 insertions, 25 deletions
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c index 2e39ff6ee349..16c0b6b0a805 100644 --- a/sound/aoa/codecs/snd-aoa-codec-tas.c +++ b/sound/aoa/codecs/snd-aoa-codec-tas.c | |||
@@ -72,22 +72,29 @@ MODULE_DESCRIPTION("tas codec driver for snd-aoa"); | |||
72 | 72 | ||
73 | #include "snd-aoa-codec-tas.h" | 73 | #include "snd-aoa-codec-tas.h" |
74 | #include "snd-aoa-codec-tas-gain-table.h" | 74 | #include "snd-aoa-codec-tas-gain-table.h" |
75 | #include "snd-aoa-codec-tas-basstreble.h" | ||
75 | #include "../aoa.h" | 76 | #include "../aoa.h" |
76 | #include "../soundbus/soundbus.h" | 77 | #include "../soundbus/soundbus.h" |
77 | 78 | ||
78 | |||
79 | #define PFX "snd-aoa-codec-tas: " | 79 | #define PFX "snd-aoa-codec-tas: " |
80 | 80 | ||
81 | |||
81 | struct tas { | 82 | struct tas { |
82 | struct aoa_codec codec; | 83 | struct aoa_codec codec; |
83 | struct i2c_client i2c; | 84 | struct i2c_client i2c; |
84 | u32 muted_l:1, muted_r:1, | 85 | u32 mute_l:1, mute_r:1 , |
85 | controls_created:1; | 86 | controls_created:1 , |
87 | drc_enabled:1, | ||
88 | hw_enabled:1; | ||
86 | u8 cached_volume_l, cached_volume_r; | 89 | u8 cached_volume_l, cached_volume_r; |
87 | u8 mixer_l[3], mixer_r[3]; | 90 | u8 mixer_l[3], mixer_r[3]; |
91 | u8 bass, treble; | ||
88 | u8 acr; | 92 | u8 acr; |
93 | int drc_range; | ||
89 | }; | 94 | }; |
90 | 95 | ||
96 | static int tas_reset_init(struct tas *tas); | ||
97 | |||
91 | static struct tas *codec_to_tas(struct aoa_codec *codec) | 98 | static struct tas *codec_to_tas(struct aoa_codec *codec) |
92 | { | 99 | { |
93 | return container_of(codec, struct tas, codec); | 100 | return container_of(codec, struct tas, codec); |
@@ -101,6 +108,44 @@ static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data) | |||
101 | return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data); | 108 | return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data); |
102 | } | 109 | } |
103 | 110 | ||
111 | static void tas3004_set_drc(struct tas *tas) | ||
112 | { | ||
113 | unsigned char val[6]; | ||
114 | |||
115 | if (tas->drc_enabled) | ||
116 | val[0] = 0x50; /* 3:1 above threshold */ | ||
117 | else | ||
118 | val[0] = 0x51; /* disabled */ | ||
119 | val[1] = 0x02; /* 1:1 below threshold */ | ||
120 | if (tas->drc_range > 0xef) | ||
121 | val[2] = 0xef; | ||
122 | else if (tas->drc_range < 0) | ||
123 | val[2] = 0x00; | ||
124 | else | ||
125 | val[2] = tas->drc_range; | ||
126 | val[3] = 0xb0; | ||
127 | val[4] = 0x60; | ||
128 | val[5] = 0xa0; | ||
129 | |||
130 | tas_write_reg(tas, TAS_REG_DRC, 6, val); | ||
131 | } | ||
132 | |||
133 | static void tas_set_treble(struct tas *tas) | ||
134 | { | ||
135 | u8 tmp; | ||
136 | |||
137 | tmp = tas3004_treble(tas->treble); | ||
138 | tas_write_reg(tas, TAS_REG_TREBLE, 1, &tmp); | ||
139 | } | ||
140 | |||
141 | static void tas_set_bass(struct tas *tas) | ||
142 | { | ||
143 | u8 tmp; | ||
144 | |||
145 | tmp = tas3004_bass(tas->bass); | ||
146 | tas_write_reg(tas, TAS_REG_BASS, 1, &tmp); | ||
147 | } | ||
148 | |||
104 | static void tas_set_volume(struct tas *tas) | 149 | static void tas_set_volume(struct tas *tas) |
105 | { | 150 | { |
106 | u8 block[6]; | 151 | u8 block[6]; |
@@ -113,8 +158,8 @@ static void tas_set_volume(struct tas *tas) | |||
113 | if (left > 177) left = 177; | 158 | if (left > 177) left = 177; |
114 | if (right > 177) right = 177; | 159 | if (right > 177) right = 177; |
115 | 160 | ||
116 | if (tas->muted_l) left = 0; | 161 | if (tas->mute_l) left = 0; |
117 | if (tas->muted_r) right = 0; | 162 | if (tas->mute_r) right = 0; |
118 | 163 | ||
119 | /* analysing the volume and mixer tables shows | 164 | /* analysing the volume and mixer tables shows |
120 | * that they are similar enough when we shift | 165 | * that they are similar enough when we shift |
@@ -202,7 +247,8 @@ static int tas_snd_vol_put(struct snd_kcontrol *kcontrol, | |||
202 | 247 | ||
203 | tas->cached_volume_l = ucontrol->value.integer.value[0]; | 248 | tas->cached_volume_l = ucontrol->value.integer.value[0]; |
204 | tas->cached_volume_r = ucontrol->value.integer.value[1]; | 249 | tas->cached_volume_r = ucontrol->value.integer.value[1]; |
205 | tas_set_volume(tas); | 250 | if (tas->hw_enabled) |
251 | tas_set_volume(tas); | ||
206 | return 1; | 252 | return 1; |
207 | } | 253 | } |
208 | 254 | ||
@@ -230,8 +276,8 @@ static int tas_snd_mute_get(struct snd_kcontrol *kcontrol, | |||
230 | { | 276 | { |
231 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 277 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
232 | 278 | ||
233 | ucontrol->value.integer.value[0] = !tas->muted_l; | 279 | ucontrol->value.integer.value[0] = !tas->mute_l; |
234 | ucontrol->value.integer.value[1] = !tas->muted_r; | 280 | ucontrol->value.integer.value[1] = !tas->mute_r; |
235 | return 0; | 281 | return 0; |
236 | } | 282 | } |
237 | 283 | ||
@@ -240,13 +286,14 @@ static int tas_snd_mute_put(struct snd_kcontrol *kcontrol, | |||
240 | { | 286 | { |
241 | struct tas *tas = snd_kcontrol_chip(kcontrol); | 287 | struct tas *tas = snd_kcontrol_chip(kcontrol); |
242 | 288 | ||
243 | if (tas->muted_l == !ucontrol->value.integer.value[0] | 289 | if (tas->mute_l == !ucontrol->value.integer.value[0] |
244 | && tas->muted_r == !ucontrol->value.integer.value[1]) | 290 | && tas->mute_r == !ucontrol->value.integer.value[1]) |
245 | return 0; | 291 | return 0; |
246 | 292 | ||
247 | tas->muted_l = !ucontrol->value.integer.value[0]; | 293 | tas->mute_l = !ucontrol->value.integer.value[0]; |
248 | tas->muted_r = !ucontrol->value.integer.value[1]; | 294 | tas->mute_r = !ucontrol->value.integer.value[1]; |
249 | tas_set_volume(tas); | 295 | if (tas->hw_enabled) |
296 | tas_set_volume(tas); | ||
250 | return 1; | 297 | return 1; |
251 | } | 298 | } |
252 | 299 | ||
@@ -294,7 +341,8 @@ static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol, | |||
294 | tas->mixer_l[idx] = ucontrol->value.integer.value[0]; | 341 | tas->mixer_l[idx] = ucontrol->value.integer.value[0]; |
295 | tas->mixer_r[idx] = ucontrol->value.integer.value[1]; | 342 | tas->mixer_r[idx] = ucontrol->value.integer.value[1]; |
296 | 343 | ||
297 | tas_set_mixer(tas); | 344 | if (tas->hw_enabled) |
345 | tas_set_mixer(tas); | ||
298 | return 1; | 346 | return 1; |
299 | } | 347 | } |
300 | 348 | ||
@@ -309,9 +357,93 @@ static struct snd_kcontrol_new n##_control = { \ | |||
309 | .private_value = idx, \ | 357 | .private_value = idx, \ |
310 | } | 358 | } |
311 | 359 | ||
312 | MIXER_CONTROL(pcm1, "PCM1", 0); | 360 | MIXER_CONTROL(pcm1, "PCM", 0); |
313 | MIXER_CONTROL(monitor, "Monitor", 2); | 361 | MIXER_CONTROL(monitor, "Monitor", 2); |
314 | 362 | ||
363 | static int tas_snd_drc_range_info(struct snd_kcontrol *kcontrol, | ||
364 | struct snd_ctl_elem_info *uinfo) | ||
365 | { | ||
366 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
367 | uinfo->count = 1; | ||
368 | uinfo->value.integer.min = 0; | ||
369 | uinfo->value.integer.max = TAS3004_DRC_MAX; | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int tas_snd_drc_range_get(struct snd_kcontrol *kcontrol, | ||
374 | struct snd_ctl_elem_value *ucontrol) | ||
375 | { | ||
376 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
377 | |||
378 | ucontrol->value.integer.value[0] = tas->drc_range; | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol, | ||
383 | struct snd_ctl_elem_value *ucontrol) | ||
384 | { | ||
385 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
386 | |||
387 | if (tas->drc_range == ucontrol->value.integer.value[0]) | ||
388 | return 0; | ||
389 | |||
390 | tas->drc_range = ucontrol->value.integer.value[0]; | ||
391 | if (tas->hw_enabled) | ||
392 | tas3004_set_drc(tas); | ||
393 | return 1; | ||
394 | } | ||
395 | |||
396 | static struct snd_kcontrol_new drc_range_control = { | ||
397 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
398 | .name = "DRC Range", | ||
399 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
400 | .info = tas_snd_drc_range_info, | ||
401 | .get = tas_snd_drc_range_get, | ||
402 | .put = tas_snd_drc_range_put, | ||
403 | }; | ||
404 | |||
405 | static int tas_snd_drc_switch_info(struct snd_kcontrol *kcontrol, | ||
406 | struct snd_ctl_elem_info *uinfo) | ||
407 | { | ||
408 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
409 | uinfo->count = 1; | ||
410 | uinfo->value.integer.min = 0; | ||
411 | uinfo->value.integer.max = 1; | ||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol, | ||
416 | struct snd_ctl_elem_value *ucontrol) | ||
417 | { | ||
418 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
419 | |||
420 | ucontrol->value.integer.value[0] = tas->drc_enabled; | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol, | ||
425 | struct snd_ctl_elem_value *ucontrol) | ||
426 | { | ||
427 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
428 | |||
429 | if (tas->drc_enabled == ucontrol->value.integer.value[0]) | ||
430 | return 0; | ||
431 | |||
432 | tas->drc_enabled = ucontrol->value.integer.value[0]; | ||
433 | if (tas->hw_enabled) | ||
434 | tas3004_set_drc(tas); | ||
435 | return 1; | ||
436 | } | ||
437 | |||
438 | static struct snd_kcontrol_new drc_switch_control = { | ||
439 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
440 | .name = "DRC Range Switch", | ||
441 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
442 | .info = tas_snd_drc_switch_info, | ||
443 | .get = tas_snd_drc_switch_get, | ||
444 | .put = tas_snd_drc_switch_put, | ||
445 | }; | ||
446 | |||
315 | static int tas_snd_capture_source_info(struct snd_kcontrol *kcontrol, | 447 | static int tas_snd_capture_source_info(struct snd_kcontrol *kcontrol, |
316 | struct snd_ctl_elem_info *uinfo) | 448 | struct snd_ctl_elem_info *uinfo) |
317 | { | 449 | { |
@@ -346,7 +478,8 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, | |||
346 | tas->acr |= TAS_ACR_INPUT_B; | 478 | tas->acr |= TAS_ACR_INPUT_B; |
347 | if (oldacr == tas->acr) | 479 | if (oldacr == tas->acr) |
348 | return 0; | 480 | return 0; |
349 | tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); | 481 | if (tas->hw_enabled) |
482 | tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); | ||
350 | return 1; | 483 | return 1; |
351 | } | 484 | } |
352 | 485 | ||
@@ -370,6 +503,89 @@ static struct snd_kcontrol_new capture_source_control = { | |||
370 | .put = tas_snd_capture_source_put, | 503 | .put = tas_snd_capture_source_put, |
371 | }; | 504 | }; |
372 | 505 | ||
506 | static int tas_snd_treble_info(struct snd_kcontrol *kcontrol, | ||
507 | struct snd_ctl_elem_info *uinfo) | ||
508 | { | ||
509 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
510 | uinfo->count = 1; | ||
511 | uinfo->value.integer.min = TAS3004_TREBLE_MIN; | ||
512 | uinfo->value.integer.max = TAS3004_TREBLE_MAX; | ||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | static int tas_snd_treble_get(struct snd_kcontrol *kcontrol, | ||
517 | struct snd_ctl_elem_value *ucontrol) | ||
518 | { | ||
519 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
520 | |||
521 | ucontrol->value.integer.value[0] = tas->treble; | ||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static int tas_snd_treble_put(struct snd_kcontrol *kcontrol, | ||
526 | struct snd_ctl_elem_value *ucontrol) | ||
527 | { | ||
528 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
529 | |||
530 | if (tas->treble == ucontrol->value.integer.value[0]) | ||
531 | return 0; | ||
532 | |||
533 | tas->treble = ucontrol->value.integer.value[0]; | ||
534 | if (tas->hw_enabled) | ||
535 | tas_set_treble(tas); | ||
536 | return 1; | ||
537 | } | ||
538 | |||
539 | static struct snd_kcontrol_new treble_control = { | ||
540 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
541 | .name = "Treble", | ||
542 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
543 | .info = tas_snd_treble_info, | ||
544 | .get = tas_snd_treble_get, | ||
545 | .put = tas_snd_treble_put, | ||
546 | }; | ||
547 | |||
548 | static int tas_snd_bass_info(struct snd_kcontrol *kcontrol, | ||
549 | struct snd_ctl_elem_info *uinfo) | ||
550 | { | ||
551 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
552 | uinfo->count = 1; | ||
553 | uinfo->value.integer.min = TAS3004_BASS_MIN; | ||
554 | uinfo->value.integer.max = TAS3004_BASS_MAX; | ||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | static int tas_snd_bass_get(struct snd_kcontrol *kcontrol, | ||
559 | struct snd_ctl_elem_value *ucontrol) | ||
560 | { | ||
561 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
562 | |||
563 | ucontrol->value.integer.value[0] = tas->bass; | ||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | static int tas_snd_bass_put(struct snd_kcontrol *kcontrol, | ||
568 | struct snd_ctl_elem_value *ucontrol) | ||
569 | { | ||
570 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
571 | |||
572 | if (tas->bass == ucontrol->value.integer.value[0]) | ||
573 | return 0; | ||
574 | |||
575 | tas->bass = ucontrol->value.integer.value[0]; | ||
576 | if (tas->hw_enabled) | ||
577 | tas_set_bass(tas); | ||
578 | return 1; | ||
579 | } | ||
580 | |||
581 | static struct snd_kcontrol_new bass_control = { | ||
582 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
583 | .name = "Bass", | ||
584 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
585 | .info = tas_snd_bass_info, | ||
586 | .get = tas_snd_bass_get, | ||
587 | .put = tas_snd_bass_put, | ||
588 | }; | ||
373 | 589 | ||
374 | static struct transfer_info tas_transfers[] = { | 590 | static struct transfer_info tas_transfers[] = { |
375 | { | 591 | { |
@@ -399,26 +615,67 @@ static int tas_usable(struct codec_info_item *cii, | |||
399 | static int tas_reset_init(struct tas *tas) | 615 | static int tas_reset_init(struct tas *tas) |
400 | { | 616 | { |
401 | u8 tmp; | 617 | u8 tmp; |
618 | |||
619 | tas->codec.gpio->methods->all_amps_off(tas->codec.gpio); | ||
620 | msleep(5); | ||
402 | tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); | 621 | tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); |
403 | msleep(1); | 622 | msleep(5); |
404 | tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1); | 623 | tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1); |
405 | msleep(1); | 624 | msleep(20); |
406 | tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); | 625 | tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); |
407 | msleep(1); | 626 | msleep(10); |
408 | 627 | tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); | |
409 | tas->acr &= ~TAS_ACR_ANALOG_PDOWN; | ||
410 | tas->acr |= TAS_ACR_B_MONAUREAL | TAS_ACR_B_MON_SEL_RIGHT; | ||
411 | if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) | ||
412 | return -ENODEV; | ||
413 | 628 | ||
414 | tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT; | 629 | tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT; |
415 | if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp)) | 630 | if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp)) |
416 | return -ENODEV; | 631 | return -ENODEV; |
417 | 632 | ||
633 | tas->acr |= TAS_ACR_ANALOG_PDOWN | TAS_ACR_B_MONAUREAL | | ||
634 | TAS_ACR_B_MON_SEL_RIGHT; | ||
635 | if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) | ||
636 | return -ENODEV; | ||
637 | |||
418 | tmp = 0; | 638 | tmp = 0; |
419 | if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp)) | 639 | if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp)) |
420 | return -ENODEV; | 640 | return -ENODEV; |
421 | 641 | ||
642 | tas3004_set_drc(tas); | ||
643 | |||
644 | /* Set treble & bass to 0dB */ | ||
645 | tas->treble = TAS3004_TREBLE_ZERO; | ||
646 | tas->bass = TAS3004_BASS_ZERO; | ||
647 | tas_set_treble(tas); | ||
648 | tas_set_bass(tas); | ||
649 | |||
650 | tas->acr &= ~TAS_ACR_ANALOG_PDOWN; | ||
651 | if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) | ||
652 | return -ENODEV; | ||
653 | |||
654 | return 0; | ||
655 | } | ||
656 | |||
657 | static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock) | ||
658 | { | ||
659 | struct tas *tas = cii->codec_data; | ||
660 | |||
661 | switch(clock) { | ||
662 | case CLOCK_SWITCH_PREPARE_SLAVE: | ||
663 | /* Clocks are going away, mute mute mute */ | ||
664 | tas->codec.gpio->methods->all_amps_off(tas->codec.gpio); | ||
665 | tas->hw_enabled = 0; | ||
666 | break; | ||
667 | case CLOCK_SWITCH_SLAVE: | ||
668 | /* Clocks are back, re-init the codec */ | ||
669 | tas_reset_init(tas); | ||
670 | tas_set_volume(tas); | ||
671 | tas_set_mixer(tas); | ||
672 | tas->hw_enabled = 1; | ||
673 | tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); | ||
674 | break; | ||
675 | default: | ||
676 | /* doesn't happen as of now */ | ||
677 | return -EINVAL; | ||
678 | } | ||
422 | return 0; | 679 | return 0; |
423 | } | 680 | } |
424 | 681 | ||
@@ -427,6 +684,7 @@ static int tas_reset_init(struct tas *tas) | |||
427 | * our i2c device is suspended, and then take note of that! */ | 684 | * our i2c device is suspended, and then take note of that! */ |
428 | static int tas_suspend(struct tas *tas) | 685 | static int tas_suspend(struct tas *tas) |
429 | { | 686 | { |
687 | tas->hw_enabled = 0; | ||
430 | tas->acr |= TAS_ACR_ANALOG_PDOWN; | 688 | tas->acr |= TAS_ACR_ANALOG_PDOWN; |
431 | tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); | 689 | tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); |
432 | return 0; | 690 | return 0; |
@@ -438,6 +696,7 @@ static int tas_resume(struct tas *tas) | |||
438 | tas_reset_init(tas); | 696 | tas_reset_init(tas); |
439 | tas_set_volume(tas); | 697 | tas_set_volume(tas); |
440 | tas_set_mixer(tas); | 698 | tas_set_mixer(tas); |
699 | tas->hw_enabled = 1; | ||
441 | return 0; | 700 | return 0; |
442 | } | 701 | } |
443 | 702 | ||
@@ -463,6 +722,7 @@ static struct codec_info tas_codec_info = { | |||
463 | .bus_factor = 64, | 722 | .bus_factor = 64, |
464 | .owner = THIS_MODULE, | 723 | .owner = THIS_MODULE, |
465 | .usable = tas_usable, | 724 | .usable = tas_usable, |
725 | .switch_clock = tas_switch_clock, | ||
466 | #ifdef CONFIG_PM | 726 | #ifdef CONFIG_PM |
467 | .suspend = _tas_suspend, | 727 | .suspend = _tas_suspend, |
468 | .resume = _tas_resume, | 728 | .resume = _tas_resume, |
@@ -483,6 +743,7 @@ static int tas_init_codec(struct aoa_codec *codec) | |||
483 | printk(KERN_ERR PFX "tas failed to initialise\n"); | 743 | printk(KERN_ERR PFX "tas failed to initialise\n"); |
484 | return -ENXIO; | 744 | return -ENXIO; |
485 | } | 745 | } |
746 | tas->hw_enabled = 1; | ||
486 | 747 | ||
487 | if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev, | 748 | if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev, |
488 | aoa_get_card(), | 749 | aoa_get_card(), |
@@ -515,6 +776,22 @@ static int tas_init_codec(struct aoa_codec *codec) | |||
515 | if (err) | 776 | if (err) |
516 | goto error; | 777 | goto error; |
517 | 778 | ||
779 | err = aoa_snd_ctl_add(snd_ctl_new1(&drc_range_control, tas)); | ||
780 | if (err) | ||
781 | goto error; | ||
782 | |||
783 | err = aoa_snd_ctl_add(snd_ctl_new1(&drc_switch_control, tas)); | ||
784 | if (err) | ||
785 | goto error; | ||
786 | |||
787 | err = aoa_snd_ctl_add(snd_ctl_new1(&treble_control, tas)); | ||
788 | if (err) | ||
789 | goto error; | ||
790 | |||
791 | err = aoa_snd_ctl_add(snd_ctl_new1(&bass_control, tas)); | ||
792 | if (err) | ||
793 | goto error; | ||
794 | |||
518 | return 0; | 795 | return 0; |
519 | error: | 796 | error: |
520 | tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); | 797 | tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); |
@@ -548,6 +825,8 @@ static int tas_create(struct i2c_adapter *adapter, | |||
548 | tas->i2c.driver = &tas_driver; | 825 | tas->i2c.driver = &tas_driver; |
549 | tas->i2c.adapter = adapter; | 826 | tas->i2c.adapter = adapter; |
550 | tas->i2c.addr = addr; | 827 | tas->i2c.addr = addr; |
828 | /* seems that half is a saner default */ | ||
829 | tas->drc_range = TAS3004_DRC_MAX / 2; | ||
551 | strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE-1); | 830 | strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE-1); |
552 | 831 | ||
553 | if (i2c_attach_client(&tas->i2c)) { | 832 | if (i2c_attach_client(&tas->i2c)) { |
@@ -564,7 +843,9 @@ static int tas_create(struct i2c_adapter *adapter, | |||
564 | if (aoa_codec_register(&tas->codec)) { | 843 | if (aoa_codec_register(&tas->codec)) { |
565 | goto detach; | 844 | goto detach; |
566 | } | 845 | } |
567 | printk(KERN_DEBUG "snd-aoa-codec-tas: created and attached tas instance\n"); | 846 | printk(KERN_DEBUG |
847 | "snd-aoa-codec-tas: tas found, addr 0x%02x on %s\n", | ||
848 | addr, node->full_name); | ||
568 | return 0; | 849 | return 0; |
569 | detach: | 850 | detach: |
570 | i2c_detach_client(&tas->i2c); | 851 | i2c_detach_client(&tas->i2c); |