From 1f93a7dfd1f8d5ff7a5c53246c7534fe2332d6f4 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 11 Dec 2023 02:46:07 +0000 Subject: [PATCH] add audio --- kernel/sound/soc/codecs/tlv320aic3x.c | 72 +++++++++++++++++++----------------- 1 files changed, 38 insertions(+), 34 deletions(-) diff --git a/kernel/sound/soc/codecs/tlv320aic3x.c b/kernel/sound/soc/codecs/tlv320aic3x.c index 6c0a3da..6d066bc 100644 --- a/kernel/sound/soc/codecs/tlv320aic3x.c +++ b/kernel/sound/soc/codecs/tlv320aic3x.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * ALSA SoC TLV320AIC3X codec driver * @@ -5,10 +6,6 @@ * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> * * Based on sound/soc/codecs/wm8753.c by Liam Girdwood - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. * * Notes: * The AIC3X is a driver for a low power stereo audio @@ -324,6 +321,9 @@ */ static DECLARE_TLV_DB_SCALE(output_stage_tlv, -5900, 50, 1); +/* Output volumes. From 0 to 9 dB in 1 dB steps */ +static const DECLARE_TLV_DB_SCALE(out_tlv, 0, 100, 0); + static const struct snd_kcontrol_new aic3x_snd_controls[] = { /* Output */ SOC_DOUBLE_R_TLV("PCM Playback Volume", @@ -386,11 +386,17 @@ DACL1_2_HPLCOM_VOL, DACR1_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv), - /* Output pin mute controls */ + /* Output pin controls */ + SOC_DOUBLE_R_TLV("Line Playback Volume", LLOPM_CTRL, RLOPM_CTRL, 4, + 9, 0, out_tlv), SOC_DOUBLE_R("Line Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3, 0x01, 0), + SOC_DOUBLE_R_TLV("HP Playback Volume", HPLOUT_CTRL, HPROUT_CTRL, 4, + 9, 0, out_tlv), SOC_DOUBLE_R("HP Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, 0x01, 0), + SOC_DOUBLE_R_TLV("HPCOM Playback Volume", HPLCOM_CTRL, HPRCOM_CTRL, + 4, 9, 0, out_tlv), SOC_DOUBLE_R("HPCOM Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, 0x01, 0), @@ -472,6 +478,9 @@ 0, 118, 1, output_stage_tlv), SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0), + SOC_SINGLE_TLV("Mono Playback Volume", MONOLOPM_CTRL, 4, 9, 0, + out_tlv), + }; /* @@ -1047,7 +1056,7 @@ width = params_width(params); /* select data word length */ - data = snd_soc_component_read32(component, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4)); + data = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4)); switch (width) { case 16: break; @@ -1207,11 +1216,11 @@ return 0; } -static int aic3x_mute(struct snd_soc_dai *dai, int mute) +static int aic3x_mute(struct snd_soc_dai *dai, int mute, int direction) { struct snd_soc_component *component = dai->component; - u8 ldac_reg = snd_soc_component_read32(component, LDAC_VOL) & ~MUTE_ON; - u8 rdac_reg = snd_soc_component_read32(component, RDAC_VOL) & ~MUTE_ON; + u8 ldac_reg = snd_soc_component_read(component, LDAC_VOL) & ~MUTE_ON; + u8 rdac_reg = snd_soc_component_read(component, RDAC_VOL) & ~MUTE_ON; if (mute) { snd_soc_component_write(component, LDAC_VOL, ldac_reg | MUTE_ON); @@ -1247,8 +1256,8 @@ struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component); u8 iface_areg, iface_breg; - iface_areg = snd_soc_component_read32(component, AIC3X_ASD_INTF_CTRLA) & 0x3f; - iface_breg = snd_soc_component_read32(component, AIC3X_ASD_INTF_CTRLB) & 0x3f; + iface_areg = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLA) & 0x3f; + iface_breg = snd_soc_component_read(component, AIC3X_ASD_INTF_CTRLB) & 0x3f; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1259,6 +1268,16 @@ case SND_SOC_DAIFMT_CBS_CFS: aic3x->master = 0; iface_areg &= ~(BIT_CLK_MASTER | WORD_CLK_MASTER); + break; + case SND_SOC_DAIFMT_CBM_CFS: + aic3x->master = 1; + iface_areg |= BIT_CLK_MASTER; + iface_areg &= ~WORD_CLK_MASTER; + break; + case SND_SOC_DAIFMT_CBS_CFM: + aic3x->master = 1; + iface_areg |= WORD_CLK_MASTER; + iface_areg &= ~BIT_CLK_MASTER; break; default: return -EINVAL; @@ -1388,8 +1407,8 @@ * writing one of them and thus caused other one also not * being written */ - pll_c = snd_soc_component_read32(component, AIC3X_PLL_PROGC_REG); - pll_d = snd_soc_component_read32(component, AIC3X_PLL_PROGD_REG); + pll_c = snd_soc_component_read(component, AIC3X_PLL_PROGC_REG); + pll_d = snd_soc_component_read(component, AIC3X_PLL_PROGD_REG); if (pll_c == aic3x_reg[AIC3X_PLL_PROGC_REG].def || pll_d == aic3x_reg[AIC3X_PLL_PROGD_REG].def) { snd_soc_component_write(component, AIC3X_PLL_PROGC_REG, pll_c); @@ -1462,10 +1481,11 @@ static const struct snd_soc_dai_ops aic3x_dai_ops = { .hw_params = aic3x_hw_params, .prepare = aic3x_prepare, - .digital_mute = aic3x_mute, + .mute_stream = aic3x_mute, .set_sysclk = aic3x_set_dai_sysclk, .set_fmt = aic3x_set_dai_fmt, .set_tdm_slot = aic3x_set_dai_tdm_slot, + .no_capture_mute = 1, }; static struct snd_soc_dai_driver aic3x_dai = { @@ -1604,13 +1624,14 @@ for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) { aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event; aic3x->disable_nb[i].aic3x = aic3x; - ret = regulator_register_notifier(aic3x->supplies[i].consumer, - &aic3x->disable_nb[i].nb); + ret = devm_regulator_register_notifier( + aic3x->supplies[i].consumer, + &aic3x->disable_nb[i].nb); if (ret) { dev_err(component->dev, "Failed to request regulator notifier: %d\n", ret); - goto err_notif; + return ret; } } @@ -1668,28 +1689,11 @@ aic3x_add_widgets(component); return 0; - -err_notif: - while (i--) - regulator_unregister_notifier(aic3x->supplies[i].consumer, - &aic3x->disable_nb[i].nb); - return ret; -} - -static void aic3x_remove(struct snd_soc_component *component) -{ - struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component); - int i; - - for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) - regulator_unregister_notifier(aic3x->supplies[i].consumer, - &aic3x->disable_nb[i].nb); } static const struct snd_soc_component_driver soc_component_dev_aic3x = { .set_bias_level = aic3x_set_bias_level, .probe = aic3x_probe, - .remove = aic3x_remove, .controls = aic3x_snd_controls, .num_controls = ARRAY_SIZE(aic3x_snd_controls), .dapm_widgets = aic3x_dapm_widgets, -- Gitblit v1.6.2