From 77fffb83933ad9e514ea0c7fd93b28cabcdea311 Mon Sep 17 00:00:00 2001 From: Vincent Knecht Date: Sun, 31 Oct 2021 22:09:55 +0100 Subject: [PATCH 1/2] ASoC: dt-bindings: nxp, tfa989x: Add rcv-gpios property for tfa9897 Add optional rcv-gpios property specific to tfa9897 receiver mode. Signed-off-by: Vincent Knecht Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20211031210956.812101-2-vincent.knecht@mailoo.org Signed-off-by: Mark Brown --- .../bindings/sound/nxp,tfa989x.yaml | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml b/Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml index 7667471be1e4..b9b1dba40856 100644 --- a/Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml +++ b/Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml @@ -24,11 +24,23 @@ properties: '#sound-dai-cells': const: 0 + rcv-gpios: + description: optional GPIO to be asserted when receiver mode is enabled. + sound-name-prefix: true vddd-supply: description: regulator phandle for the VDDD power supply. +if: + not: + properties: + compatible: + const: nxp,tfa9897 +then: + properties: + rcv-gpios: false + required: - compatible - reg @@ -55,3 +67,32 @@ examples: #sound-dai-cells = <0>; }; }; + + - | + #include + i2c { + #address-cells = <1>; + #size-cells = <0>; + + speaker_codec_top: audio-codec@34 { + compatible = "nxp,tfa9897"; + reg = <0x34>; + vddd-supply = <&pm8916_l6>; + rcv-gpios = <&msmgpio 50 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&speaker_top_default>; + sound-name-prefix = "Speaker Top"; + #sound-dai-cells = <0>; + }; + + speaker_codec_bottom: audio-codec@36 { + compatible = "nxp,tfa9897"; + reg = <0x36>; + vddd-supply = <&pm8916_l6>; + rcv-gpios = <&msmgpio 111 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&speaker_bottom_default>; + sound-name-prefix = "Speaker Bottom"; + #sound-dai-cells = <0>; + }; + }; From 9da52c39b33e7bd9c1f56175c0466fa468d7f145 Mon Sep 17 00:00:00 2001 From: Vincent Knecht Date: Sun, 31 Oct 2021 22:09:56 +0100 Subject: [PATCH 2/2] ASoC: codecs: tfa989x: Add support for tfa9897 optional rcv-gpios Some OEM use a GPIO in addition to the tfa9897 RCV bit to switch between loudspeaker and earpiece/receiver mode. Add support for the GPIO switching by specifying rcv-gpios in DT. Signed-off-by: Vincent Knecht Link: https://lore.kernel.org/r/20211031210956.812101-3-vincent.knecht@mailoo.org Signed-off-by: Mark Brown --- sound/soc/codecs/tfa989x.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/tfa989x.c b/sound/soc/codecs/tfa989x.c index eb2a7870148d..dc86852752c5 100644 --- a/sound/soc/codecs/tfa989x.c +++ b/sound/soc/codecs/tfa989x.c @@ -7,6 +7,7 @@ * Copyright (C) 2013 Sony Mobile Communications Inc. */ +#include #include #include #include @@ -56,6 +57,7 @@ struct tfa989x_rev { struct tfa989x { const struct tfa989x_rev *rev; struct regulator *vddd_supply; + struct gpio_desc *rcv_gpiod; }; static bool tfa989x_writeable_reg(struct device *dev, unsigned int reg) @@ -99,10 +101,20 @@ static const struct snd_soc_dapm_route tfa989x_dapm_routes[] = { {"Amp Input", "Right", "AIFINR"}, }; +static int tfa989x_put_mode(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct tfa989x *tfa989x = snd_soc_component_get_drvdata(component); + + gpiod_set_value_cansleep(tfa989x->rcv_gpiod, ucontrol->value.enumerated.item[0]); + + return snd_soc_put_enum_double(kcontrol, ucontrol); +} + static const char * const mode_text[] = { "Speaker", "Receiver" }; static SOC_ENUM_SINGLE_DECL(mode_enum, TFA989X_I2SREG, TFA989X_I2SREG_RCV, mode_text); static const struct snd_kcontrol_new tfa989x_mode_controls[] = { - SOC_ENUM("Mode", mode_enum), + SOC_ENUM_EXT("Mode", mode_enum, snd_soc_get_enum_double, tfa989x_put_mode), }; static int tfa989x_probe(struct snd_soc_component *component) @@ -301,6 +313,12 @@ static int tfa989x_i2c_probe(struct i2c_client *i2c) return dev_err_probe(dev, PTR_ERR(tfa989x->vddd_supply), "Failed to get vddd regulator\n"); + if (tfa989x->rev->rev == TFA9897_REVISION) { + tfa989x->rcv_gpiod = devm_gpiod_get_optional(dev, "rcv", GPIOD_OUT_LOW); + if (IS_ERR(tfa989x->rcv_gpiod)) + return PTR_ERR(tfa989x->rcv_gpiod); + } + regmap = devm_regmap_init_i2c(i2c, &tfa989x_regmap); if (IS_ERR(regmap)) return PTR_ERR(regmap);