• Home
  • Raw
  • Download

Lines Matching +full:codec +full:- +full:3

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Apple Onboard Audio driver for tas codec
8 * - How to distinguish between 3004 and versions?
11 * - This codec driver doesn't honour the 'connected'
15 * - Driver assumes that the microphone is always
17 * the input. This should also be a codec-dependent
18 * flag, maybe the codec should have 3 different
23 * - As Apple notes in their code, the tas3004 seems
36 * - this should actually register *two* aoa_codec
49 * codec to refine the transfer_info items in the
54 * a 'clock group id' value so the codec can
72 MODULE_DESCRIPTION("tas codec driver for snd-aoa");
75 #include "tas-gain-table.h"
76 #include "tas-basstreble.h"
80 #define PFX "snd-aoa-codec-tas: "
84 struct aoa_codec codec; member
91 u8 mixer_l[3], mixer_r[3];
97 * codec init/suspend/resume */
103 static struct tas *codec_to_tas(struct aoa_codec *codec) in codec_to_tas() argument
105 return container_of(codec, struct tas, codec); in codec_to_tas()
111 return i2c_smbus_write_byte_data(tas->i2c, reg, *data); in tas_write_reg()
113 return i2c_smbus_write_i2c_block_data(tas->i2c, reg, len, data); in tas_write_reg()
120 if (tas->drc_enabled) in tas3004_set_drc()
121 val[0] = 0x50; /* 3:1 above threshold */ in tas3004_set_drc()
125 if (tas->drc_range > 0xef) in tas3004_set_drc()
127 else if (tas->drc_range < 0) in tas3004_set_drc()
130 val[2] = tas->drc_range; in tas3004_set_drc()
131 val[3] = 0xb0; in tas3004_set_drc()
142 tmp = tas3004_treble(tas->treble); in tas_set_treble()
150 tmp = tas3004_bass(tas->bass); in tas_set_bass()
160 left = tas->cached_volume_l; in tas_set_volume()
161 right = tas->cached_volume_r; in tas_set_volume()
166 if (tas->mute_l) left = 0; in tas_set_volume()
167 if (tas->mute_r) right = 0; in tas_set_volume()
180 block[3] = tmp>>20; in tas_set_volume()
192 for (i=0;i<3;i++) { in tas_set_mixer()
193 val = tas->mixer_l[i]; in tas_set_mixer()
196 block[3*i+0] = tmp>>16; in tas_set_mixer()
197 block[3*i+1] = tmp>>8; in tas_set_mixer()
198 block[3*i+2] = tmp; in tas_set_mixer()
202 for (i=0;i<3;i++) { in tas_set_mixer()
203 val = tas->mixer_r[i]; in tas_set_mixer()
206 block[3*i+0] = tmp>>16; in tas_set_mixer()
207 block[3*i+1] = tmp>>8; in tas_set_mixer()
208 block[3*i+2] = tmp; in tas_set_mixer()
227 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in tas_snd_vol_info()
228 uinfo->count = 2; in tas_snd_vol_info()
229 uinfo->value.integer.min = 0; in tas_snd_vol_info()
230 uinfo->value.integer.max = 177; in tas_snd_vol_info()
239 mutex_lock(&tas->mtx); in tas_snd_vol_get()
240 ucontrol->value.integer.value[0] = tas->cached_volume_l; in tas_snd_vol_get()
241 ucontrol->value.integer.value[1] = tas->cached_volume_r; in tas_snd_vol_get()
242 mutex_unlock(&tas->mtx); in tas_snd_vol_get()
251 if (ucontrol->value.integer.value[0] < 0 || in tas_snd_vol_put()
252 ucontrol->value.integer.value[0] > 177) in tas_snd_vol_put()
253 return -EINVAL; in tas_snd_vol_put()
254 if (ucontrol->value.integer.value[1] < 0 || in tas_snd_vol_put()
255 ucontrol->value.integer.value[1] > 177) in tas_snd_vol_put()
256 return -EINVAL; in tas_snd_vol_put()
258 mutex_lock(&tas->mtx); in tas_snd_vol_put()
259 if (tas->cached_volume_l == ucontrol->value.integer.value[0] in tas_snd_vol_put()
260 && tas->cached_volume_r == ucontrol->value.integer.value[1]) { in tas_snd_vol_put()
261 mutex_unlock(&tas->mtx); in tas_snd_vol_put()
265 tas->cached_volume_l = ucontrol->value.integer.value[0]; in tas_snd_vol_put()
266 tas->cached_volume_r = ucontrol->value.integer.value[1]; in tas_snd_vol_put()
267 if (tas->hw_enabled) in tas_snd_vol_put()
269 mutex_unlock(&tas->mtx); in tas_snd_vol_put()
289 mutex_lock(&tas->mtx); in tas_snd_mute_get()
290 ucontrol->value.integer.value[0] = !tas->mute_l; in tas_snd_mute_get()
291 ucontrol->value.integer.value[1] = !tas->mute_r; in tas_snd_mute_get()
292 mutex_unlock(&tas->mtx); in tas_snd_mute_get()
301 mutex_lock(&tas->mtx); in tas_snd_mute_put()
302 if (tas->mute_l == !ucontrol->value.integer.value[0] in tas_snd_mute_put()
303 && tas->mute_r == !ucontrol->value.integer.value[1]) { in tas_snd_mute_put()
304 mutex_unlock(&tas->mtx); in tas_snd_mute_put()
308 tas->mute_l = !ucontrol->value.integer.value[0]; in tas_snd_mute_put()
309 tas->mute_r = !ucontrol->value.integer.value[1]; in tas_snd_mute_put()
310 if (tas->hw_enabled) in tas_snd_mute_put()
312 mutex_unlock(&tas->mtx); in tas_snd_mute_put()
328 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in tas_snd_mixer_info()
329 uinfo->count = 2; in tas_snd_mixer_info()
330 uinfo->value.integer.min = 0; in tas_snd_mixer_info()
331 uinfo->value.integer.max = 177; in tas_snd_mixer_info()
339 int idx = kcontrol->private_value; in tas_snd_mixer_get()
341 mutex_lock(&tas->mtx); in tas_snd_mixer_get()
342 ucontrol->value.integer.value[0] = tas->mixer_l[idx]; in tas_snd_mixer_get()
343 ucontrol->value.integer.value[1] = tas->mixer_r[idx]; in tas_snd_mixer_get()
344 mutex_unlock(&tas->mtx); in tas_snd_mixer_get()
353 int idx = kcontrol->private_value; in tas_snd_mixer_put()
355 mutex_lock(&tas->mtx); in tas_snd_mixer_put()
356 if (tas->mixer_l[idx] == ucontrol->value.integer.value[0] in tas_snd_mixer_put()
357 && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) { in tas_snd_mixer_put()
358 mutex_unlock(&tas->mtx); in tas_snd_mixer_put()
362 tas->mixer_l[idx] = ucontrol->value.integer.value[0]; in tas_snd_mixer_put()
363 tas->mixer_r[idx] = ucontrol->value.integer.value[1]; in tas_snd_mixer_put()
365 if (tas->hw_enabled) in tas_snd_mixer_put()
367 mutex_unlock(&tas->mtx); in tas_snd_mixer_put()
388 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in tas_snd_drc_range_info()
389 uinfo->count = 1; in tas_snd_drc_range_info()
390 uinfo->value.integer.min = 0; in tas_snd_drc_range_info()
391 uinfo->value.integer.max = TAS3004_DRC_MAX; in tas_snd_drc_range_info()
400 mutex_lock(&tas->mtx); in tas_snd_drc_range_get()
401 ucontrol->value.integer.value[0] = tas->drc_range; in tas_snd_drc_range_get()
402 mutex_unlock(&tas->mtx); in tas_snd_drc_range_get()
411 if (ucontrol->value.integer.value[0] < 0 || in tas_snd_drc_range_put()
412 ucontrol->value.integer.value[0] > TAS3004_DRC_MAX) in tas_snd_drc_range_put()
413 return -EINVAL; in tas_snd_drc_range_put()
415 mutex_lock(&tas->mtx); in tas_snd_drc_range_put()
416 if (tas->drc_range == ucontrol->value.integer.value[0]) { in tas_snd_drc_range_put()
417 mutex_unlock(&tas->mtx); in tas_snd_drc_range_put()
421 tas->drc_range = ucontrol->value.integer.value[0]; in tas_snd_drc_range_put()
422 if (tas->hw_enabled) in tas_snd_drc_range_put()
424 mutex_unlock(&tas->mtx); in tas_snd_drc_range_put()
444 mutex_lock(&tas->mtx); in tas_snd_drc_switch_get()
445 ucontrol->value.integer.value[0] = tas->drc_enabled; in tas_snd_drc_switch_get()
446 mutex_unlock(&tas->mtx); in tas_snd_drc_switch_get()
455 mutex_lock(&tas->mtx); in tas_snd_drc_switch_put()
456 if (tas->drc_enabled == ucontrol->value.integer.value[0]) { in tas_snd_drc_switch_put()
457 mutex_unlock(&tas->mtx); in tas_snd_drc_switch_put()
461 tas->drc_enabled = !!ucontrol->value.integer.value[0]; in tas_snd_drc_switch_put()
462 if (tas->hw_enabled) in tas_snd_drc_switch_put()
464 mutex_unlock(&tas->mtx); in tas_snd_drc_switch_put()
480 static const char * const texts[] = { "Line-In", "Microphone" }; in tas_snd_capture_source_info()
490 mutex_lock(&tas->mtx); in tas_snd_capture_source_get()
491 ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B); in tas_snd_capture_source_get()
492 mutex_unlock(&tas->mtx); in tas_snd_capture_source_get()
502 if (ucontrol->value.enumerated.item[0] > 1) in tas_snd_capture_source_put()
503 return -EINVAL; in tas_snd_capture_source_put()
504 mutex_lock(&tas->mtx); in tas_snd_capture_source_put()
505 oldacr = tas->acr; in tas_snd_capture_source_put()
512 tas->acr &= ~(TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL); in tas_snd_capture_source_put()
513 if (ucontrol->value.enumerated.item[0]) in tas_snd_capture_source_put()
514 tas->acr |= TAS_ACR_INPUT_B | TAS_ACR_B_MONAUREAL | in tas_snd_capture_source_put()
516 if (oldacr == tas->acr) { in tas_snd_capture_source_put()
517 mutex_unlock(&tas->mtx); in tas_snd_capture_source_put()
520 if (tas->hw_enabled) in tas_snd_capture_source_put()
521 tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); in tas_snd_capture_source_put()
522 mutex_unlock(&tas->mtx); in tas_snd_capture_source_put()
549 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in tas_snd_treble_info()
550 uinfo->count = 1; in tas_snd_treble_info()
551 uinfo->value.integer.min = TAS3004_TREBLE_MIN; in tas_snd_treble_info()
552 uinfo->value.integer.max = TAS3004_TREBLE_MAX; in tas_snd_treble_info()
561 mutex_lock(&tas->mtx); in tas_snd_treble_get()
562 ucontrol->value.integer.value[0] = tas->treble; in tas_snd_treble_get()
563 mutex_unlock(&tas->mtx); in tas_snd_treble_get()
572 if (ucontrol->value.integer.value[0] < TAS3004_TREBLE_MIN || in tas_snd_treble_put()
573 ucontrol->value.integer.value[0] > TAS3004_TREBLE_MAX) in tas_snd_treble_put()
574 return -EINVAL; in tas_snd_treble_put()
575 mutex_lock(&tas->mtx); in tas_snd_treble_put()
576 if (tas->treble == ucontrol->value.integer.value[0]) { in tas_snd_treble_put()
577 mutex_unlock(&tas->mtx); in tas_snd_treble_put()
581 tas->treble = ucontrol->value.integer.value[0]; in tas_snd_treble_put()
582 if (tas->hw_enabled) in tas_snd_treble_put()
584 mutex_unlock(&tas->mtx); in tas_snd_treble_put()
600 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in tas_snd_bass_info()
601 uinfo->count = 1; in tas_snd_bass_info()
602 uinfo->value.integer.min = TAS3004_BASS_MIN; in tas_snd_bass_info()
603 uinfo->value.integer.max = TAS3004_BASS_MAX; in tas_snd_bass_info()
612 mutex_lock(&tas->mtx); in tas_snd_bass_get()
613 ucontrol->value.integer.value[0] = tas->bass; in tas_snd_bass_get()
614 mutex_unlock(&tas->mtx); in tas_snd_bass_get()
623 if (ucontrol->value.integer.value[0] < TAS3004_BASS_MIN || in tas_snd_bass_put()
624 ucontrol->value.integer.value[0] > TAS3004_BASS_MAX) in tas_snd_bass_put()
625 return -EINVAL; in tas_snd_bass_put()
626 mutex_lock(&tas->mtx); in tas_snd_bass_put()
627 if (tas->bass == ucontrol->value.integer.value[0]) { in tas_snd_bass_put()
628 mutex_unlock(&tas->mtx); in tas_snd_bass_put()
632 tas->bass = ucontrol->value.integer.value[0]; in tas_snd_bass_put()
633 if (tas->hw_enabled) in tas_snd_bass_put()
635 mutex_unlock(&tas->mtx); in tas_snd_bass_put()
675 tas->codec.gpio->methods->all_amps_off(tas->codec.gpio); in tas_reset_init()
677 tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); in tas_reset_init()
679 tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1); in tas_reset_init()
681 tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); in tas_reset_init()
683 tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); in tas_reset_init()
689 tas->acr |= TAS_ACR_ANALOG_PDOWN; in tas_reset_init()
690 if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) in tas_reset_init()
700 tas->treble = TAS3004_TREBLE_ZERO; in tas_reset_init()
701 tas->bass = TAS3004_BASS_ZERO; in tas_reset_init()
705 tas->acr &= ~TAS_ACR_ANALOG_PDOWN; in tas_reset_init()
706 if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) in tas_reset_init()
711 return -ENODEV; in tas_reset_init()
716 struct tas *tas = cii->codec_data; in tas_switch_clock()
721 tas->codec.gpio->methods->all_amps_off(tas->codec.gpio); in tas_switch_clock()
722 tas->hw_enabled = 0; in tas_switch_clock()
725 /* Clocks are back, re-init the codec */ in tas_switch_clock()
726 mutex_lock(&tas->mtx); in tas_switch_clock()
730 tas->hw_enabled = 1; in tas_switch_clock()
731 tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); in tas_switch_clock()
732 mutex_unlock(&tas->mtx); in tas_switch_clock()
736 return -EINVAL; in tas_switch_clock()
747 mutex_lock(&tas->mtx); in tas_suspend()
748 tas->hw_enabled = 0; in tas_suspend()
749 tas->acr |= TAS_ACR_ANALOG_PDOWN; in tas_suspend()
750 tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); in tas_suspend()
751 mutex_unlock(&tas->mtx); in tas_suspend()
757 /* reset codec */ in tas_resume()
758 mutex_lock(&tas->mtx); in tas_resume()
762 tas->hw_enabled = 1; in tas_resume()
763 mutex_unlock(&tas->mtx); in tas_resume()
769 return tas_suspend(cii->codec_data); in _tas_suspend()
774 return tas_resume(cii->codec_data); in _tas_resume()
796 static int tas_init_codec(struct aoa_codec *codec) in tas_init_codec() argument
798 struct tas *tas = codec_to_tas(codec); in tas_init_codec()
801 if (!tas->codec.gpio || !tas->codec.gpio->methods) { in tas_init_codec()
803 return -EINVAL; in tas_init_codec()
806 mutex_lock(&tas->mtx); in tas_init_codec()
809 mutex_unlock(&tas->mtx); in tas_init_codec()
810 return -ENXIO; in tas_init_codec()
812 tas->hw_enabled = 1; in tas_init_codec()
813 mutex_unlock(&tas->mtx); in tas_init_codec()
815 if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev, in tas_init_codec()
819 return -ENODEV; in tas_init_codec()
824 return -ENODEV; in tas_init_codec()
864 tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); in tas_init_codec()
869 static void tas_exit_codec(struct aoa_codec *codec) in tas_exit_codec() argument
871 struct tas *tas = codec_to_tas(codec); in tas_exit_codec()
873 if (!tas->codec.soundbus_dev) in tas_exit_codec()
875 tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); in tas_exit_codec()
882 struct device_node *node = client->dev.of_node; in tas_i2c_probe()
888 return -ENOMEM; in tas_i2c_probe()
890 mutex_init(&tas->mtx); in tas_i2c_probe()
891 tas->i2c = client; in tas_i2c_probe()
895 tas->drc_range = TAS3004_DRC_MAX / 2; in tas_i2c_probe()
897 strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN); in tas_i2c_probe()
898 tas->codec.owner = THIS_MODULE; in tas_i2c_probe()
899 tas->codec.init = tas_init_codec; in tas_i2c_probe()
900 tas->codec.exit = tas_exit_codec; in tas_i2c_probe()
901 tas->codec.node = of_node_get(node); in tas_i2c_probe()
903 if (aoa_codec_register(&tas->codec)) { in tas_i2c_probe()
907 "snd-aoa-codec-tas: tas found, addr 0x%02x on %pOF\n", in tas_i2c_probe()
908 (unsigned int)client->addr, node); in tas_i2c_probe()
911 mutex_destroy(&tas->mtx); in tas_i2c_probe()
913 return -EINVAL; in tas_i2c_probe()
921 aoa_codec_unregister(&tas->codec); in tas_i2c_remove()
922 of_node_put(tas->codec.node); in tas_i2c_remove()
924 /* power down codec chip */ in tas_i2c_remove()
927 mutex_destroy(&tas->mtx); in tas_i2c_remove()