From 658fb7fe8e7f4014ea17a4da0e0c1d9bc319fa35 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 5 Mar 2025 18:27:32 +0100 Subject: [PATCH 01/16] ASoC: cs42l43: convert to SYSTEM_SLEEP_PM_OPS The custom suspend function causes a build warning when CONFIG_PM_SLEEP is disabled: sound/soc/codecs/cs42l43.c:2405:12: error: unused function 'cs42l43_codec_runtime_force_suspend' [-Werror,-Wunused-function] Change SET_SYSTEM_SLEEP_PM_OPS() to the newer SYSTEM_SLEEP_PM_OPS(), to avoid this. Fixes: 164b7dd4546b ("ASoC: cs42l43: Add jack delay debounce after suspend") Signed-off-by: Arnd Bergmann Reviewed-by: Maciej Strozek Reviewed-by: Charles Keepax Link: https://patch.msgid.link/20250305172738.3437513-1-arnd@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l43.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42l43.c b/sound/soc/codecs/cs42l43.c index d307b56a7f38..ea84ac64c775 100644 --- a/sound/soc/codecs/cs42l43.c +++ b/sound/soc/codecs/cs42l43.c @@ -2417,7 +2417,7 @@ static int cs42l43_codec_runtime_force_suspend(struct device *dev) static const struct dev_pm_ops cs42l43_codec_pm_ops = { RUNTIME_PM_OPS(NULL, cs42l43_codec_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(cs42l43_codec_runtime_force_suspend, pm_runtime_force_resume) + SYSTEM_SLEEP_PM_OPS(cs42l43_codec_runtime_force_suspend, pm_runtime_force_resume) }; static const struct platform_device_id cs42l43_codec_id_table[] = { -- 2.51.0 From a935b3f981809272d2649ad9c27a751685137846 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 12 Mar 2025 18:05:16 +0200 Subject: [PATCH 02/16] ASoC: SOF: ipc4-topology: Allocate ref_params on stack Currently the compiler (clang 19.1.7) is not happy about the size of the stack frame in sof_ipc4_prepare_copier_module: sound/soc/sof/ipc4-topology.c:1800:1: error: stack frame size (1288) exceeds limit (1024) in 'sof_ipc4_prepare_copier_module' [-Werror,-Wframe-larger-than] 1800 | sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, | ^ Work around this by allocating ref_params on stack, as it looks the biggest variable on stack right now. Note, this only happens when compile for 32-bit machines (x86_32 in my case). Signed-off-by: Andy Shevchenko Acked-by: Peter Ujfalusi Link: https://patch.msgid.link/20250312160516.3864295-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index f14b8ef8d0b0..540ba140e155 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -7,6 +7,7 @@ // // #include +#include #include #include #include @@ -1807,8 +1808,8 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc4_copier_data *copier_data; int input_fmt_index, output_fmt_index; - struct snd_pcm_hw_params ref_params; struct sof_ipc4_copier *ipc4_copier; + struct snd_pcm_hw_params *ref_params __free(kfree) = NULL; struct snd_sof_dai *dai; u32 gtw_cfg_config_length; u32 dma_config_tlv_size = 0; @@ -1885,9 +1886,11 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, * for capture. */ if (dir == SNDRV_PCM_STREAM_PLAYBACK) - ref_params = *fe_params; + ref_params = kmemdup(fe_params, sizeof(*ref_params), GFP_KERNEL); else - ref_params = *pipeline_params; + ref_params = kmemdup(pipeline_params, sizeof(*ref_params), GFP_KERNEL); + if (!ref_params) + return -ENOMEM; copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; copier_data->gtw_cfg.node_id |= @@ -1924,8 +1927,11 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, * In case of capture the ref_params returned will be used to * find the input configuration of the copier. */ - ref_params = *fe_params; - ret = sof_ipc4_prepare_dai_copier(sdev, dai, &ref_params, dir); + ref_params = kmemdup(fe_params, sizeof(*ref_params), GFP_KERNEL); + if (!ref_params) + return -ENOMEM; + + ret = sof_ipc4_prepare_dai_copier(sdev, dai, ref_params, dir); if (ret < 0) return ret; @@ -1934,7 +1940,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, * input configuration of the copier. */ if (dir == SNDRV_PCM_STREAM_PLAYBACK) - ref_params = *pipeline_params; + memcpy(ref_params, pipeline_params, sizeof(*ref_params)); break; } @@ -1946,7 +1952,10 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, ipc4_copier = (struct sof_ipc4_copier *)swidget->private; copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; - ref_params = *pipeline_params; + + ref_params = kmemdup(pipeline_params, sizeof(*ref_params), GFP_KERNEL); + if (!ref_params) + return -ENOMEM; break; } @@ -1959,7 +1968,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, /* set input and output audio formats */ input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget, &copier_data->base_config, - &ref_params, available_fmt); + ref_params, available_fmt); if (input_fmt_index < 0) return input_fmt_index; -- 2.51.0 From de74ec718e0788e1998eb7289ad07970e27cae27 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 28 Feb 2025 00:29:30 +0000 Subject: [PATCH 03/16] ASoC: simple-card-utils: Don't use __free(device_node) at graph_util_parse_dai() commit 419d1918105e ("ASoC: simple-card-utils: use __free(device_node) for device node") uses __free(device_node) for dlc->of_node, but we need to keep it while driver is in use. Don't use __free(device_node) in graph_util_parse_dai(). Fixes: 419d1918105e ("ASoC: simple-card-utils: use __free(device_node) for device node") Reported-by: Thuan Nguyen Reported-by: Detlev Casanova Signed-off-by: Kuninori Morimoto Tested-by: Thuan Nguyen Tested-by: Detlev Casanova Link: https://patch.msgid.link/87eczisyhh.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card-utils.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index c2445c5ccd84..32efb30c55d6 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -1077,6 +1077,7 @@ static int graph_get_dai_id(struct device_node *ep) int graph_util_parse_dai(struct device *dev, struct device_node *ep, struct snd_soc_dai_link_component *dlc, int *is_single_link) { + struct device_node *node; struct of_phandle_args args = {}; struct snd_soc_dai *dai; int ret; @@ -1084,7 +1085,7 @@ int graph_util_parse_dai(struct device *dev, struct device_node *ep, if (!ep) return 0; - struct device_node *node __free(device_node) = of_graph_get_port_parent(ep); + node = of_graph_get_port_parent(ep); /* * Try to find from DAI node @@ -1126,8 +1127,10 @@ int graph_util_parse_dai(struct device *dev, struct device_node *ep, * if he unbinded CPU or Codec. */ ret = snd_soc_get_dlc(&args, dlc); - if (ret < 0) + if (ret < 0) { + of_node_put(node); return ret; + } parse_dai_end: if (is_single_link) -- 2.51.0 From 25a83f870b8a25a4b10bf5ba474a017ed5a72e7d Mon Sep 17 00:00:00 2001 From: James Calligeros Date: Thu, 27 Feb 2025 22:07:28 +1000 Subject: [PATCH 04/16] ASoC: dt-bindings: tas27xx: add compatible for SN012776 The TI SN012776 is a variant of TAS2764 found in Apple Silicon Macs. It continues Apple's long-standing policy of getting vendors to spin out subtly incompatible and Apple-exclusive variants of their publicly available parts. Reviewed-by: Neal Gompa Acked-by: Rob Herring (Arm) Signed-off-by: James Calligeros Link: https://patch.msgid.link/20250227-apple-codec-changes-v3-1-cbb130030acf@gmail.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/ti,tas27xx.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml b/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml index 5447482179c1..fcaae848e78a 100644 --- a/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml +++ b/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml @@ -24,6 +24,7 @@ properties: enum: - ti,tas2764 - ti,tas2780 + - ti,sn012776 # Apple variant of TAS2764 reg: maxItems: 1 -- 2.51.0 From ce9233937f3233e277ff23395e61ea690c769bef Mon Sep 17 00:00:00 2001 From: James Calligeros Date: Thu, 27 Feb 2025 22:07:29 +1000 Subject: [PATCH 05/16] ASoC: dt-bindings: tas2770: add compatible for TAS5770L A variant of TAS2770 known as TAS5770L is found in Apple Silicon Macs. Reviewed-by: Neal Gompa Acked-by: Rob Herring (Arm) Signed-off-by: James Calligeros Link: https://patch.msgid.link/20250227-apple-codec-changes-v3-2-cbb130030acf@gmail.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/ti,tas2770.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/ti,tas2770.yaml b/Documentation/devicetree/bindings/sound/ti,tas2770.yaml index 5e7aea43aced..8eab98a0f7a2 100644 --- a/Documentation/devicetree/bindings/sound/ti,tas2770.yaml +++ b/Documentation/devicetree/bindings/sound/ti,tas2770.yaml @@ -23,6 +23,7 @@ properties: compatible: enum: - ti,tas2770 + - ti,tas5770l # Apple variant reg: maxItems: 1 -- 2.51.0 From ad18392962df46a858432839cc6bcaf2ede7cc86 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Martin=20Povi=C5=A1er?= Date: Thu, 27 Feb 2025 22:07:30 +1000 Subject: [PATCH 06/16] ASoC: tas2764: Extend driver to SN012776 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit SN012776 is a speaker amp chip found in Apple's 2021 laptops. It appears similar and more-or-less compatible to TAS2764. Extend the TAS2764 driver with some SN012776 specifics and configure the chip assuming it's in one of the Apple machines. Reviewed-by: Neal Gompa Signed-off-by: Martin Povišer Signed-off-by: James Calligeros Link: https://patch.msgid.link/20250227-apple-codec-changes-v3-3-cbb130030acf@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2764.c | 43 +++++++++++++++++++++++++++++++++++--- sound/soc/codecs/tas2764.h | 3 +++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index c0a1d0c2a938..d9b4f898789f 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,11 @@ #include "tas2764.h" +enum tas2764_devid { + DEVID_TAS2764 = 0, + DEVID_SN012776 = 1 +}; + struct tas2764_priv { struct snd_soc_component *component; struct gpio_desc *reset_gpio; @@ -30,7 +36,8 @@ struct tas2764_priv { struct regmap *regmap; struct device *dev; int irq; - + enum tas2764_devid devid; + int v_sense_slot; int i_sense_slot; @@ -533,10 +540,16 @@ static struct snd_soc_dai_driver tas2764_dai_driver[] = { }, }; +static uint8_t sn012776_bop_presets[] = { + 0x01, 0x32, 0x02, 0x22, 0x83, 0x2d, 0x80, 0x02, 0x06, + 0x32, 0x46, 0x30, 0x02, 0x06, 0x38, 0x40, 0x30, 0x02, + 0x06, 0x3e, 0x37, 0x30, 0xff, 0xe6 +}; + static int tas2764_codec_probe(struct snd_soc_component *component) { struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component); - int ret; + int ret, i; tas2764->component = component; @@ -585,6 +598,27 @@ static int tas2764_codec_probe(struct snd_soc_component *component) if (ret < 0) return ret; + switch (tas2764->devid) { + case DEVID_SN012776: + ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL, + TAS2764_PWR_CTRL_BOP_SRC, + TAS2764_PWR_CTRL_BOP_SRC); + if (ret < 0) + return ret; + + for (i = 0; i < ARRAY_SIZE(sn012776_bop_presets); i++) { + ret = snd_soc_component_write(component, + TAS2764_BOP_CFG0 + i, + sn012776_bop_presets[i]); + + if (ret < 0) + return ret; + } + break; + default: + break; + } + return 0; } @@ -716,6 +750,8 @@ static int tas2764_i2c_probe(struct i2c_client *client) if (!tas2764) return -ENOMEM; + tas2764->devid = (enum tas2764_devid)of_device_get_match_data(&client->dev); + tas2764->dev = &client->dev; tas2764->irq = client->irq; i2c_set_clientdata(client, tas2764); @@ -752,7 +788,8 @@ MODULE_DEVICE_TABLE(i2c, tas2764_i2c_id); #if defined(CONFIG_OF) static const struct of_device_id tas2764_of_match[] = { - { .compatible = "ti,tas2764" }, + { .compatible = "ti,tas2764", .data = (void *)DEVID_TAS2764 }, + { .compatible = "ti,sn012776", .data = (void *)DEVID_SN012776 }, {}, }; MODULE_DEVICE_TABLE(of, tas2764_of_match); diff --git a/sound/soc/codecs/tas2764.h b/sound/soc/codecs/tas2764.h index 9490f2686e38..69c0f91cb423 100644 --- a/sound/soc/codecs/tas2764.h +++ b/sound/soc/codecs/tas2764.h @@ -29,6 +29,7 @@ #define TAS2764_PWR_CTRL_ACTIVE 0x0 #define TAS2764_PWR_CTRL_MUTE BIT(0) #define TAS2764_PWR_CTRL_SHUTDOWN BIT(1) +#define TAS2764_PWR_CTRL_BOP_SRC BIT(7) #define TAS2764_VSENSE_POWER_EN 3 #define TAS2764_ISENSE_POWER_EN 4 @@ -116,4 +117,6 @@ #define TAS2764_INT_CLK_CFG TAS2764_REG(0x0, 0x5c) #define TAS2764_INT_CLK_CFG_IRQZ_CLR BIT(2) +#define TAS2764_BOP_CFG0 TAS2764_REG(0X0, 0x1d) + #endif /* __TAS2764__ */ -- 2.51.0 From f8d5f28e3f2ece5a1392205022afe30c87107a9b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Martin=20Povi=C5=A1er?= Date: Thu, 27 Feb 2025 22:07:31 +1000 Subject: [PATCH 07/16] ASoC: tas2764: Add control concerning overcurrent events MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Add control to expose the option of autoretry behavior on overcurrent events in the codec. Reviewed-by: Neal Gompa Signed-off-by: Martin Povišer Signed-off-by: James Calligeros Link: https://patch.msgid.link/20250227-apple-codec-changes-v3-4-cbb130030acf@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2764.c | 9 +++++++++ sound/soc/codecs/tas2764.h | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index d9b4f898789f..08aa7ee34256 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -634,12 +634,21 @@ static SOC_ENUM_SINGLE_DECL( tas2764_hpf_enum, TAS2764_DC_BLK0, TAS2764_DC_BLK0_HPF_FREQ_PB_SHIFT, tas2764_hpf_texts); +static const char * const tas2764_oce_texts[] = { + "Disable", "Retry", +}; + +static SOC_ENUM_SINGLE_DECL( + tas2764_oce_enum, TAS2764_MISC_CFG1, + TAS2764_MISC_CFG1_OCE_RETRY_SHIFT, tas2764_oce_texts); + static const struct snd_kcontrol_new tas2764_snd_controls[] = { SOC_SINGLE_TLV("Speaker Volume", TAS2764_DVC, 0, TAS2764_DVC_MAX, 1, tas2764_playback_volume), SOC_SINGLE_TLV("Amp Gain Volume", TAS2764_CHNL_0, 1, 0x14, 0, tas2764_digital_tlv), SOC_ENUM("HPF Corner Frequency", tas2764_hpf_enum), + SOC_ENUM("OCE Handling", tas2764_oce_enum), }; static const struct snd_soc_component_driver soc_component_driver_tas2764 = { diff --git a/sound/soc/codecs/tas2764.h b/sound/soc/codecs/tas2764.h index 69c0f91cb423..3251dc0106e0 100644 --- a/sound/soc/codecs/tas2764.h +++ b/sound/soc/codecs/tas2764.h @@ -44,6 +44,10 @@ #define TAS2764_CHNL_0 TAS2764_REG(0X0, 0x03) +/* Miscellaneous */ +#define TAS2764_MISC_CFG1 TAS2764_REG(0x0, 0x06) +#define TAS2764_MISC_CFG1_OCE_RETRY_SHIFT 5 + /* TDM Configuration Reg0 */ #define TAS2764_TDM_CFG0 TAS2764_REG(0X0, 0x08) #define TAS2764_TDM_CFG0_SMP_MASK BIT(5) -- 2.51.0 From 6553ee024b4452ef861de10605156c9d79e208ab Mon Sep 17 00:00:00 2001 From: =?utf8?q?Martin=20Povi=C5=A1er?= Date: Thu, 27 Feb 2025 22:07:32 +1000 Subject: [PATCH 08/16] ASoC: tas2770: Factor out set_ivsense_slots MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Add a new explicit function for the setting of I/V sense TDM slots. Reviewed-by: Neal Gompa Signed-off-by: Martin Povišer Signed-off-by: James Calligeros Link: https://patch.msgid.link/20250227-apple-codec-changes-v3-5-cbb130030acf@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2770.c | 40 +++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index 863c3f672ba9..4a86fcec0c1e 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -189,6 +189,31 @@ static int tas2770_mute(struct snd_soc_dai *dai, int mute, int direction) return tas2770_update_pwr_ctrl(tas2770); } +static int tas2770_set_ivsense_transmit(struct tas2770_priv *tas2770, + int i_slot, int v_slot) +{ + struct snd_soc_component *component = tas2770->component; + int ret; + + ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG5, + TAS2770_TDM_CFG_REG5_VSNS_MASK | + TAS2770_TDM_CFG_REG5_50_MASK, + TAS2770_TDM_CFG_REG5_VSNS_ENABLE | + v_slot); + if (ret < 0) + return ret; + + ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG6, + TAS2770_TDM_CFG_REG6_ISNS_MASK | + TAS2770_TDM_CFG_REG6_50_MASK, + TAS2770_TDM_CFG_REG6_ISNS_ENABLE | + i_slot); + if (ret < 0) + return ret; + + return 0; +} + static int tas2770_set_bitwidth(struct tas2770_priv *tas2770, int bitwidth) { int ret; @@ -221,19 +246,8 @@ static int tas2770_set_bitwidth(struct tas2770_priv *tas2770, int bitwidth) if (ret < 0) return ret; - ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG5, - TAS2770_TDM_CFG_REG5_VSNS_MASK | - TAS2770_TDM_CFG_REG5_50_MASK, - TAS2770_TDM_CFG_REG5_VSNS_ENABLE | - tas2770->v_sense_slot); - if (ret < 0) - return ret; - - ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG6, - TAS2770_TDM_CFG_REG6_ISNS_MASK | - TAS2770_TDM_CFG_REG6_50_MASK, - TAS2770_TDM_CFG_REG6_ISNS_ENABLE | - tas2770->i_sense_slot); + ret = tas2770_set_ivsense_transmit(tas2770, tas2770->i_sense_slot, + tas2770->v_sense_slot); if (ret < 0) return ret; -- 2.51.0 From f0066c8d1d3298e9f9d136a365139bac733e84c5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Martin=20Povi=C5=A1er?= Date: Thu, 27 Feb 2025 22:07:33 +1000 Subject: [PATCH 09/16] ASoC: tas2770: Fix and redo I/V sense TDM slot setting logic MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The former code sets the V slot from inside set_bitwidth according to the bitwidth of the PCM format. That's wrong, since: * It overrides the V slot parsed from DT binding. * The V slot is set shifted behind the I slot by the length of the PCM bitwidth, but the PCM bitwidth has no assured relation to the TDM slot width. Replace the former logic by setting up the I/V sense transmission only in case of both I/V slots being specified in devicetree, and never override those values. In case the slots are left unspecified, disable the transmission completely. There's an improbable case someone is relying on the old behavior, but if so, that's a setup that only works by accident, and cannot be sanely supported going forward. There's no indication anyone is consuming the I/V sense data up to today, so break the former behavior. Reviewed-by: Neal Gompa Signed-off-by: Martin Povišer Signed-off-by: James Calligeros Link: https://patch.msgid.link/20250227-apple-codec-changes-v3-6-cbb130030acf@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2770.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index 4a86fcec0c1e..7f219df8be70 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -224,19 +224,16 @@ static int tas2770_set_bitwidth(struct tas2770_priv *tas2770, int bitwidth) ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2, TAS2770_TDM_CFG_REG2_RXW_MASK, TAS2770_TDM_CFG_REG2_RXW_16BITS); - tas2770->v_sense_slot = tas2770->i_sense_slot + 2; break; case SNDRV_PCM_FORMAT_S24_LE: ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2, TAS2770_TDM_CFG_REG2_RXW_MASK, TAS2770_TDM_CFG_REG2_RXW_24BITS); - tas2770->v_sense_slot = tas2770->i_sense_slot + 4; break; case SNDRV_PCM_FORMAT_S32_LE: ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG2, TAS2770_TDM_CFG_REG2_RXW_MASK, TAS2770_TDM_CFG_REG2_RXW_32BITS); - tas2770->v_sense_slot = tas2770->i_sense_slot + 4; break; default: @@ -246,11 +243,6 @@ static int tas2770_set_bitwidth(struct tas2770_priv *tas2770, int bitwidth) if (ret < 0) return ret; - ret = tas2770_set_ivsense_transmit(tas2770, tas2770->i_sense_slot, - tas2770->v_sense_slot); - if (ret < 0) - return ret; - return 0; } @@ -505,6 +497,7 @@ static int tas2770_codec_probe(struct snd_soc_component *component) { struct tas2770_priv *tas2770 = snd_soc_component_get_drvdata(component); + int ret; tas2770->component = component; @@ -516,6 +509,14 @@ static int tas2770_codec_probe(struct snd_soc_component *component) tas2770_reset(tas2770); regmap_reinit_cache(tas2770->regmap, &tas2770_i2c_regmap); + if (tas2770->i_sense_slot != -1 && tas2770->v_sense_slot != -1) { + ret = tas2770_set_ivsense_transmit(tas2770, tas2770->i_sense_slot, + tas2770->v_sense_slot); + + if (ret < 0) + return ret; + } + return 0; } @@ -643,7 +644,7 @@ static int tas2770_parse_dt(struct device *dev, struct tas2770_priv *tas2770) dev_info(tas2770->dev, "Property %s is missing setting default slot\n", "ti,imon-slot-no"); - tas2770->i_sense_slot = 0; + tas2770->i_sense_slot = -1; } rc = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no", @@ -652,7 +653,7 @@ static int tas2770_parse_dt(struct device *dev, struct tas2770_priv *tas2770) dev_info(tas2770->dev, "Property %s is missing setting default slot\n", "ti,vmon-slot-no"); - tas2770->v_sense_slot = 2; + tas2770->v_sense_slot = -1; } tas2770->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH); -- 2.51.0 From 7bda89a2489fb012c4c63f3338827ad1f35c8880 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Sat, 15 Feb 2025 11:02:23 +1300 Subject: [PATCH 10/16] ASoC: dt-bindings: sun4i-a10-codec: add hp-det-gpios Devices integrating Allwinner SoCs may use line-out or headphone jacks with jack detection circuits attached to a GPIO. Support defining these in DTs. A number of Anbernic devices featuring the H700 SoC use this mechanism to switch between a headphone jack and an internal speaker, so add these to the allowed routing items. Signed-off-by: Chris Morgan Signed-off-by: Ryan Walklin Reviewed-by: Rob Herring (Arm) -- Changelog v1..v2: - Remove vendor prefix from hp-det-gpios Changelog v2..v3: - Add Reviewed-by tag Reviewed-by: Rob Herring (Arm) Tested-by: Philippe Simons Link: https://patch.msgid.link/20250214220247.10810-2-ryan@testtoast.com Signed-off-by: Mark Brown --- .../bindings/sound/allwinner,sun4i-a10-codec.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml index ccae64ce3071..b4eca702febc 100644 --- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml +++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml @@ -102,6 +102,10 @@ properties: maxItems: 1 description: GPIO to enable the external amplifier + hp-det-gpios: + maxItems: 1 + description: GPIO for headphone/line-out detection + required: - "#sound-dai-cells" - compatible @@ -251,8 +255,10 @@ allOf: allwinner,audio-routing: items: enum: + - Headphone - LINEOUT - Line Out + - Speaker dmas: items: -- 2.51.0 From ae5f76d4044d1580849316c49290678605e0889d Mon Sep 17 00:00:00 2001 From: Ryan Walklin Date: Sat, 15 Feb 2025 11:02:24 +1300 Subject: [PATCH 11/16] ASoC: sun4i-codec: correct dapm widgets and controls for h616 The previous H616 support patch added a single LINEOUT DAPM pin switch to the card controls. As the codec in this SoC only has a single route, this seemed reasonable at the time, however is redundant given the existing DAPM codec widget definitions controlling the digital and analog sides of the codec. It is also insufficient to describe the scenario where separate components (muxes, jack detection etc) are used to modify the audio route external to the SoC. For example the Anbernic RG(##)XX series of devices uses a headphone jack detection switch, GPIO-controlled speaker amplifier and a passive external mux chip to route audio. Remove the redundant LINEOUT card control, and add a Speaker pin switch control and Headphone DAPM widget to allow control of the above hardware. Signed-off-by: Chris Morgan Signed-off-by: Ryan Walklin Tested-by: Philippe Simons Link: https://patch.msgid.link/20250214220247.10810-3-ryan@testtoast.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-codec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 886b3fa537d2..f24bbefeb392 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -1916,10 +1916,11 @@ static const struct snd_soc_component_driver sun50i_h616_codec_codec = { }; static const struct snd_kcontrol_new sun50i_h616_card_controls[] = { - SOC_DAPM_PIN_SWITCH("LINEOUT"), + SOC_DAPM_PIN_SWITCH("Speaker"), }; static const struct snd_soc_dapm_widget sun50i_h616_codec_card_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_LINE("Line Out", NULL), SND_SOC_DAPM_SPK("Speaker", sun4i_codec_spk_event), }; -- 2.51.0 From a149377c033afe6557c50892ebbfc0e8b7e2e253 Mon Sep 17 00:00:00 2001 From: Ryan Walklin Date: Sat, 15 Feb 2025 11:02:25 +1300 Subject: [PATCH 12/16] ASoC: sun4i-codec: support hp-det-gpios property Add support for GPIO headphone detection with the hp-det-gpios property. In order for this to properly disable the path upon removal of headphones, the output must be labelled Headphone which is a common sink in the driver. Describe a headphone jack and detection GPIO in the driver, check for a corresponding device tree node, and enable jack detection in a new machine init function if described. Signed-off-by: Chris Morgan Signed-off-by: Ryan Walklin -- Changelog v1..v2: - Separate DAPM changes into separate patch and add rationale. Tested-by: Philippe Simons Link: https://patch.msgid.link/20250214220247.10810-4-ryan@testtoast.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-codec.c | 53 +++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index f24bbefeb392..3701f56c7275 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -331,6 +332,7 @@ struct sun4i_codec { struct clk *clk_module; struct reset_control *rst; struct gpio_desc *gpio_pa; + struct gpio_desc *gpio_hp; /* ADC_FIFOC register is at different offset on different SoCs */ struct regmap_field *reg_adc_fifoc; @@ -1583,6 +1585,49 @@ static struct snd_soc_dai_driver dummy_cpu_dai = { .ops = &dummy_dai_ops, }; +static struct snd_soc_jack sun4i_headphone_jack; + +static struct snd_soc_jack_pin sun4i_headphone_jack_pins[] = { + { .pin = "Headphone", .mask = SND_JACK_HEADPHONE }, +}; + +static struct snd_soc_jack_gpio sun4i_headphone_jack_gpio = { + .name = "hp-det", + .report = SND_JACK_HEADPHONE, + .debounce_time = 150, +}; + +static int sun4i_codec_machine_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct sun4i_codec *scodec = snd_soc_card_get_drvdata(card); + int ret; + + if (scodec->gpio_hp) { + ret = snd_soc_card_jack_new_pins(card, "Headphone Jack", + SND_JACK_HEADPHONE, + &sun4i_headphone_jack, + sun4i_headphone_jack_pins, + ARRAY_SIZE(sun4i_headphone_jack_pins)); + if (ret) { + dev_err(rtd->dev, + "Headphone jack creation failed: %d\n", ret); + return ret; + } + + sun4i_headphone_jack_gpio.desc = scodec->gpio_hp; + ret = snd_soc_jack_add_gpios(&sun4i_headphone_jack, 1, + &sun4i_headphone_jack_gpio); + + if (ret) { + dev_err(rtd->dev, "Headphone GPIO not added: %d\n", ret); + return ret; + } + } + + return 0; +} + static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev, int *num_links) { @@ -1608,6 +1653,7 @@ static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev, link->codecs->name = dev_name(dev); link->platforms->name = dev_name(dev); link->dai_fmt = SND_SOC_DAIFMT_I2S; + link->init = sun4i_codec_machine_init; *num_links = 1; @@ -2302,6 +2348,13 @@ static int sun4i_codec_probe(struct platform_device *pdev) return ret; } + scodec->gpio_hp = devm_gpiod_get_optional(&pdev->dev, "hp-det", GPIOD_IN); + if (IS_ERR(scodec->gpio_hp)) { + ret = PTR_ERR(scodec->gpio_hp); + dev_err_probe(&pdev->dev, ret, "Failed to get hp-det gpio\n"); + return ret; + } + /* reg_field setup */ scodec->reg_adc_fifoc = devm_regmap_field_alloc(&pdev->dev, scodec->regmap, -- 2.51.0 From d389719fb4ece17ea28c0cf908066815d3ab0e25 Mon Sep 17 00:00:00 2001 From: Ryan Walklin Date: Sat, 15 Feb 2025 11:02:27 +1300 Subject: [PATCH 13/16] ASoC: sun4i-codec: add h616 card long_name Adding jack detection requires sound servers to act on the emitted events, which are described by ALSA Use Case Manager configurations in userspace. These configurations include the long card name in the file path (falling back to card->name if this is not present), so add a long card name for the H616 without spaces, making UCM referencing easier. The corresponding ALSA UCM patch is here (now merged): https://github.com/alsa-project/alsa-ucm-conf/pull/491 Signed-off-by: Ryan Walklin -- Changelog v1..v2: - Separate patch for card->long_name - Note UCM patch link Changelog v2..v3: - Add card->long_name rather than change existing card->name Link: https://patch.msgid.link/20250214220247.10810-6-ryan@testtoast.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-codec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 3701f56c7275..93733ff2e32a 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -2013,6 +2013,7 @@ static struct snd_soc_card *sun50i_h616_codec_create_card(struct device *dev) card->dev = dev; card->owner = THIS_MODULE; card->name = "H616 Audio Codec"; + card->long_name = "h616-audio-codec"; card->driver_name = "sun4i-codec"; card->controls = sun50i_h616_card_controls; card->num_controls = ARRAY_SIZE(sun50i_h616_card_controls); -- 2.51.0 From 3fec903f2cb18805b1ef22a0e310498020c1f15e Mon Sep 17 00:00:00 2001 From: =?utf8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Thu, 6 Mar 2025 16:52:15 -0300 Subject: [PATCH 14/16] ASoC: dt-bindings: mediatek,mt8188-mt6359: Add mediatek,accdet MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Add a mediatek,accdet phandle property to allow getting a reference to the MT6359 ACCDET block, which is responsible for detecting jack insertion/removal. Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Rob Herring (Arm) Signed-off-by: Nícolas F. R. A. Prado Link: https://patch.msgid.link/20250306-mt8188-accdet-v3-1-7828e835ff4b@collabora.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml index 8c77e7f68ad7..76d5a437dc8f 100644 --- a/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml +++ b/Documentation/devicetree/bindings/sound/mediatek,mt8188-mt6359.yaml @@ -40,6 +40,14 @@ properties: hardware that provides additional audio functionalities if present. The AFE will link to ADSP when the phandle is provided. + mediatek,accdet: + $ref: /schemas/types.yaml#/definitions/phandle + description: + The phandle to the MT6359 accessory detection block, which detects audio + jack insertion and removal. This property should only be present if the + accdet block is actually wired to the audio jack pins and to be used for + jack detection. + patternProperties: "^dai-link-[0-9]+$": type: object -- 2.51.0 From cf536e2622e2b0a60c99e799995b6e9acf539c17 Mon Sep 17 00:00:00 2001 From: =?utf8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Thu, 6 Mar 2025 16:52:16 -0300 Subject: [PATCH 15/16] ASoC: mediatek: common: Handle mediatek,accdet property MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Handle the optional mediatek,accdet property. When present, retrieve the sound component from its phandle, so the machine sound driver can use it to register the audio jack and initialize the MT6359 ACCDET for jack detection. Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Nícolas F. R. A. Prado Link: https://patch.msgid.link/20250306-mt8188-accdet-v3-2-7828e835ff4b@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-soc-card.h | 1 + .../mediatek/common/mtk-soundcard-driver.c | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/sound/soc/mediatek/common/mtk-soc-card.h b/sound/soc/mediatek/common/mtk-soc-card.h index 3f6e24dd22df..a1d2794ac1f7 100644 --- a/sound/soc/mediatek/common/mtk-soc-card.h +++ b/sound/soc/mediatek/common/mtk-soc-card.h @@ -16,6 +16,7 @@ struct mtk_soc_card_data { const struct mtk_sof_priv *sof_priv; struct list_head sof_dai_link_list; struct mtk_platform_card_data *card_data; + struct snd_soc_component *accdet; void *mach_priv; }; diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c index f4314dddc460..713a368f79cf 100644 --- a/sound/soc/mediatek/common/mtk-soundcard-driver.c +++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c @@ -8,6 +8,7 @@ #include #include +#include #include #include "mtk-dsp-sof-common.h" @@ -192,7 +193,9 @@ EXPORT_SYMBOL_GPL(mtk_soundcard_common_capture_ops); int mtk_soundcard_common_probe(struct platform_device *pdev) { - struct device_node *platform_node, *adsp_node; + struct device_node *platform_node, *adsp_node, *accdet_node; + struct snd_soc_component *accdet_comp; + struct platform_device *accdet_pdev; const struct mtk_soundcard_pdata *pdata; struct mtk_soc_card_data *soc_card_data; struct snd_soc_dai_link *orig_dai_link, *dai_link; @@ -250,6 +253,20 @@ int mtk_soundcard_common_probe(struct platform_device *pdev) soc_card_data->card_data->jacks = jacks; + accdet_node = of_parse_phandle(pdev->dev.of_node, "mediatek,accdet", 0); + if (accdet_node) { + accdet_pdev = of_find_device_by_node(accdet_node); + if (accdet_pdev) { + accdet_comp = snd_soc_lookup_component(&accdet_pdev->dev, NULL); + if (accdet_comp) + soc_card_data->accdet = accdet_comp; + else + dev_err(&pdev->dev, "No sound component found from mediatek,accdet property\n"); + } else { + dev_err(&pdev->dev, "No device found from mediatek,accdet property\n"); + } + } + platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); if (!platform_node) return dev_err_probe(&pdev->dev, -EINVAL, -- 2.51.0 From 0116a7d84b32537a10d9bea1fd1bfc06577ef527 Mon Sep 17 00:00:00 2001 From: =?utf8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Thu, 6 Mar 2025 16:52:17 -0300 Subject: [PATCH 16/16] ASoC: mediatek: mt6359: Add stub for mt6359_accdet_enable_jack_detect MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Add a stub for mt6359_accdet_enable_jack_detect() to prevent linker failures in the machine sound drivers calling it when CONFIG_SND_SOC_MT6359_ACCDET is not enabled. Suggested-by: AngeloGioacchino Del Regno Signed-off-by: Nícolas F. R. A. Prado Link: https://patch.msgid.link/20250306-mt8188-accdet-v3-3-7828e835ff4b@collabora.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6359-accdet.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h index c234f2f4276a..78ada3a5bfae 100644 --- a/sound/soc/codecs/mt6359-accdet.h +++ b/sound/soc/codecs/mt6359-accdet.h @@ -123,6 +123,15 @@ struct mt6359_accdet { struct workqueue_struct *jd_workqueue; }; +#if IS_ENABLED(CONFIG_SND_SOC_MT6359_ACCDET) int mt6359_accdet_enable_jack_detect(struct snd_soc_component *component, struct snd_soc_jack *jack); +#else +static inline int +mt6359_accdet_enable_jack_detect(struct snd_soc_component *component, + struct snd_soc_jack *jack) +{ + return -EOPNOTSUPP; +} +#endif #endif -- 2.51.0