* [PATCH v3 01/20] ASoC: dt-bindings: tas27xx: add compatible for SN012776
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 12:07 ` [PATCH v3 02/20] ASoC: dt-bindings: tas2770: add compatible for TAS5770L James Calligeros
` (20 subsequent siblings)
21 siblings, 0 replies; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
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 <neal@gompa.dev>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
.../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 5447482179c14ee78885e5bee02f4549428694a6..fcaae848e78a1137e4d44f98258207bba68772b9 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.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v3 02/20] ASoC: dt-bindings: tas2770: add compatible for TAS5770L
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
2025-02-27 12:07 ` [PATCH v3 01/20] ASoC: dt-bindings: tas27xx: add compatible for SN012776 James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 12:07 ` [PATCH v3 03/20] ASoC: tas2764: Extend driver to SN012776 James Calligeros
` (19 subsequent siblings)
21 siblings, 0 replies; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
A variant of TAS2770 known as TAS5770L is found in Apple Silicon Macs.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
.../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 5e7aea43acedc0f7d8c22e36debfe805c7ebe74f..8eab98a0f7a25a9c87d2c56fd0635ff8ecee17d0 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.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v3 03/20] ASoC: tas2764: Extend driver to SN012776
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
2025-02-27 12:07 ` [PATCH v3 01/20] ASoC: dt-bindings: tas27xx: add compatible for SN012776 James Calligeros
2025-02-27 12:07 ` [PATCH v3 02/20] ASoC: dt-bindings: tas2770: add compatible for TAS5770L James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 12:07 ` [PATCH v3 04/20] ASoC: tas2764: Add control concerning overcurrent events James Calligeros
` (18 subsequent siblings)
21 siblings, 0 replies; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
From: Martin Povišer <povik+lin@cutebit.org>
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 <neal@gompa.dev>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
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 c0a1d0c2a93890105a169717a7fb75ec05f93146..d9b4f898789fa9b59c94c97e3b130950b88c3a76 100644
--- a/sound/soc/codecs/tas2764.c
+++ b/sound/soc/codecs/tas2764.c
@@ -14,6 +14,7 @@
#include <linux/regulator/consumer.h>
#include <linux/regmap.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/slab.h>
#include <sound/soc.h>
#include <sound/pcm.h>
@@ -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 9490f2686e38919a726e649884d9b6ad761493a2..69c0f91cb423986f7f0ded0b2160927f024d957d 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.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v3 04/20] ASoC: tas2764: Add control concerning overcurrent events
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (2 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 03/20] ASoC: tas2764: Extend driver to SN012776 James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 12:07 ` [PATCH v3 05/20] ASoC: tas2770: Factor out set_ivsense_slots James Calligeros
` (17 subsequent siblings)
21 siblings, 0 replies; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
From: Martin Povišer <povik+lin@cutebit.org>
Add control to expose the option of autoretry behavior on overcurrent
events in the codec.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
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 d9b4f898789fa9b59c94c97e3b130950b88c3a76..08aa7ee34256896915f3ed6438b8b8827ce240c7 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 69c0f91cb423986f7f0ded0b2160927f024d957d..3251dc0106e07862dd69efd69fa0e40c3858ecb7 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.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v3 05/20] ASoC: tas2770: Factor out set_ivsense_slots
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (3 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 04/20] ASoC: tas2764: Add control concerning overcurrent events James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 12:07 ` [PATCH v3 06/20] ASoC: tas2770: Fix and redo I/V sense TDM slot setting logic James Calligeros
` (16 subsequent siblings)
21 siblings, 0 replies; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
From: Martin Povišer <povik+lin@cutebit.org>
Add a new explicit function for the setting of I/V sense TDM slots.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
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 863c3f672ba98dd74a5ba1b15d650a90f91176a1..4a86fcec0c1ecab45b9ebcdfc90c78f3290c6fa6 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.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v3 06/20] ASoC: tas2770: Fix and redo I/V sense TDM slot setting logic
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (4 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 05/20] ASoC: tas2770: Factor out set_ivsense_slots James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 12:07 ` [PATCH v3 07/20] ASoC: tas2764: Reinit cache on part reset James Calligeros
` (15 subsequent siblings)
21 siblings, 0 replies; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
From: Martin Povišer <povik+lin@cutebit.org>
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 <neal@gompa.dev>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
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 4a86fcec0c1ecab45b9ebcdfc90c78f3290c6fa6..7f219df8be7046912bf3ef452f75c17b5118bcf6 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.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v3 07/20] ASoC: tas2764: Reinit cache on part reset
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (5 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 06/20] ASoC: tas2770: Fix and redo I/V sense TDM slot setting logic James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 14:09 ` Mark Brown
2025-02-27 12:07 ` [PATCH v3 08/20] ASoC: dt-bindings: tas27xx: document ti,sdout-force-zero-mask property James Calligeros
` (14 subsequent siblings)
21 siblings, 1 reply; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
From: Martin Povišer <povik+lin@cutebit.org>
When the part is reset in component_probe, do not forget to reinit the
regcache, otherwise the cache can get out of sync with the part's
actual state. This fix is similar to commit 0a0342ede303
("ASoC: tas2770: Reinit regcache on reset") which concerned the
tas2770 driver.
Fixes: 827ed8a0fa50 ("ASoC: tas2764: Add the driver for the TAS2764")
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
sound/soc/codecs/tas2764.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
index 08aa7ee34256896915f3ed6438b8b8827ce240c7..49b73b74b2d9dd6d09747cabc2b00519c549775d 100644
--- a/sound/soc/codecs/tas2764.c
+++ b/sound/soc/codecs/tas2764.c
@@ -546,6 +546,8 @@ static uint8_t sn012776_bop_presets[] = {
0x06, 0x3e, 0x37, 0x30, 0xff, 0xe6
};
+static const struct regmap_config tas2764_i2c_regmap;
+
static int tas2764_codec_probe(struct snd_soc_component *component)
{
struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
@@ -559,6 +561,7 @@ static int tas2764_codec_probe(struct snd_soc_component *component)
}
tas2764_reset(tas2764);
+ regmap_reinit_cache(tas2764->regmap, &tas2764_i2c_regmap);
if (tas2764->irq) {
ret = snd_soc_component_write(tas2764->component, TAS2764_INT_MASK0, 0xff);
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: [PATCH v3 07/20] ASoC: tas2764: Reinit cache on part reset
2025-02-27 12:07 ` [PATCH v3 07/20] ASoC: tas2764: Reinit cache on part reset James Calligeros
@ 2025-02-27 14:09 ` Mark Brown
0 siblings, 0 replies; 40+ messages in thread
From: Mark Brown @ 2025-02-27 14:09 UTC (permalink / raw)
To: James Calligeros
Cc: Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Shenghao Ding,
Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Shi Fu, Jean Delvare, Guenter Roeck,
Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa
[-- Attachment #1: Type: text/plain, Size: 652 bytes --]
On Thu, Feb 27, 2025 at 10:07:34PM +1000, James Calligeros wrote:
> From: Martin Povišer <povik+lin@cutebit.org>
>
> When the part is reset in component_probe, do not forget to reinit the
> regcache, otherwise the cache can get out of sync with the part's
> actual state. This fix is similar to commit 0a0342ede303
> ("ASoC: tas2770: Reinit regcache on reset") which concerned the
> tas2770 driver.
>
> Fixes: 827ed8a0fa50 ("ASoC: tas2764: Add the driver for the TAS2764")
As previously and repeatedly mentioned please put fixes at the start of
patch serieses so they don't end up with spurious dependencies on other
non-fix patches.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v3 08/20] ASoC: dt-bindings: tas27xx: document ti,sdout-force-zero-mask property
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (6 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 07/20] ASoC: tas2764: Reinit cache on part reset James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-28 20:22 ` Rob Herring (Arm)
2025-02-27 12:07 ` [PATCH v3 09/20] ASoC: tas2764: Configure zeroing of SDOUT slots James Calligeros
` (13 subsequent siblings)
21 siblings, 1 reply; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
James Calligeros
TAS2764 can be programmed to zero-fill/ignore certain TDM slots on a
shared I2S bus. Since this is a per-chip setting that is a consequence
of how it is implemented on a specific board, express this as a Devicetree
property.
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
.../bindings/sound/ti,tas27xx.yaml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml b/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml
index fcaae848e78a1137e4d44f98258207bba68772b9..d65a278c92873b00bf357fb26b430386e7860e54 100644
--- a/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tas27xx.yaml
@@ -50,6 +50,10 @@ properties:
$ref: /schemas/types.yaml#/definitions/uint32
description: TDM TX voltage sense time slot.
+ ti,sdout-force-zero-mask:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: Mask of TDM slots to zero-fill on a shared I2S bus.
+
'#sound-dai-cells':
# The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward
# compatibility but is deprecated.
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: [PATCH v3 08/20] ASoC: dt-bindings: tas27xx: document ti,sdout-force-zero-mask property
2025-02-27 12:07 ` [PATCH v3 08/20] ASoC: dt-bindings: tas27xx: document ti,sdout-force-zero-mask property James Calligeros
@ 2025-02-28 20:22 ` Rob Herring (Arm)
0 siblings, 0 replies; 40+ messages in thread
From: Rob Herring (Arm) @ 2025-02-28 20:22 UTC (permalink / raw)
To: James Calligeros
Cc: Baojun Xu, Takashi Iwai, Alyssa Rosenzweig, Shi Fu, linux-hwmon,
Jean Delvare, Kevin Lu, Mark Brown, Conor Dooley,
Krzysztof Kozlowski, Guenter Roeck, linux-kernel, Dan Murphy,
devicetree, Hector Martin, Jaroslav Kysela, Martin Povišer,
asahi, linux-sound, Liam Girdwood, Shenghao Ding
On Thu, 27 Feb 2025 22:07:35 +1000, James Calligeros wrote:
> TAS2764 can be programmed to zero-fill/ignore certain TDM slots on a
> shared I2S bus. Since this is a per-chip setting that is a consequence
> of how it is implemented on a specific board, express this as a Devicetree
> property.
>
> Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
> ---
> .../bindings/sound/ti,tas27xx.yaml | 4 ++++
> 1 file changed, 4 insertions(+)
>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v3 09/20] ASoC: tas2764: Configure zeroing of SDOUT slots
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (7 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 08/20] ASoC: dt-bindings: tas27xx: document ti,sdout-force-zero-mask property James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 12:07 ` [PATCH v3 10/20] ASoC: tas2764: Apply Apple quirks James Calligeros
` (12 subsequent siblings)
21 siblings, 0 replies; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
From: Martin Povišer <povik+lin@cutebit.org>
The codec has an option to zero out certain TDM slots on its SDOUT
output according to a preconfigured mask (otherwise the output is, for
the duration of unused slots, in a Hi-Z state).
Since the programmed value is dependent on how the chip is implemented
on a given board, configure this feature based on a mask read from the
specific codec's Devicetree node.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
sound/soc/codecs/tas2764.c | 23 +++++++++++++++++++++++
sound/soc/codecs/tas2764.h | 11 +++++++++++
2 files changed, 34 insertions(+)
diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
index 49b73b74b2d9dd6d09747cabc2b00519c549775d..f33ac89ffc598c39f3a7e0d620724098ca5bc3d3 100644
--- a/sound/soc/codecs/tas2764.c
+++ b/sound/soc/codecs/tas2764.c
@@ -40,6 +40,7 @@ struct tas2764_priv {
int v_sense_slot;
int i_sense_slot;
+ u32 sdout_zero_mask;
bool dac_powered;
bool unmuted;
@@ -601,6 +602,23 @@ static int tas2764_codec_probe(struct snd_soc_component *component)
if (ret < 0)
return ret;
+ if (tas2764->sdout_zero_mask) {
+ for (i = 0; i < 4; i++) {
+ ret = snd_soc_component_write(component, TAS2764_SDOUT_HIZ_1 + i,
+ (tas2764->sdout_zero_mask >> (i * 8)) & 0xff);
+
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = snd_soc_component_update_bits(component, TAS2764_SDOUT_HIZ_9,
+ TAS2764_SDOUT_HIZ_9_FORCE_0_EN,
+ TAS2764_SDOUT_HIZ_9_FORCE_0_EN);
+
+ if (ret < 0)
+ return ret;
+ }
+
switch (tas2764->devid) {
case DEVID_SN012776:
ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
@@ -749,6 +767,11 @@ static int tas2764_parse_dt(struct device *dev, struct tas2764_priv *tas2764)
if (ret)
tas2764->v_sense_slot = 2;
+ ret = fwnode_property_read_u32(dev->fwnode, "ti,sdout-force-zero-mask",
+ &tas2764->sdout_zero_mask);
+ if (ret)
+ tas2764->sdout_zero_mask = 0;
+
return 0;
}
diff --git a/sound/soc/codecs/tas2764.h b/sound/soc/codecs/tas2764.h
index 3251dc0106e07862dd69efd69fa0e40c3858ecb7..4cf0f7f112d6c3002203fa32e900efd640ef3f22 100644
--- a/sound/soc/codecs/tas2764.h
+++ b/sound/soc/codecs/tas2764.h
@@ -123,4 +123,15 @@
#define TAS2764_BOP_CFG0 TAS2764_REG(0X0, 0x1d)
+#define TAS2764_SDOUT_HIZ_1 TAS2764_REG(0x1, 0x3d)
+#define TAS2764_SDOUT_HIZ_2 TAS2764_REG(0x1, 0x3e)
+#define TAS2764_SDOUT_HIZ_3 TAS2764_REG(0x1, 0x3f)
+#define TAS2764_SDOUT_HIZ_4 TAS2764_REG(0x1, 0x40)
+#define TAS2764_SDOUT_HIZ_5 TAS2764_REG(0x1, 0x41)
+#define TAS2764_SDOUT_HIZ_6 TAS2764_REG(0x1, 0x42)
+#define TAS2764_SDOUT_HIZ_7 TAS2764_REG(0x1, 0x43)
+#define TAS2764_SDOUT_HIZ_8 TAS2764_REG(0x1, 0x44)
+#define TAS2764_SDOUT_HIZ_9 TAS2764_REG(0x1, 0x45)
+#define TAS2764_SDOUT_HIZ_9_FORCE_0_EN BIT(7)
+
#endif /* __TAS2764__ */
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v3 10/20] ASoC: tas2764: Apply Apple quirks
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (8 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 09/20] ASoC: tas2764: Configure zeroing of SDOUT slots James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 12:07 ` [PATCH v3 11/20] ASoC: tas2764: Raise regmap range maximum James Calligeros
` (11 subsequent siblings)
21 siblings, 0 replies; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
From: Martin Povišer <povik+lin@cutebit.org>
Apple's SN012776 driver has some peculiar aspects to its behavior that
are suspected to work around issues in the codec part. Add a module
parameter for enabling individual quirks that should be imitated after
the Apple driver.
Setting some of these by default seems to be required. For example,
setting 0xf fixes an issue with transient overcurrent errors which
can crash the chip until the next system reboot. To be safe, let's
enable all of them by default.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Co-developed-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
Co-developed-by: James Calligeros <jcalligeros99@gmail.com>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
sound/soc/codecs/tas2764-quirks.h | 180 +++++++++++++++++++++++++
sound/soc/codecs/tas2764.c | 39 ++++++
2 files changed, 219 insertions(+)
diff --git a/sound/soc/codecs/tas2764-quirks.h b/sound/soc/codecs/tas2764-quirks.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a62b3ba5b40b3f06fc1ebeb590d9c32b1b2c7d3
--- /dev/null
+++ b/sound/soc/codecs/tas2764-quirks.h
@@ -0,0 +1,180 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __TAS2764_QUIRKS__
+#define __TAS2764_QUIRKS__
+
+#include <linux/regmap.h>
+
+#include "tas2764.h"
+
+/* Bitmask of enabled Apple quirks */
+#define ENABLED_APPLE_QUIRKS 0x3f
+
+/*
+ * Disable noise gate and flip down reserved bit in NS_CFG0
+ */
+#define TAS2764_NOISE_GATE_DISABLE BIT(0)
+
+static const struct reg_sequence tas2764_noise_gate_dis_seq[] = {
+ REG_SEQ0(TAS2764_REG(0x0, 0x35), 0xb0)
+};
+
+/*
+ * CONV_VBAT_PVDD_MODE=1
+ */
+#define TAS2764_CONV_VBAT_PVDD_MODE BIT(1)
+
+static const struct reg_sequence tas2764_conv_vbat_pvdd_mode_seq[] = {
+ REG_SEQ0(TAS2764_REG(0x0, 0x6b), 0x41)
+};
+
+/*
+ * Reset of DAC modulator when DSP is OFF
+ */
+#define TAS2764_DMOD_RST BIT(2)
+
+static const struct reg_sequence tas2764_dmod_rst_seq[] = {
+ REG_SEQ0(TAS2764_REG(0x0, 0x76), 0x0)
+};
+
+/*
+ * Unknown 0x133/0x137 writes (maybe TDM related)
+ */
+#define TAS2764_UNK_SEQ0 BIT(3)
+
+static const struct reg_sequence tas2764_unk_seq0[] = {
+ REG_SEQ0(TAS2764_REG(0x1, 0x33), 0x80),
+ REG_SEQ0(TAS2764_REG(0x1, 0x37), 0x3a),
+};
+
+/*
+ * Unknown 0x614 - 0x61f writes
+ */
+#define TAS2764_APPLE_UNK_SEQ1 BIT(4)
+
+static const struct reg_sequence tas2764_unk_seq1[] = {
+ REG_SEQ0(TAS2764_REG(0x6, 0x14), 0x0),
+ REG_SEQ0(TAS2764_REG(0x6, 0x15), 0x13),
+ REG_SEQ0(TAS2764_REG(0x6, 0x16), 0x52),
+ REG_SEQ0(TAS2764_REG(0x6, 0x17), 0x0),
+ REG_SEQ0(TAS2764_REG(0x6, 0x18), 0xe4),
+ REG_SEQ0(TAS2764_REG(0x6, 0x19), 0xc),
+ REG_SEQ0(TAS2764_REG(0x6, 0x16), 0xaa),
+ REG_SEQ0(TAS2764_REG(0x6, 0x1b), 0x0),
+ REG_SEQ0(TAS2764_REG(0x6, 0x1c), 0x12),
+ REG_SEQ0(TAS2764_REG(0x6, 0x1d), 0xa0),
+ REG_SEQ0(TAS2764_REG(0x6, 0x1e), 0xd8),
+ REG_SEQ0(TAS2764_REG(0x6, 0x1f), 0x0),
+};
+
+/*
+ * Unknown writes in the 0xfd page (with secondary paging inside)
+ */
+#define TAS2764_APPLE_UNK_SEQ2 BIT(5)
+
+static const struct reg_sequence tas2764_unk_seq2[] = {
+ REG_SEQ0(TAS2764_REG(0xfd, 0x0d), 0xd),
+ REG_SEQ0(TAS2764_REG(0xfd, 0x6c), 0x2),
+ REG_SEQ0(TAS2764_REG(0xfd, 0x6d), 0xf),
+ REG_SEQ0(TAS2764_REG(0xfd, 0x0d), 0x0),
+};
+
+/*
+ * Disable 'Thermal Threshold 1'
+ */
+#define TAS2764_THERMAL_TH1_DISABLE BIT(6)
+
+static const struct reg_sequence tas2764_thermal_th1_dis_seq[] = {
+ REG_SEQ0(TAS2764_REG(0x1, 0x47), 0x2),
+};
+
+/*
+ * Imitate Apple's shutdown dance
+ */
+#define TAS2764_SHUTDOWN_DANCE BIT(7)
+
+static const struct reg_sequence tas2764_shutdown_dance_init_seq[] = {
+ /*
+ * SDZ_MODE=01 (immediate)
+ *
+ * We want the shutdown to happen under the influence of
+ * the magic writes in the 0xfdXX region, so make sure
+ * the shutdown is immediate and there's no grace period
+ * followed by the codec part.
+ */
+ REG_SEQ0(TAS2764_REG(0x0, 0x7), 0x60),
+};
+
+static const struct reg_sequence tas2764_pre_shutdown_seq[] = {
+ REG_SEQ0(TAS2764_REG(0xfd, 0x0d), 0xd), /* switch hidden page */
+ REG_SEQ0(TAS2764_REG(0xfd, 0x64), 0x4), /* do write (unknown semantics) */
+ REG_SEQ0(TAS2764_REG(0xfd, 0x0d), 0x0), /* switch hidden page back */
+};
+
+static const struct reg_sequence tas2764_post_shutdown_seq[] = {
+ REG_SEQ0(TAS2764_REG(0xfd, 0x0d), 0xd),
+ REG_SEQ0(TAS2764_REG(0xfd, 0x64), 0x0), /* revert write from pre sequence */
+ REG_SEQ0(TAS2764_REG(0xfd, 0x0d), 0x0),
+};
+
+static int tas2764_do_quirky_pwr_ctrl_change(struct tas2764_priv *tas2764,
+ unsigned int target)
+{
+ unsigned int curr;
+ int ret;
+
+ curr = snd_soc_component_read_field(tas2764->component,
+ TAS2764_PWR_CTRL,
+ TAS2764_PWR_CTRL_MASK);
+
+ if (target == curr)
+ return 0;
+
+ /* Handle power state transition to shutdown */
+ if (target == TAS2764_PWR_CTRL_SHUTDOWN &&
+ (curr == TAS2764_PWR_CTRL_MUTE || curr == TAS2764_PWR_CTRL_ACTIVE)) {
+ ret = regmap_multi_reg_write(tas2764->regmap, tas2764_pre_shutdown_seq,
+ ARRAY_SIZE(tas2764_pre_shutdown_seq));
+ if (!ret)
+ ret = snd_soc_component_update_bits(tas2764->component,
+ TAS2764_PWR_CTRL,
+ TAS2764_PWR_CTRL_MASK,
+ TAS2764_PWR_CTRL_SHUTDOWN);
+ if (!ret)
+ ret = regmap_multi_reg_write(tas2764->regmap,
+ tas2764_post_shutdown_seq,
+ ARRAY_SIZE(tas2764_post_shutdown_seq));
+ }
+
+ ret = snd_soc_component_update_bits(tas2764->component, TAS2764_PWR_CTRL,
+ TAS2764_PWR_CTRL_MASK, target);
+
+ return ret;
+}
+
+/*
+ * Via devicetree (TODO):
+ * - switch from spread spectrum to class-D switching
+ * - disable edge control
+ * - set BOP settings (the BOP config bits *and* BOP_SRC)
+ */
+
+/*
+ * Other setup TODOs:
+ * - DVC ramp rate
+ */
+
+static const struct tas2764_quirk_init_sequence {
+ const struct reg_sequence *seq;
+ int len;
+} tas2764_quirk_init_sequences[] = {
+ { tas2764_noise_gate_dis_seq, ARRAY_SIZE(tas2764_noise_gate_dis_seq) },
+ { tas2764_dmod_rst_seq, ARRAY_SIZE(tas2764_dmod_rst_seq) },
+ { tas2764_conv_vbat_pvdd_mode_seq, ARRAY_SIZE(tas2764_conv_vbat_pvdd_mode_seq) },
+ { tas2764_unk_seq0, ARRAY_SIZE(tas2764_unk_seq0) },
+ { tas2764_unk_seq1, ARRAY_SIZE(tas2764_unk_seq1) },
+ { tas2764_unk_seq2, ARRAY_SIZE(tas2764_unk_seq2) },
+ { tas2764_thermal_th1_dis_seq, ARRAY_SIZE(tas2764_thermal_th1_dis_seq) },
+ { tas2764_shutdown_dance_init_seq, ARRAY_SIZE(tas2764_shutdown_dance_init_seq) },
+};
+
+#endif /* __TAS2764_QUIRKS__ */
diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
index f33ac89ffc598c39f3a7e0d620724098ca5bc3d3..d21ad23f59ee1b393a27014d403dab1d99836012 100644
--- a/sound/soc/codecs/tas2764.c
+++ b/sound/soc/codecs/tas2764.c
@@ -46,6 +46,8 @@ struct tas2764_priv {
bool unmuted;
};
+#include "tas2764-quirks.h"
+
static const char *tas2764_int_ltch0_msgs[8] = {
"fault: over temperature", /* INT_LTCH0 & BIT(0) */
"fault: over current",
@@ -123,6 +125,9 @@ static int tas2764_update_pwr_ctrl(struct tas2764_priv *tas2764)
else
val = TAS2764_PWR_CTRL_SHUTDOWN;
+ if (ENABLED_APPLE_QUIRKS & TAS2764_SHUTDOWN_DANCE)
+ return tas2764_do_quirky_pwr_ctrl_change(tas2764, val);
+
ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL,
TAS2764_PWR_CTRL_MASK, val);
if (ret < 0)
@@ -549,6 +554,30 @@ static uint8_t sn012776_bop_presets[] = {
static const struct regmap_config tas2764_i2c_regmap;
+static int tas2764_apply_init_quirks(struct tas2764_priv *tas2764)
+{
+ int ret, i;
+
+ for (i = 0; i < ARRAY_SIZE(tas2764_quirk_init_sequences); i++) {
+ const struct tas2764_quirk_init_sequence *init_seq =
+ &tas2764_quirk_init_sequences[i];
+
+ if (!init_seq->seq)
+ continue;
+
+ if (!(BIT(i) & ENABLED_APPLE_QUIRKS))
+ continue;
+
+ ret = regmap_multi_reg_write(tas2764->regmap, init_seq->seq,
+ init_seq->len);
+
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
static int tas2764_codec_probe(struct snd_soc_component *component)
{
struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
@@ -635,6 +664,13 @@ static int tas2764_codec_probe(struct snd_soc_component *component)
if (ret < 0)
return ret;
}
+
+ /* Apply all enabled Apple quirks */
+ ret = tas2764_apply_init_quirks(tas2764);
+
+ if (ret < 0)
+ return ret;
+
break;
default:
break;
@@ -719,6 +755,9 @@ static bool tas2764_volatile_register(struct device *dev, unsigned int reg)
case TAS2764_INT_LTCH0 ... TAS2764_INT_LTCH4:
case TAS2764_INT_CLK_CFG:
return true;
+ case TAS2764_REG(0xf0, 0x0) ... TAS2764_REG(0xff, 0x0):
+ /* TI's undocumented registers for the application of quirks */
+ return true;
default:
return false;
}
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v3 11/20] ASoC: tas2764: Raise regmap range maximum
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (9 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 10/20] ASoC: tas2764: Apply Apple quirks James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 12:07 ` [PATCH v3 12/20] ASoC: tas2770: expose die temp to hwmon James Calligeros
` (10 subsequent siblings)
21 siblings, 0 replies; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
From: Martin Povišer <povik+lin@cutebit.org>
TAS2764 has a number of undocumented registers between
page 0xf0 and 0xff. These are used to apply in-silicon
quirks and workarounds at runtime.
Raise the regmap max register to 0xffff to cover any
quirks registers.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
sound/soc/codecs/tas2764.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
index d21ad23f59ee1b393a27014d403dab1d99836012..0234a41deecd62e860c9d54a7a3206abc0bdac54 100644
--- a/sound/soc/codecs/tas2764.c
+++ b/sound/soc/codecs/tas2764.c
@@ -739,7 +739,7 @@ static const struct reg_default tas2764_reg_defaults[] = {
static const struct regmap_range_cfg tas2764_regmap_ranges[] = {
{
.range_min = 0,
- .range_max = 1 * 128,
+ .range_max = 0xffff,
.selector_reg = TAS2764_PAGE,
.selector_mask = 0xff,
.selector_shift = 0,
@@ -772,7 +772,7 @@ static const struct regmap_config tas2764_i2c_regmap = {
.cache_type = REGCACHE_RBTREE,
.ranges = tas2764_regmap_ranges,
.num_ranges = ARRAY_SIZE(tas2764_regmap_ranges),
- .max_register = 1 * 128,
+ .max_register = 0xffff,
};
static int tas2764_parse_dt(struct device *dev, struct tas2764_priv *tas2764)
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v3 12/20] ASoC: tas2770: expose die temp to hwmon
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (10 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 11/20] ASoC: tas2764: Raise regmap range maximum James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 12:45 ` Guenter Roeck
2025-02-27 12:07 ` [PATCH v3 13/20] ASoC: tas2764: " James Calligeros
` (9 subsequent siblings)
21 siblings, 1 reply; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
James Calligeros
TAS2770 includes an ADC which reports the chip's die temperature.
As per the datasheet, the temperature in degrees Celsius is derived
ny taking the raw value stored in the ADC's registers, dividing by 16,
then subtracting 93.
Create and register a hwmon device to expose the chip's die temperature
to the hwmon interface.
The ADC is shut down during software shutdown mode, and its registers
are initialised to 0 on reset. This means that the die temperature will
read -93 *C until the chip has been fully powered up at least once (e.g.
the PCM its attached to is opened). Once the chip is put into software
shutdown again, the ADC will also shut down. The last value sampled
before this happens will persist in the ADC's registers.
Co-developed-by: Martin Povišer <povik+lin@cutebit.org>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
sound/soc/codecs/tas2770.c | 102 +++++++++++++++++++++++++
1 file changed, 102 insertions(+)
diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c
index 7f219df8be7046912bf3ef452f75c17b5118bcf6..9cdd3470e9a04d5a5f801c3690d40f8fd131cd94 100644
--- a/sound/soc/codecs/tas2770.c
+++ b/sound/soc/codecs/tas2770.c
@@ -12,6 +12,7 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/hwmon.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/gpio/consumer.h>
@@ -491,6 +492,94 @@ static struct snd_soc_dai_driver tas2770_dai_driver[] = {
},
};
+static int tas2770_read_die_temp(struct tas2770_priv *tas2770, long *result)
+{
+ int ret, reading;
+
+ /*
+ * component could be uninitialised if the codec is not
+ * attached to a machine driver
+ */
+ if (!tas2770->component)
+ return -EINVAL;
+
+ ret = snd_soc_component_read(tas2770->component, TAS2770_TEMP_MSB);
+ if (ret < 0)
+ return ret;
+ reading = ret << 4;
+
+ ret = snd_soc_component_read(tas2770->component, TAS2770_TEMP_LSB);
+ if (ret < 0)
+ return ret;
+ reading |= ret >> 4;
+
+ /*
+ * As per datasheet: divide register by 16 and subtract 93 to get
+ * degrees Celsius. hwmon requires millidegrees. Let's avoid rounding
+ * errors by subtracting 93 * 16 then multiplying by 1000 / 16.
+ *
+ * NOTE: The ADC registers are initialised to 0 on reset. This means
+ * that the temperature will read -93 *C until the chip is brought out
+ * of software shutdown (e.g. the PCM it's attached to is opened). The
+ * ADC is also shut down in software shutdown/low-power mode, so the
+ * value read back from its registers will be the last value sampled
+ * before entering software shutdown.
+ */
+ *result = (reading - (93 * 16)) * (1000 / 16);
+ return 0;
+}
+
+static umode_t tas2770_hwmon_is_visible(const void *data,
+ enum hwmon_sensor_types type, u32 attr,
+ int channel)
+{
+ if (type != hwmon_temp)
+ return 0;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ return 0444;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int tas2770_hwmon_read(struct device *dev,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct tas2770_priv *tas2770 = dev_get_drvdata(dev);
+ int ret;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ ret = tas2770_read_die_temp(tas2770, val);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+static const struct hwmon_channel_info *const tas2770_hwmon_info[] = {
+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
+ NULL
+};
+
+static const struct hwmon_ops tas2770_hwmon_ops = {
+ .is_visible = tas2770_hwmon_is_visible,
+ .read = tas2770_hwmon_read,
+};
+
+static const struct hwmon_chip_info tas2770_hwmon_chip_info = {
+ .ops = &tas2770_hwmon_ops,
+ .info = tas2770_hwmon_info,
+};
+
static const struct regmap_config tas2770_i2c_regmap;
static int tas2770_codec_probe(struct snd_soc_component *component)
@@ -707,6 +796,19 @@ static int tas2770_i2c_probe(struct i2c_client *client)
}
}
+ if (IS_REACHABLE(CONFIG_HWMON)) {
+ struct device *hwmon;
+
+ hwmon = devm_hwmon_device_register_with_info(&client->dev, "tas2770",
+ tas2770,
+ &tas2770_hwmon_chip_info,
+ NULL);
+ if (IS_ERR(hwmon)) {
+ return dev_err_probe(&client->dev, PTR_ERR(hwmon),
+ "Failed to register temp sensor\n");
+ }
+ }
+
result = tas2770_register_codec(tas2770);
if (result)
dev_err(tas2770->dev, "Register codec failed.\n");
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: [PATCH v3 12/20] ASoC: tas2770: expose die temp to hwmon
2025-02-27 12:07 ` [PATCH v3 12/20] ASoC: tas2770: expose die temp to hwmon James Calligeros
@ 2025-02-27 12:45 ` Guenter Roeck
2025-02-27 14:04 ` Mark Brown
0 siblings, 1 reply; 40+ messages in thread
From: Guenter Roeck @ 2025-02-27 12:45 UTC (permalink / raw)
To: James Calligeros, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai, Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shi Fu,
Jean Delvare
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon
On 2/27/25 04:07, James Calligeros wrote:
> TAS2770 includes an ADC which reports the chip's die temperature.
> As per the datasheet, the temperature in degrees Celsius is derived
> ny taking the raw value stored in the ADC's registers, dividing by 16,
> then subtracting 93.
>
> Create and register a hwmon device to expose the chip's die temperature
> to the hwmon interface.
>
> The ADC is shut down during software shutdown mode, and its registers
> are initialised to 0 on reset. This means that the die temperature will
> read -93 *C until the chip has been fully powered up at least once (e.g.
> the PCM its attached to is opened). Once the chip is put into software
> shutdown again, the ADC will also shut down. The last value sampled
> before this happens will persist in the ADC's registers.
>
> Co-developed-by: Martin Povišer <povik+lin@cutebit.org>
> Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
> Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
> ---
> sound/soc/codecs/tas2770.c | 102 +++++++++++++++++++++++++
> 1 file changed, 102 insertions(+)
>
> diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c
> index 7f219df8be7046912bf3ef452f75c17b5118bcf6..9cdd3470e9a04d5a5f801c3690d40f8fd131cd94 100644
> --- a/sound/soc/codecs/tas2770.c
> +++ b/sound/soc/codecs/tas2770.c
> @@ -12,6 +12,7 @@
> #include <linux/err.h>
> #include <linux/init.h>
> #include <linux/delay.h>
> +#include <linux/hwmon.h>
> #include <linux/pm.h>
> #include <linux/i2c.h>
> #include <linux/gpio/consumer.h>
> @@ -491,6 +492,94 @@ static struct snd_soc_dai_driver tas2770_dai_driver[] = {
> },
> };
>
> +static int tas2770_read_die_temp(struct tas2770_priv *tas2770, long *result)
> +{
> + int ret, reading;
> +
> + /*
> + * component could be uninitialised if the codec is not
> + * attached to a machine driver
> + */
> + if (!tas2770->component)
> + return -EINVAL;
> +
If this is temporary, it should return -ENODATA or better only instantiate after
a component is attached. If it is permanent, the device should not instantiate
in the first place.
> + ret = snd_soc_component_read(tas2770->component, TAS2770_TEMP_MSB);
> + if (ret < 0)
> + return ret;
> + reading = ret << 4;
> +
> + ret = snd_soc_component_read(tas2770->component, TAS2770_TEMP_LSB);
> + if (ret < 0)
> + return ret;
> + reading |= ret >> 4;
> +
> + /*
> + * As per datasheet: divide register by 16 and subtract 93 to get
> + * degrees Celsius. hwmon requires millidegrees. Let's avoid rounding
> + * errors by subtracting 93 * 16 then multiplying by 1000 / 16.
> + *
> + * NOTE: The ADC registers are initialised to 0 on reset. This means
> + * that the temperature will read -93 *C until the chip is brought out
> + * of software shutdown (e.g. the PCM it's attached to is opened). The
> + * ADC is also shut down in software shutdown/low-power mode, so the
> + * value read back from its registers will be the last value sampled
> + * before entering software shutdown.
> + */
> + *result = (reading - (93 * 16)) * (1000 / 16);
> + return 0;
> +}
> +
> +static umode_t tas2770_hwmon_is_visible(const void *data,
> + enum hwmon_sensor_types type, u32 attr,
> + int channel)
> +{
> + if (type != hwmon_temp)
> + return 0;
> +
> + switch (attr) {
> + case hwmon_temp_input:
> + return 0444;
> + default:
> + break;
> + }
> +
> + return 0;
> +}
> +
> +static int tas2770_hwmon_read(struct device *dev,
> + enum hwmon_sensor_types type,
> + u32 attr, int channel, long *val)
> +{
> + struct tas2770_priv *tas2770 = dev_get_drvdata(dev);
> + int ret;
> +
> + switch (attr) {
> + case hwmon_temp_input:
> + ret = tas2770_read_die_temp(tas2770, val);
> + break;
> + default:
> + ret = -EOPNOTSUPP;
> + break;
> + }
> +
> + return ret;
> +}
> +
> +static const struct hwmon_channel_info *const tas2770_hwmon_info[] = {
> + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
> + NULL
> +};
> +
> +static const struct hwmon_ops tas2770_hwmon_ops = {
> + .is_visible = tas2770_hwmon_is_visible,
> + .read = tas2770_hwmon_read,
> +};
> +
> +static const struct hwmon_chip_info tas2770_hwmon_chip_info = {
> + .ops = &tas2770_hwmon_ops,
> + .info = tas2770_hwmon_info,
> +};
> +
> static const struct regmap_config tas2770_i2c_regmap;
>
> static int tas2770_codec_probe(struct snd_soc_component *component)
> @@ -707,6 +796,19 @@ static int tas2770_i2c_probe(struct i2c_client *client)
> }
> }
>
> + if (IS_REACHABLE(CONFIG_HWMON)) {
> + struct device *hwmon;
> +
> + hwmon = devm_hwmon_device_register_with_info(&client->dev, "tas2770",
> + tas2770,
> + &tas2770_hwmon_chip_info,
> + NULL);
> + if (IS_ERR(hwmon)) {
> + return dev_err_probe(&client->dev, PTR_ERR(hwmon),
> + "Failed to register temp sensor\n");
> + }
> + }
> +
> result = tas2770_register_codec(tas2770);
> if (result)
> dev_err(tas2770->dev, "Register codec failed.\n");
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3 12/20] ASoC: tas2770: expose die temp to hwmon
2025-02-27 12:45 ` Guenter Roeck
@ 2025-02-27 14:04 ` Mark Brown
0 siblings, 0 replies; 40+ messages in thread
From: Mark Brown @ 2025-02-27 14:04 UTC (permalink / raw)
To: Guenter Roeck
Cc: James Calligeros, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon
[-- Attachment #1: Type: text/plain, Size: 779 bytes --]
On Thu, Feb 27, 2025 at 04:45:35AM -0800, Guenter Roeck wrote:
> On 2/27/25 04:07, James Calligeros wrote:
> > +static int tas2770_read_die_temp(struct tas2770_priv *tas2770, long *result)
> > +{
> > + int ret, reading;
> > +
> > + /*
> > + * component could be uninitialised if the codec is not
> > + * attached to a machine driver
> > + */
> > + if (!tas2770->component)
> > + return -EINVAL;
> > +
> If this is temporary, it should return -ENODATA or better only instantiate after
> a component is attached. If it is permanent, the device should not instantiate
> in the first place.
I am wondering why this is using the ASoC component rather than just
the regmap, then there wouldn't be any issue here and the reads would
always work so long as the device was probed.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v3 13/20] ASoC: tas2764: expose die temp to hwmon
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (11 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 12/20] ASoC: tas2770: expose die temp to hwmon James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 12:07 ` [PATCH v3 14/20] ASoC: tas2764: Crop SDOUT zero-out mask based on BCLK ratio James Calligeros
` (8 subsequent siblings)
21 siblings, 0 replies; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
James Calligeros
TAS2764 contains an ADC that reports the chip's die temperature.
The temperature in degrees Celsius is yielded by subtracting 93
from the raw value reported by the ADC.
Expose the codec die temperature to the hwmon interface.
The chip will initialise the temperature register to 2.6 *C
to avoid triggering over temp protection. As the ADC is powered
down during software shutdown, this value will persist until the
chip is fully powered up (e.g. when the PCM it's attached to is
opened). When the chip is powered back down, the last value sampled
will persist in the register.
Co-developed-by: Martin Povišer <povik+lin@cutebit.org>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
sound/soc/codecs/tas2764.c | 96 +++++++++++++++++++++++++
sound/soc/codecs/tas2764.h | 3 +
2 files changed, 99 insertions(+)
diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
index 0234a41deecd62e860c9d54a7a3206abc0bdac54..b42bd5a50ee566ee83755d4ed7e2071b60951457 100644
--- a/sound/soc/codecs/tas2764.c
+++ b/sound/soc/codecs/tas2764.c
@@ -8,6 +8,7 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/hwmon.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/gpio/consumer.h>
@@ -578,6 +579,87 @@ static int tas2764_apply_init_quirks(struct tas2764_priv *tas2764)
return 0;
}
+static int tas2764_read_die_temp(struct tas2764_priv *tas2764, long *result)
+{
+ int ret;
+
+ /*
+ * component could be uninitialised if the codec is not
+ * attached to a machine driver
+ */
+ if (!tas2764->component)
+ return -EINVAL;
+
+ ret = snd_soc_component_read(tas2764->component, TAS2764_TEMP);
+ if (ret < 0)
+ return ret;
+ /*
+ * As per datasheet, subtract 93 from raw value to get degrees
+ * Celsius. hwmon wants millidegrees.
+ *
+ * NOTE: The chip will initialise the TAS2764_TEMP register to
+ * 2.6 *C to avoid triggering temperature protection. Since the
+ * ADC is powered down during software shutdown, this value will
+ * persist until the chip is fully powered up (e.g. the PCM it's
+ * attached to is opened). The ADC will power down again when
+ * the chip is put back into software shutdown, with the last
+ * value sampled persisting in the ADC's register.
+ */
+ *result = (ret - 93) * 1000;
+ return 0;
+}
+
+static umode_t tas2764_hwmon_is_visible(const void *data,
+ enum hwmon_sensor_types type, u32 attr,
+ int channel)
+{
+ if (type != hwmon_temp)
+ return 0;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ return 0444;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int tas2764_hwmon_read(struct device *dev,
+ enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct tas2764_priv *tas2764 = dev_get_drvdata(dev);
+ int ret;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ ret = tas2764_read_die_temp(tas2764, val);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+static const struct hwmon_channel_info *const tas2764_hwmon_info[] = {
+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
+ NULL
+};
+
+static const struct hwmon_ops tas2764_hwmon_ops = {
+ .is_visible = tas2764_hwmon_is_visible,
+ .read = tas2764_hwmon_read,
+};
+
+static const struct hwmon_chip_info tas2764_hwmon_chip_info = {
+ .ops = &tas2764_hwmon_ops,
+ .info = tas2764_hwmon_info,
+};
+
static int tas2764_codec_probe(struct snd_soc_component *component)
{
struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
@@ -848,6 +930,20 @@ static int tas2764_i2c_probe(struct i2c_client *client)
}
}
+ if (IS_REACHABLE(CONFIG_HWMON)) {
+ struct device *hwmon;
+
+ hwmon = devm_hwmon_device_register_with_info(&client->dev, "tas2764",
+ tas2764,
+ &tas2764_hwmon_chip_info,
+ NULL);
+ if (IS_ERR(hwmon)) {
+ return dev_err_probe(&client->dev, PTR_ERR(hwmon),
+ "Failed to register temp sensor\n");
+ }
+ }
+
+
return devm_snd_soc_register_component(tas2764->dev,
&soc_component_driver_tas2764,
tas2764_dai_driver,
diff --git a/sound/soc/codecs/tas2764.h b/sound/soc/codecs/tas2764.h
index 4cf0f7f112d6c3002203fa32e900efd640ef3f22..4a419c11d4b08eebb915762db00af5c06ff3dd42 100644
--- a/sound/soc/codecs/tas2764.h
+++ b/sound/soc/codecs/tas2764.h
@@ -117,6 +117,9 @@
#define TAS2764_INT_LTCH3 TAS2764_REG(0x0, 0x50)
#define TAS2764_INT_LTCH4 TAS2764_REG(0x0, 0x51)
+/* Readout Registers */
+#define TAS2764_TEMP TAS2764_REG(0x0, 0x56)
+
/* Clock/IRQ Settings */
#define TAS2764_INT_CLK_CFG TAS2764_REG(0x0, 0x5c)
#define TAS2764_INT_CLK_CFG_IRQZ_CLR BIT(2)
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v3 14/20] ASoC: tas2764: Crop SDOUT zero-out mask based on BCLK ratio
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (12 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 13/20] ASoC: tas2764: " James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 16:22 ` Mark Brown
2025-02-27 12:07 ` [PATCH v3 15/20] ASoC: tas2764: Enable main IRQs James Calligeros
` (7 subsequent siblings)
21 siblings, 1 reply; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
From: Martin Povišer <povik+lin@cutebit.org>
As per the datasheet, SDOUT bits must be zeroed out if the
corresponding TDM slot is invalid for a given clock ratio.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Martin Povišer <povik+lin@cutebit.org>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
sound/soc/codecs/tas2764.c | 39 +++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
index b42bd5a50ee566ee83755d4ed7e2071b60951457..2a787baaff5342e09cdfbf7939b0d635433f27ac 100644
--- a/sound/soc/codecs/tas2764.c
+++ b/sound/soc/codecs/tas2764.c
@@ -374,6 +374,44 @@ static int tas2764_hw_params(struct snd_pcm_substream *substream,
return tas2764_set_samplerate(tas2764, params_rate(params));
}
+static int tas2764_write_sdout_zero_mask(struct tas2764_priv *tas2764, int bclk_ratio)
+{
+ struct snd_soc_component *component = tas2764->component;
+ int nsense_slots = bclk_ratio / 8;
+ u32 cropped_mask;
+ int i, ret;
+
+ if (!tas2764->sdout_zero_mask)
+ return 0;
+
+ cropped_mask = tas2764->sdout_zero_mask & GENMASK(nsense_slots - 1, 0);
+
+ for (i = 0; i < 4; i++) {
+ ret = snd_soc_component_write(component, TAS2764_SDOUT_HIZ_1 + i,
+ (cropped_mask >> (i * 8)) & 0xff);
+
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = snd_soc_component_update_bits(component, TAS2764_SDOUT_HIZ_9,
+ TAS2764_SDOUT_HIZ_9_FORCE_0_EN,
+ TAS2764_SDOUT_HIZ_9_FORCE_0_EN);
+
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int tas2764_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
+{
+ struct snd_soc_component *component = dai->component;
+ struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component);
+
+ return tas2764_write_sdout_zero_mask(tas2764, ratio);
+}
+
static int tas2764_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct snd_soc_component *component = dai->component;
@@ -513,6 +551,7 @@ static int tas2764_set_dai_tdm_slot(struct snd_soc_dai *dai,
static const struct snd_soc_dai_ops tas2764_dai_ops = {
.mute_stream = tas2764_mute,
.hw_params = tas2764_hw_params,
+ .set_bclk_ratio = tas2764_set_bclk_ratio,
.set_fmt = tas2764_set_fmt,
.set_tdm_slot = tas2764_set_dai_tdm_slot,
.no_capture_mute = 1,
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: [PATCH v3 14/20] ASoC: tas2764: Crop SDOUT zero-out mask based on BCLK ratio
2025-02-27 12:07 ` [PATCH v3 14/20] ASoC: tas2764: Crop SDOUT zero-out mask based on BCLK ratio James Calligeros
@ 2025-02-27 16:22 ` Mark Brown
0 siblings, 0 replies; 40+ messages in thread
From: Mark Brown @ 2025-02-27 16:22 UTC (permalink / raw)
To: James Calligeros
Cc: Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Shenghao Ding,
Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Shi Fu, Jean Delvare, Guenter Roeck,
Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa
[-- Attachment #1: Type: text/plain, Size: 270 bytes --]
On Thu, Feb 27, 2025 at 10:07:41PM +1000, James Calligeros wrote:
> From: Martin Povišer <povik+lin@cutebit.org>
>
> As per the datasheet, SDOUT bits must be zeroed out if the
> corresponding TDM slot is invalid for a given clock ratio.
This seems like a fix?
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v3 15/20] ASoC: tas2764: Enable main IRQs
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (13 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 14/20] ASoC: tas2764: Crop SDOUT zero-out mask based on BCLK ratio James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 16:23 ` Mark Brown
2025-02-27 12:07 ` [PATCH v3 16/20] ASoC: tas2770: Power cycle amp on ISENSE/VSENSE change James Calligeros
` (6 subsequent siblings)
21 siblings, 1 reply; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
From: Hector Martin <marcan@marcan.st>
IRQ handling was added in commit dae191fb957f ("ASoC: tas2764: Add IRQ
handling") however that same commit masks all interrupts coming from
the chip. Unmask the "main" interrupts so that we can see and
deal with a number of errors including clock, voltage, and current.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
sound/soc/codecs/tas2764.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
index 2a787baaff5342e09cdfbf7939b0d635433f27ac..c122c07e2483b9ed1e6011dd949f97f8b2d0897f 100644
--- a/sound/soc/codecs/tas2764.c
+++ b/sound/soc/codecs/tas2764.c
@@ -715,7 +715,7 @@ static int tas2764_codec_probe(struct snd_soc_component *component)
regmap_reinit_cache(tas2764->regmap, &tas2764_i2c_regmap);
if (tas2764->irq) {
- ret = snd_soc_component_write(tas2764->component, TAS2764_INT_MASK0, 0xff);
+ ret = snd_soc_component_write(tas2764->component, TAS2764_INT_MASK0, 0x00);
if (ret < 0)
return ret;
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: [PATCH v3 15/20] ASoC: tas2764: Enable main IRQs
2025-02-27 12:07 ` [PATCH v3 15/20] ASoC: tas2764: Enable main IRQs James Calligeros
@ 2025-02-27 16:23 ` Mark Brown
2025-02-27 21:58 ` James Calligeros
0 siblings, 1 reply; 40+ messages in thread
From: Mark Brown @ 2025-02-27 16:23 UTC (permalink / raw)
To: James Calligeros
Cc: Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Shenghao Ding,
Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Shi Fu, Jean Delvare, Guenter Roeck,
Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa
[-- Attachment #1: Type: text/plain, Size: 428 bytes --]
On Thu, Feb 27, 2025 at 10:07:42PM +1000, James Calligeros wrote:
> From: Hector Martin <marcan@marcan.st>
>
> IRQ handling was added in commit dae191fb957f ("ASoC: tas2764: Add IRQ
> handling") however that same commit masks all interrupts coming from
> the chip. Unmask the "main" interrupts so that we can see and
> deal with a number of errors including clock, voltage, and current.
Shouldn't this also be a fix?
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3 15/20] ASoC: tas2764: Enable main IRQs
2025-02-27 16:23 ` Mark Brown
@ 2025-02-27 21:58 ` James Calligeros
2025-02-28 13:53 ` Mark Brown
0 siblings, 1 reply; 40+ messages in thread
From: James Calligeros @ 2025-02-27 21:58 UTC (permalink / raw)
To: Mark Brown
Cc: Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Shenghao Ding,
Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Shi Fu, Jean Delvare, Guenter Roeck,
Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa
On Fri, Feb 28, 2025 at 2:23 AM Mark Brown <broonie@kernel.org> wrote:
>
> On Thu, Feb 27, 2025 at 10:07:42PM +1000, James Calligeros wrote:
> > From: Hector Martin <marcan@marcan.st>
> >
> > IRQ handling was added in commit dae191fb957f ("ASoC: tas2764: Add IRQ
> > handling") however that same commit masks all interrupts coming from
> > the chip. Unmask the "main" interrupts so that we can see and
> > deal with a number of errors including clock, voltage, and current.
>
> Shouldn't this also be a fix?
I don't think so. The referenced commit only says that it adds an IRQ handler.
I don't think this commit is actually "fixing" anything - it's just
enabling previously
masked interrupts.
Happy to move things around if you disagree.
James
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3 15/20] ASoC: tas2764: Enable main IRQs
2025-02-27 21:58 ` James Calligeros
@ 2025-02-28 13:53 ` Mark Brown
0 siblings, 0 replies; 40+ messages in thread
From: Mark Brown @ 2025-02-28 13:53 UTC (permalink / raw)
To: James Calligeros
Cc: Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Shenghao Ding,
Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Shi Fu, Jean Delvare, Guenter Roeck,
Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa
[-- Attachment #1: Type: text/plain, Size: 872 bytes --]
On Fri, Feb 28, 2025 at 07:58:33AM +1000, James Calligeros wrote:
> On Fri, Feb 28, 2025 at 2:23 AM Mark Brown <broonie@kernel.org> wrote:
> > On Thu, Feb 27, 2025 at 10:07:42PM +1000, James Calligeros wrote:
> > > IRQ handling was added in commit dae191fb957f ("ASoC: tas2764: Add IRQ
> > > handling") however that same commit masks all interrupts coming from
> > > the chip. Unmask the "main" interrupts so that we can see and
> > > deal with a number of errors including clock, voltage, and current.
> > Shouldn't this also be a fix?
> I don't think so. The referenced commit only says that it adds an IRQ handler.
> I don't think this commit is actually "fixing" anything - it's just
> enabling previously
> masked interrupts.
I think the expectation would be that when the interrupt handler was
added it would've been possible for it to fire.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v3 16/20] ASoC: tas2770: Power cycle amp on ISENSE/VSENSE change
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (14 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 15/20] ASoC: tas2764: Enable main IRQs James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 12:07 ` [PATCH v3 17/20] ASoC: dt-bindings: tas2770: add flags for SDOUT pulldown and zero-fill James Calligeros
` (5 subsequent siblings)
21 siblings, 0 replies; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
From: Hector Martin <marcan@marcan.st>
The ISENSE/VSENSE blocks are only powered up when the amplifier
transitions from shutdown to active. This means that if those controls
are flipped on while the amplifier is already playing back audio, they
will have no effect.
Fix this by forcing a power cycle around transitions in those controls.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
sound/soc/codecs/tas2770.c | 30 +++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c
index 9cdd3470e9a04d5a5f801c3690d40f8fd131cd94..787356a4f4256627a55e35c851a9e78a1cf29771 100644
--- a/sound/soc/codecs/tas2770.c
+++ b/sound/soc/codecs/tas2770.c
@@ -157,11 +157,37 @@ static const struct snd_kcontrol_new isense_switch =
static const struct snd_kcontrol_new vsense_switch =
SOC_DAPM_SINGLE("Switch", TAS2770_PWR_CTRL, 2, 1, 1);
+static int sense_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+ struct tas2770_priv *tas2770 = snd_soc_component_get_drvdata(component);
+
+ /*
+ * Powering up ISENSE/VSENSE requires a trip through the shutdown state.
+ * Do that here to ensure that our changes are applied properly, otherwise
+ * we might end up with non-functional IVSENSE if playback started earlier,
+ * which would break software speaker protection.
+ */
+ switch (event) {
+ case SND_SOC_DAPM_PRE_REG:
+ return snd_soc_component_update_bits(component, TAS2770_PWR_CTRL,
+ TAS2770_PWR_CTRL_MASK,
+ TAS2770_PWR_CTRL_SHUTDOWN);
+ case SND_SOC_DAPM_POST_REG:
+ return tas2770_update_pwr_ctrl(tas2770);
+ default:
+ return 0;
+ }
+}
+
static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2770_asi1_mux),
- SND_SOC_DAPM_SWITCH("ISENSE", TAS2770_PWR_CTRL, 3, 1, &isense_switch),
- SND_SOC_DAPM_SWITCH("VSENSE", TAS2770_PWR_CTRL, 2, 1, &vsense_switch),
+ SND_SOC_DAPM_SWITCH_E("ISENSE", TAS2770_PWR_CTRL, 3, 1, &isense_switch,
+ sense_event, SND_SOC_DAPM_PRE_REG | SND_SOC_DAPM_POST_REG),
+ SND_SOC_DAPM_SWITCH_E("VSENSE", TAS2770_PWR_CTRL, 2, 1, &vsense_switch,
+ sense_event, SND_SOC_DAPM_PRE_REG | SND_SOC_DAPM_POST_REG),
SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2770_dac_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_OUTPUT("OUT"),
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v3 17/20] ASoC: dt-bindings: tas2770: add flags for SDOUT pulldown and zero-fill
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (15 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 16/20] ASoC: tas2770: Power cycle amp on ISENSE/VSENSE change James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-03-04 13:50 ` Rob Herring
2025-02-27 12:07 ` [PATCH v3 18/20] ASoC: tas2770: Add zero-fill and pull-down controls James Calligeros
` (4 subsequent siblings)
21 siblings, 1 reply; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
James Calligeros
TAS2770 can pull down and zero-fill SDOUT when not actively transmitting
TDM slot data. Zero-fill is useful when there are no other amps on the
bus. Pulldown is useful when the chip is attached to a shared bus.
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
.../bindings/sound/ti,tas2770.yaml | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/ti,tas2770.yaml b/Documentation/devicetree/bindings/sound/ti,tas2770.yaml
index 8eab98a0f7a25a9c87d2c56fd0635ff8ecee17d0..3eba9bb34a581526f68b6bf2e8437e1f1e03d26f 100644
--- a/Documentation/devicetree/bindings/sound/ti,tas2770.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tas2770.yaml
@@ -57,6 +57,18 @@ properties:
- 0 # Rising edge
- 1 # Falling edge
+ ti,sdout-pull-down:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ If present, SDOUT will be pulled low when not
+ transmitting.
+
+ ti,sdout-zero-fill:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ If present, SDOUT will be zero-filled when not
+ transmitting.
+
'#sound-dai-cells':
# The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward
# compatibility but is deprecated.
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: [PATCH v3 17/20] ASoC: dt-bindings: tas2770: add flags for SDOUT pulldown and zero-fill
2025-02-27 12:07 ` [PATCH v3 17/20] ASoC: dt-bindings: tas2770: add flags for SDOUT pulldown and zero-fill James Calligeros
@ 2025-03-04 13:50 ` Rob Herring
2025-03-05 1:19 ` James Calligeros
0 siblings, 1 reply; 40+ messages in thread
From: Rob Herring @ 2025-03-04 13:50 UTC (permalink / raw)
To: James Calligeros
Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck, Alyssa Rosenzweig, Martin Povišer,
Hector Martin, linux-sound, linux-kernel, devicetree, asahi,
linux-hwmon
On Thu, Feb 27, 2025 at 10:07:44PM +1000, James Calligeros wrote:
> TAS2770 can pull down and zero-fill SDOUT when not actively transmitting
> TDM slot data. Zero-fill is useful when there are no other amps on the
> bus. Pulldown is useful when the chip is attached to a shared bus.
>
> Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
> ---
> .../bindings/sound/ti,tas2770.yaml | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/sound/ti,tas2770.yaml b/Documentation/devicetree/bindings/sound/ti,tas2770.yaml
> index 8eab98a0f7a25a9c87d2c56fd0635ff8ecee17d0..3eba9bb34a581526f68b6bf2e8437e1f1e03d26f 100644
> --- a/Documentation/devicetree/bindings/sound/ti,tas2770.yaml
> +++ b/Documentation/devicetree/bindings/sound/ti,tas2770.yaml
> @@ -57,6 +57,18 @@ properties:
> - 0 # Rising edge
> - 1 # Falling edge
>
> + ti,sdout-pull-down:
> + $ref: /schemas/types.yaml#/definitions/flag
> + description:
> + If present, SDOUT will be pulled low when not
> + transmitting.
> +
> + ti,sdout-zero-fill:
> + $ref: /schemas/types.yaml#/definitions/flag
> + description:
> + If present, SDOUT will be zero-filled when not
> + transmitting.
Can't you align this with the other property you added? Or extend the
existing TDM properties we have.
Rob
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3 17/20] ASoC: dt-bindings: tas2770: add flags for SDOUT pulldown and zero-fill
2025-03-04 13:50 ` Rob Herring
@ 2025-03-05 1:19 ` James Calligeros
2025-03-05 13:22 ` Rob Herring
0 siblings, 1 reply; 40+ messages in thread
From: James Calligeros @ 2025-03-05 1:19 UTC (permalink / raw)
To: Rob Herring
Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck, Alyssa Rosenzweig, Martin Povišer,
Hector Martin, linux-sound, linux-kernel, devicetree, asahi,
linux-hwmon
On Tue, Mar 4, 2025 at 1:50 PM Rob Herring <robh@kernel.org> wrote:
> Can't you align this with the other property you added? Or extend the
> existing TDM properties we have.
I don't think either option makes sense given the functionality. This chip
behaves differently to TAS2764, and instead of using a bitmask to determine
which slots to ignore, we only get a single bit to tell the chip whether we want
it to fill or pull down *all* inactive slots. The property being a u32 mask
therefore does not make sense here.
Building the logic off the existing generic TDM slot properties would alter
behaviour of existing implementations where zero-fill and pulldown may not be
required or even wanted. This may continue to be the case going forward so I'd
rather make it an explicit opt-in rather than some unconditional thing we try to
turn on heuristically.
I gave some thought to flipping these bits if a TDM slot mask is passed to the
driver, however it can still be the case that we don't want both zero-fill *and*
pulldown active at the same time, or as above some implementations may want
neither, so we still need to be able to specify them individually.
Regards,
James
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3 17/20] ASoC: dt-bindings: tas2770: add flags for SDOUT pulldown and zero-fill
2025-03-05 1:19 ` James Calligeros
@ 2025-03-05 13:22 ` Rob Herring
2025-03-07 6:18 ` James Calligeros
0 siblings, 1 reply; 40+ messages in thread
From: Rob Herring @ 2025-03-05 13:22 UTC (permalink / raw)
To: James Calligeros
Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck, Alyssa Rosenzweig, Martin Povišer,
Hector Martin, linux-sound, linux-kernel, devicetree, asahi,
linux-hwmon
On Wed, Mar 05, 2025 at 01:19:15AM +0000, James Calligeros wrote:
> On Tue, Mar 4, 2025 at 1:50 PM Rob Herring <robh@kernel.org> wrote:
> > Can't you align this with the other property you added? Or extend the
> > existing TDM properties we have.
>
> I don't think either option makes sense given the functionality. This chip
> behaves differently to TAS2764, and instead of using a bitmask to determine
> which slots to ignore, we only get a single bit to tell the chip whether we want
> it to fill or pull down *all* inactive slots. The property being a u32 mask
> therefore does not make sense here.
If there's a single bit control, then that just means there's only 1
valid value for a mask in that case.
Or maybe a mask is overkill. What's the usecase for fill or pulldown
*some* inactive slots?
> Building the logic off the existing generic TDM slot properties would alter
> behaviour of existing implementations where zero-fill and pulldown may not be
> required or even wanted. This may continue to be the case going forward so I'd
> rather make it an explicit opt-in rather than some unconditional thing we try to
> turn on heuristically.
Existing implementations would not have the new/extra properties and
would continue to operate as before. Or those drivers could simply
ignore the properties.
> I gave some thought to flipping these bits if a TDM slot mask is passed to the
> driver, however it can still be the case that we don't want both zero-fill *and*
> pulldown active at the same time, or as above some implementations may want
> neither, so we still need to be able to specify them individually.
This just feels like something common because any TDM interface may need
to control this. It's not really a property of the chip, but requirement
of the TDM interface.
Rob
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3 17/20] ASoC: dt-bindings: tas2770: add flags for SDOUT pulldown and zero-fill
2025-03-05 13:22 ` Rob Herring
@ 2025-03-07 6:18 ` James Calligeros
2025-03-07 20:51 ` Rob Herring
0 siblings, 1 reply; 40+ messages in thread
From: James Calligeros @ 2025-03-07 6:18 UTC (permalink / raw)
To: Rob Herring
Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck, Alyssa Rosenzweig, Martin Povišer,
Hector Martin, linux-sound, linux-kernel, devicetree, asahi,
linux-hwmon
On Wed, Mar 5, 2025 at 11:22 PM Rob Herring <robh@kernel.org> wrote:
> This just feels like something common because any TDM interface may need
> to control this. It's not really a property of the chip, but requirement
> of the TDM interface.
What I'm imagining then is something like:
dai-link@0 {
cpu {
sound-dai = <&some_cpu>;
};
codec {
sound-dai = <&some_codec>;
dai-tdm-tx-zerofill;
dai-tdm-tx-pulldown; /* either or, having both makes no sense */
};
};
Codec drivers would then provide a function to set TDM TX behaviour if they
support it, and export that as a dai op for use by machine drivers
when they parse
the dai link similar to dai-tdm-tx-slot and friends. Is that close to
what you have
in mind?
Regards,
James
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3 17/20] ASoC: dt-bindings: tas2770: add flags for SDOUT pulldown and zero-fill
2025-03-07 6:18 ` James Calligeros
@ 2025-03-07 20:51 ` Rob Herring
2025-03-10 9:30 ` James Calligeros
0 siblings, 1 reply; 40+ messages in thread
From: Rob Herring @ 2025-03-07 20:51 UTC (permalink / raw)
To: James Calligeros
Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck, Alyssa Rosenzweig, Martin Povišer,
Hector Martin, linux-sound, linux-kernel, devicetree, asahi,
linux-hwmon
On Fri, Mar 07, 2025 at 04:18:31PM +1000, James Calligeros wrote:
> On Wed, Mar 5, 2025 at 11:22 PM Rob Herring <robh@kernel.org> wrote:
> > This just feels like something common because any TDM interface may need
> > to control this. It's not really a property of the chip, but requirement
> > of the TDM interface.
>
> What I'm imagining then is something like:
>
> dai-link@0 {
> cpu {
> sound-dai = <&some_cpu>;
> };
> codec {
> sound-dai = <&some_codec>;
> dai-tdm-tx-zerofill;
> dai-tdm-tx-pulldown; /* either or, having both makes no sense */
If they are mutually exclusive, it's best to design the properties that
way. So something like:
dai-tdm-tx-idle = "zerofill";
dai-tdm-tx-idle = "pulldown";
> };
> };
>
> Codec drivers would then provide a function to set TDM TX behaviour if they
> support it, and export that as a dai op for use by machine drivers
> when they parse
> the dai link similar to dai-tdm-tx-slot and friends. Is that close to
> what you have
> in mind?
How would it work when you need a mask? "dai-tdm-slot-tx-mask" is
enough?
Rob
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3 17/20] ASoC: dt-bindings: tas2770: add flags for SDOUT pulldown and zero-fill
2025-03-07 20:51 ` Rob Herring
@ 2025-03-10 9:30 ` James Calligeros
2025-03-12 12:58 ` Rob Herring
0 siblings, 1 reply; 40+ messages in thread
From: James Calligeros @ 2025-03-10 9:30 UTC (permalink / raw)
To: Rob Herring
Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck, Alyssa Rosenzweig, Martin Povišer,
Hector Martin, linux-sound, linux-kernel, devicetree, asahi,
linux-hwmon
On Sat, Mar 8, 2025 at 6:51 AM Rob Herring <robh@kernel.org> wrote:
> How would it work when you need a mask? "dai-tdm-slot-tx-mask" is
> enough?
The existing TX/RX slot masks are used to control which slots the codec
is operating on, AIUI. I don't know if it makes sense to alter how codecs
deal with this. Could we combine the suggested dai-tdm-slot-tx-idle
with an optional dai-tdm-slot-tx-idle-mask property? From the machine
driver's perspective, the API would then be similar to the existing
set_tdm_slot ops. The current downstream macaudio machine driver builds
its links by allowing multiple codecs and CPUs to be linked to a DAI,
like so:
dai-link@0 {
cpu {
sound-dai = <&cpu0>, <&cpu1>;
};
codec {
sound-dai = <&speaker0>,
...,
<&speaker6>;
};
};
In this case, the codec-specific mask property was added so that a mask
could be applied to a specific codec rather than the whole dai, however
from upstream drivers tt looks like the way this should be handled is to
have "dai-tdm-slot-tx-idle-mask-n" properties at the dai level, then have
the machine driver set the mask for the appropriate codec during setup. So
for macaudio, assuming speaker5 requires this zerofill mask, we would
have something like this:
dai-link@0 {
cpu {
sound-dai = <&cpu0>, <&cpu1>;
};
codec {
sound-dai = <&speaker0>,
...,
<&speaker6>;
};
/* equivalent to ti,sdout-force-zero-mask = <0xf0f0f0> */
dai-tdm-slot-tx-idle-mode-5 = "zerofill";
/* should this be an array like the slot masks? */
dai-tdm-slot-tx-idle-mask-5 = <0xf0f0f0>;
};
The machine driver then calls something like
snd_soc_dai_set_tdm_idle(speaker5_dai, SND_SOC_TDM_IDLE_MODE_ZEROFILL,
SND_SOC_TDM_IDLE_MODE_NONE, tx_idle_mask, 0);
and the codec driver deals with it however it needs to.
Regards,
James
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3 17/20] ASoC: dt-bindings: tas2770: add flags for SDOUT pulldown and zero-fill
2025-03-10 9:30 ` James Calligeros
@ 2025-03-12 12:58 ` Rob Herring
2025-03-13 0:49 ` James Calligeros
2025-03-14 13:23 ` Martin Povišer
0 siblings, 2 replies; 40+ messages in thread
From: Rob Herring @ 2025-03-12 12:58 UTC (permalink / raw)
To: James Calligeros
Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck, Alyssa Rosenzweig, Martin Povišer,
Hector Martin, linux-sound, linux-kernel, devicetree, asahi,
linux-hwmon
On Mon, Mar 10, 2025 at 07:30:07PM +1000, James Calligeros wrote:
> On Sat, Mar 8, 2025 at 6:51 AM Rob Herring <robh@kernel.org> wrote:
> > How would it work when you need a mask? "dai-tdm-slot-tx-mask" is
> > enough?
>
> The existing TX/RX slot masks are used to control which slots the codec
> is operating on, AIUI. I don't know if it makes sense to alter how codecs
> deal with this. Could we combine the suggested dai-tdm-slot-tx-idle
> with an optional dai-tdm-slot-tx-idle-mask property? From the machine
> driver's perspective, the API would then be similar to the existing
> set_tdm_slot ops. The current downstream macaudio machine driver builds
> its links by allowing multiple codecs and CPUs to be linked to a DAI,
> like so:
Wouldn't the NOT of dai-tdm-slot-tx-mask be the idle mask?
Don't think about the Linux APIs here. The DT is separate. So think in
terms of what you need to describe the TDM timing/waveform.
>
> dai-link@0 {
> cpu {
> sound-dai = <&cpu0>, <&cpu1>;
> };
> codec {
> sound-dai = <&speaker0>,
> ...,
> <&speaker6>;
> };
> };
>
> In this case, the codec-specific mask property was added so that a mask
> could be applied to a specific codec rather than the whole dai, however
> from upstream drivers tt looks like the way this should be handled is to
> have "dai-tdm-slot-tx-idle-mask-n" properties at the dai level, then have
> the machine driver set the mask for the appropriate codec during setup. So
> for macaudio, assuming speaker5 requires this zerofill mask, we would
> have something like this:
I'm now confused why you need n masks and what does n represent?
Rob
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3 17/20] ASoC: dt-bindings: tas2770: add flags for SDOUT pulldown and zero-fill
2025-03-12 12:58 ` Rob Herring
@ 2025-03-13 0:49 ` James Calligeros
2025-03-14 13:23 ` Martin Povišer
1 sibling, 0 replies; 40+ messages in thread
From: James Calligeros @ 2025-03-13 0:49 UTC (permalink / raw)
To: Rob Herring
Cc: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck, Alyssa Rosenzweig, Martin Povišer,
Hector Martin, linux-sound, linux-kernel, devicetree, asahi,
linux-hwmon
On Wed, Mar 12, 2025 at 10:58 PM Rob Herring <robh@kernel.org> wrote:
>
> On Mon, Mar 10, 2025 at 07:30:07PM +1000, James Calligeros wrote:
> > On Sat, Mar 8, 2025 at 6:51 AM Rob Herring <robh@kernel.org> wrote:
> > > How would it work when you need a mask? "dai-tdm-slot-tx-mask" is
> > > enough?
> >
> > The existing TX/RX slot masks are used to control which slots the codec
> > is operating on, AIUI. I don't know if it makes sense to alter how codecs
> > deal with this. Could we combine the suggested dai-tdm-slot-tx-idle
> > with an optional dai-tdm-slot-tx-idle-mask property? From the machine
> > driver's perspective, the API would then be similar to the existing
> > set_tdm_slot ops. The current downstream macaudio machine driver builds
> > its links by allowing multiple codecs and CPUs to be linked to a DAI,
> > like so:
>
> Wouldn't the NOT of dai-tdm-slot-tx-mask be the idle mask?
Theoretically it should be, and that's probably just what we should do.
We would then just have the dai-tdm-slot-tx-idle-mode property to worry
about. There may be a reason a unique property was added however, as only
some codecs have it set in our downstream DTs. Perhaps Martin can shed
some light on this?
> >
> > dai-link@0 {
> > cpu {
> > sound-dai = <&cpu0>, <&cpu1>;
> > };
> > codec {
> > sound-dai = <&speaker0>,
> > ...,
> > <&speaker6>;
> > };
> > };
> >
> > In this case, the codec-specific mask property was added so that a mask
> > could be applied to a specific codec rather than the whole dai, however
> > from upstream drivers tt looks like the way this should be handled is to
> > have "dai-tdm-slot-tx-idle-mask-n" properties at the dai level, then have
> > the machine driver set the mask for the appropriate codec during setup. So
> > for macaudio, assuming speaker5 requires this zerofill mask, we would
> > have something like this:
>
> I'm now confused why you need n masks and what does n represent?
We can have n cpus linked to m codecs in macaudio, and we need to specify
the TDM properties for each codec individually . There seem to be a couple
of ways upstream drivers deal with this, but the "nicest" way I've seen is
what amlogic[1] does, which is extend the dai-tdm-slot-* properties with
an index (-n) representing the specific codec it's for.
Regards,
James
[1] https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/sound/amlogic%2Caxg-sound-card.yaml
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v3 17/20] ASoC: dt-bindings: tas2770: add flags for SDOUT pulldown and zero-fill
2025-03-12 12:58 ` Rob Herring
2025-03-13 0:49 ` James Calligeros
@ 2025-03-14 13:23 ` Martin Povišer
1 sibling, 0 replies; 40+ messages in thread
From: Martin Povišer @ 2025-03-14 13:23 UTC (permalink / raw)
To: Rob Herring
Cc: James Calligeros, Liam Girdwood, Mark Brown, Jaroslav Kysela,
Takashi Iwai, Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck, Alyssa Rosenzweig, Hector Martin, linux-sound,
linux-kernel, devicetree, asahi, linux-hwmon
Hi Rob, James,
> On 12. 3. 2025, at 13:58, Rob Herring <robh@kernel.org> wrote:
>
> On Mon, Mar 10, 2025 at 07:30:07PM +1000, James Calligeros wrote:
>> On Sat, Mar 8, 2025 at 6:51 AM Rob Herring <robh@kernel.org> wrote:
>>> How would it work when you need a mask? "dai-tdm-slot-tx-mask" is
>>> enough?
>>
>> The existing TX/RX slot masks are used to control which slots the codec
>> is operating on, AIUI. I don't know if it makes sense to alter how codecs
>> deal with this. Could we combine the suggested dai-tdm-slot-tx-idle
>> with an optional dai-tdm-slot-tx-idle-mask property? From the machine
>> driver's perspective, the API would then be similar to the existing
>> set_tdm_slot ops. The current downstream macaudio machine driver builds
>> its links by allowing multiple codecs and CPUs to be linked to a DAI,
>> like so:
>
> Wouldn't the NOT of dai-tdm-slot-tx-mask be the idle mask?
>
> Don't think about the Linux APIs here. The DT is separate. So think in
> terms of what you need to describe the TDM timing/waveform.
>
>>
>> dai-link@0 {
>> cpu {
>> sound-dai = <&cpu0>, <&cpu1>;
>> };
>> codec {
>> sound-dai = <&speaker0>,
>> ...,
>> <&speaker6>;
>> };
>> };
>>
>> In this case, the codec-specific mask property was added so that a mask
>> could be applied to a specific codec rather than the whole dai, however
>> from upstream drivers tt looks like the way this should be handled is to
>> have "dai-tdm-slot-tx-idle-mask-n" properties at the dai level, then have
>> the machine driver set the mask for the appropriate codec during setup. So
>> for macaudio, assuming speaker5 requires this zerofill mask, we would
>> have something like this:
>
> I'm now confused why you need n masks and what does n represent?
For this setup there are 6 codecs on the same bus but 3 of those are on one
data line and the other 3 are on another data line. Within the SoC these two
data lines (both for codec->SoC direction) are ORed together in front of the
receiver peripheral.
This means we need at least one codec within each group of the three to zero
out the bus for the duration of the slots used by the other group of three.
I solved this by attaching
ti,sdout-force-zero-mask = <0xf0f0f0>;
on one codec from the first group, and
ti,sdout-force-zero-mask = <0x0f0f0f>;
on one from the other group.
FWIW the right form of these masks is not an implementation detail of the
machine driver spilling into the device tree (so that the mask would need
to be different if the machine driver was implemented differently). This is
because the slots used by each codec are specified via a DT property too, e.g.
ti,imon-slot-no = <8>;
ti,vmon-slot-no = <10>;
Martin
> Rob
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v3 18/20] ASoC: tas2770: Add zero-fill and pull-down controls
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (16 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 17/20] ASoC: dt-bindings: tas2770: add flags for SDOUT pulldown and zero-fill James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 12:07 ` [PATCH v3 19/20] ASoC: tas2770: Support setting the PDM TX slot James Calligeros
` (3 subsequent siblings)
21 siblings, 0 replies; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
From: Hector Martin <marcan@marcan.st>
Expose the bits that control the behavior of the SDOUT pin when not
actively transmitting slot data. Zero-fill is useful when there is a
single amp on the SDOUT bus (e.g. Apple machines with mono speakers or a
single stereo pair, where L/R are on separate buses).
Pull-down is useful, though not perfect, when multiple amps share a
bus. It typically takes around 2 bits for the line to transition from
high to low after going Hi-Z, with the pull-down.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
sound/soc/codecs/tas2770.c | 17 +++++++++++++++++
sound/soc/codecs/tas2770.h | 13 +++++++++++++
2 files changed, 30 insertions(+)
diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c
index 787356a4f4256627a55e35c851a9e78a1cf29771..252c65ae839a28fdaf7aaa39faf49891905741a0 100644
--- a/sound/soc/codecs/tas2770.c
+++ b/sound/soc/codecs/tas2770.c
@@ -632,6 +632,20 @@ static int tas2770_codec_probe(struct snd_soc_component *component)
return ret;
}
+ ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG4,
+ TAS2770_TDM_CFG_REG4_TX_FILL,
+ tas2770->sdout_zfill ? 0 :
+ TAS2770_TDM_CFG_REG4_TX_FILL);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_component_update_bits(component, TAS2770_DIN_PD,
+ TAS2770_DIN_PD_SDOUT,
+ tas2770->sdout_pd ?
+ TAS2770_DIN_PD_SDOUT : 0);
+ if (ret < 0)
+ return ret;
+
return 0;
}
@@ -771,6 +785,9 @@ static int tas2770_parse_dt(struct device *dev, struct tas2770_priv *tas2770)
tas2770->v_sense_slot = -1;
}
+ tas2770->sdout_pd = fwnode_property_read_bool(dev->fwnode, "ti,sdout-pull-down");
+ tas2770->sdout_zfill = fwnode_property_read_bool(dev->fwnode, "ti,sdout-zero-fill");
+
tas2770->sdz_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);
if (IS_ERR(tas2770->sdz_gpio)) {
if (PTR_ERR(tas2770->sdz_gpio) == -EPROBE_DEFER)
diff --git a/sound/soc/codecs/tas2770.h b/sound/soc/codecs/tas2770.h
index f75f40781ab136cccbe1c272f7129ddd3e4a22a3..7da60d2746e8b03faa9d17319c4c41cad7f8cdbd 100644
--- a/sound/soc/codecs/tas2770.h
+++ b/sound/soc/codecs/tas2770.h
@@ -67,6 +67,14 @@
#define TAS2770_TDM_CFG_REG3_RXS_SHIFT 0x4
#define TAS2770_TDM_CFG_REG3_30_MASK GENMASK(3, 0)
#define TAS2770_TDM_CFG_REG3_30_SHIFT 0
+ /* TDM Configuration Reg4 */
+#define TAS2770_TDM_CFG_REG4 TAS2770_REG(0X0, 0x0E)
+#define TAS2770_TDM_CFG_REG4_TX_LSB_CFG BIT(7)
+#define TAS2770_TDM_CFG_REG4_TX_KEEPER_CFG BIT(6)
+#define TAS2770_TDM_CFG_REG4_TX_KEEPER BIT(5)
+#define TAS2770_TDM_CFG_REG4_TX_FILL BIT(4)
+#define TAS2770_TDM_CFG_REG4_TX_OFFSET_MASK GENMASK(3, 1)
+#define TAS2770_TDM_CFG_REG4_TX_EDGE_FALLING BIT(0)
/* TDM Configuration Reg5 */
#define TAS2770_TDM_CFG_REG5 TAS2770_REG(0X0, 0x0F)
#define TAS2770_TDM_CFG_REG5_VSNS_MASK BIT(6)
@@ -110,6 +118,9 @@
#define TAS2770_TEMP_LSB TAS2770_REG(0X0, 0x2A)
/* Interrupt Configuration */
#define TAS2770_INT_CFG TAS2770_REG(0X0, 0x30)
+ /* Data In Pull-Down */
+#define TAS2770_DIN_PD TAS2770_REG(0X0, 0x31)
+#define TAS2770_DIN_PD_SDOUT BIT(7)
/* Misc IRQ */
#define TAS2770_MISC_IRQ TAS2770_REG(0X0, 0x32)
/* Clock Configuration */
@@ -138,6 +149,8 @@ struct tas2770_priv {
struct device *dev;
int v_sense_slot;
int i_sense_slot;
+ bool sdout_pd;
+ bool sdout_zfill;
bool dac_powered;
bool unmuted;
};
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v3 19/20] ASoC: tas2770: Support setting the PDM TX slot
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (17 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 18/20] ASoC: tas2770: Add zero-fill and pull-down controls James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-02-27 12:07 ` [PATCH v3 20/20] ASoC: tas2770: Set the SDOUT polarity correctly James Calligeros
` (2 subsequent siblings)
21 siblings, 0 replies; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
From: Hector Martin <marcan@marcan.st>
We don't actually support configuring the PDM input right now. Rather,
this is useful as a hack.
On Apple Silicon machines, amps are split between two I2S buses which
are logically ANDed internally at the SoC. Odd and even slot groups are
driven by amps on either bus respectively. Since the signals are ANDed,
unused slot groups must be driven as zero to avoid corrupting the data
from the other side.
On most recent machines (TAS2764-based), this is accomplished using the
"SDOUT zero mask" feature of that chip. Unfortunately, TAS2770 does not
support this. It does support zeroing out *all* unused slots, which
works well for machines with a single amp per I2S bus. That is all,
except one.
The 13" M1 MacBook Pro is the only machine using TAS2770 and two amps
per I2S bus:
L Bus: SPK0I SPK0V Hi-Z Hi-Z SPK2I SPK2V Hi-Z Hi-Z
R Bus: Hi-Z Hi-Z SPK1I SPK2V Hi-Z Hi-Z SPK3I SPK3V
To ensure uncorrupted data, we need to force all the Hi-Z periods to
zero. We cannot use the "force all zero" feature, as that would cause a
bus conflict between both amps. We can use the pull-down feature, but
that leaves a few bits of garbage on the trailing edge of the speaker
data, since the pull-down is weak.
This is where the PDM transmit feature comes in. With PDM grounded and
disabled (the default state), the PDM slot is transmitted as all zeroes.
We can use that to force a zero 16-bit slot after the voltage data for
each speaker, cleaning it up. Then the pull-down ensures the line stays
low for the subsequent slot:
L Bus: SPK0I SPK0V PDM0 PulDn SPK2I SPK2V PDM0 PulDn
R Bus: PDM0 PulDn SPK1I SPK2V PDM0 PulDn SPK3I SPK3V
Yes, this is a horrible hack, but it beats adding dummy slots that would
be visible to the userspace capture side. There may be some other way to
fix the logical AND behavior on the MCA side... that would make this
unnecessary.
("How does Apple deal with this"? - they don't, macOS does not use
IVSENSE on TAS2770 machines even though it's physically wired up,
but we want to do so on Linux.)
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
sound/soc/codecs/tas2770.c | 25 +++++++++++++++++++++++++
sound/soc/codecs/tas2770.h | 6 ++++++
2 files changed, 31 insertions(+)
diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c
index 252c65ae839a28fdaf7aaa39faf49891905741a0..58f36cf471a6b7dd15c1b0600710396de4e2f61e 100644
--- a/sound/soc/codecs/tas2770.c
+++ b/sound/soc/codecs/tas2770.c
@@ -241,6 +241,19 @@ static int tas2770_set_ivsense_transmit(struct tas2770_priv *tas2770,
return 0;
}
+static int tas2770_set_pdm_transmit(struct tas2770_priv *tas2770, int slot)
+{
+ struct snd_soc_component *component = tas2770->component;
+ int ret;
+
+ ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG7,
+ TAS2770_TDM_CFG_REG7_PDM_MASK |
+ TAS2770_TDM_CFG_REG7_50_MASK,
+ TAS2770_TDM_CFG_REG7_PDM_ENABLE |
+ slot);
+ return ret;
+}
+
static int tas2770_set_bitwidth(struct tas2770_priv *tas2770, int bitwidth)
{
int ret;
@@ -632,6 +645,13 @@ static int tas2770_codec_probe(struct snd_soc_component *component)
return ret;
}
+ if (tas2770->pdm_slot != -1) {
+ ret = tas2770_set_pdm_transmit(tas2770, tas2770->pdm_slot);
+
+ if (ret < 0)
+ return ret;
+ }
+
ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG4,
TAS2770_TDM_CFG_REG4_TX_FILL,
tas2770->sdout_zfill ? 0 :
@@ -785,6 +805,11 @@ static int tas2770_parse_dt(struct device *dev, struct tas2770_priv *tas2770)
tas2770->v_sense_slot = -1;
}
+ rc = fwnode_property_read_u32(dev->fwnode, "ti,pdm-slot-no",
+ &tas2770->pdm_slot);
+ if (rc)
+ tas2770->pdm_slot = -1;
+
tas2770->sdout_pd = fwnode_property_read_bool(dev->fwnode, "ti,sdout-pull-down");
tas2770->sdout_zfill = fwnode_property_read_bool(dev->fwnode, "ti,sdout-zero-fill");
diff --git a/sound/soc/codecs/tas2770.h b/sound/soc/codecs/tas2770.h
index 7da60d2746e8b03faa9d17319c4c41cad7f8cdbd..8a208cee8712cb28422dd10cc5d80c460666728a 100644
--- a/sound/soc/codecs/tas2770.h
+++ b/sound/soc/codecs/tas2770.h
@@ -85,6 +85,11 @@
#define TAS2770_TDM_CFG_REG6_ISNS_MASK BIT(6)
#define TAS2770_TDM_CFG_REG6_ISNS_ENABLE BIT(6)
#define TAS2770_TDM_CFG_REG6_50_MASK GENMASK(5, 0)
+ /* TDM Configuration Reg10 */
+#define TAS2770_TDM_CFG_REG7 TAS2770_REG(0X0, 0x11)
+#define TAS2770_TDM_CFG_REG7_PDM_MASK BIT(6)
+#define TAS2770_TDM_CFG_REG7_PDM_ENABLE BIT(6)
+#define TAS2770_TDM_CFG_REG7_50_MASK GENMASK(5, 0)
/* Brown Out Prevention Reg0 */
#define TAS2770_BO_PRV_REG0 TAS2770_REG(0X0, 0x1B)
/* Interrupt MASK Reg0 */
@@ -149,6 +154,7 @@ struct tas2770_priv {
struct device *dev;
int v_sense_slot;
int i_sense_slot;
+ int pdm_slot;
bool sdout_pd;
bool sdout_zfill;
bool dac_powered;
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* [PATCH v3 20/20] ASoC: tas2770: Set the SDOUT polarity correctly
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (18 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 19/20] ASoC: tas2770: Support setting the PDM TX slot James Calligeros
@ 2025-02-27 12:07 ` James Calligeros
2025-03-14 15:52 ` (subset) [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants Mark Brown
2025-04-14 13:56 ` Mark Brown
21 siblings, 0 replies; 40+ messages in thread
From: James Calligeros @ 2025-02-27 12:07 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Shenghao Ding, Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Shi Fu, Jean Delvare,
Guenter Roeck
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa, James Calligeros
From: Hector Martin <marcan@marcan.st>
TX launch polarity needs to be the opposite of RX capture polarity, to
generate the right bit slot alignment.
Reviewed-by: Neal Gompa <neal@gompa.dev>
Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: James Calligeros <jcalligeros99@gmail.com>
---
sound/soc/codecs/tas2770.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c
index 58f36cf471a6b7dd15c1b0600710396de4e2f61e..b68ae6236d69b43cfb1cf28cabf73b1f729191ab 100644
--- a/sound/soc/codecs/tas2770.c
+++ b/sound/soc/codecs/tas2770.c
@@ -352,7 +352,7 @@ static int tas2770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
struct snd_soc_component *component = dai->component;
struct tas2770_priv *tas2770 =
snd_soc_component_get_drvdata(component);
- u8 tdm_rx_start_slot = 0, invert_fpol = 0, fpol_preinv = 0, asi_cfg_1 = 0;
+ u8 tdm_rx_start_slot = 0, invert_fpol = 0, fpol_preinv = 0, asi_cfg_1 = 0, asi_cfg_4 = 0;
int ret;
switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
@@ -369,6 +369,7 @@ static int tas2770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
fallthrough;
case SND_SOC_DAIFMT_NB_NF:
asi_cfg_1 |= TAS2770_TDM_CFG_REG1_RX_RSING;
+ asi_cfg_4 |= TAS2770_TDM_CFG_REG4_TX_EDGE_FALLING;
break;
case SND_SOC_DAIFMT_IB_IF:
invert_fpol = 1;
@@ -387,6 +388,12 @@ static int tas2770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
if (ret < 0)
return ret;
+ ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG4,
+ TAS2770_TDM_CFG_REG4_TX_EDGE_FALLING,
+ asi_cfg_4);
+ if (ret < 0)
+ return ret;
+
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
tdm_rx_start_slot = 1;
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread
* Re: (subset) [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (19 preceding siblings ...)
2025-02-27 12:07 ` [PATCH v3 20/20] ASoC: tas2770: Set the SDOUT polarity correctly James Calligeros
@ 2025-03-14 15:52 ` Mark Brown
2025-04-14 13:56 ` Mark Brown
21 siblings, 0 replies; 40+ messages in thread
From: Mark Brown @ 2025-03-14 15:52 UTC (permalink / raw)
To: Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Shenghao Ding,
Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Shi Fu, Jean Delvare, Guenter Roeck,
James Calligeros
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa
On Thu, 27 Feb 2025 22:07:27 +1000, James Calligeros wrote:
> This series introduces a number of changes to the drivers for
> the Texas Instruments TAS2764 and TAS2770 amplifiers in order to
> introduce (and improve in the case of TAS2770) support for the
> variants of these amps found in Apple Silicon Macs.
>
> Apple's variant of TAS2764 is known as SN012776, and as always with
> Apple is a subtly incompatible variant with a number of quirks. It
> is not publicly available. The TAS2770 variant is known as TAS5770L,
> and does not require incompatible handling.
>
> [...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[01/20] ASoC: dt-bindings: tas27xx: add compatible for SN012776
commit: 25a83f870b8a25a4b10bf5ba474a017ed5a72e7d
[02/20] ASoC: dt-bindings: tas2770: add compatible for TAS5770L
commit: ce9233937f3233e277ff23395e61ea690c769bef
[03/20] ASoC: tas2764: Extend driver to SN012776
commit: ad18392962df46a858432839cc6bcaf2ede7cc86
[04/20] ASoC: tas2764: Add control concerning overcurrent events
commit: f8d5f28e3f2ece5a1392205022afe30c87107a9b
[05/20] ASoC: tas2770: Factor out set_ivsense_slots
commit: 6553ee024b4452ef861de10605156c9d79e208ab
[06/20] ASoC: tas2770: Fix and redo I/V sense TDM slot setting logic
commit: f0066c8d1d3298e9f9d136a365139bac733e84c5
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: (subset) [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants
2025-02-27 12:07 [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants James Calligeros
` (20 preceding siblings ...)
2025-03-14 15:52 ` (subset) [PATCH v3 00/20] ASoC: tas27{64,70}: improve support for Apple codec variants Mark Brown
@ 2025-04-14 13:56 ` Mark Brown
21 siblings, 0 replies; 40+ messages in thread
From: Mark Brown @ 2025-04-14 13:56 UTC (permalink / raw)
To: Liam Girdwood, Jaroslav Kysela, Takashi Iwai, Shenghao Ding,
Kevin Lu, Baojun Xu, Dan Murphy, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Shi Fu, Jean Delvare, Guenter Roeck,
James Calligeros
Cc: Alyssa Rosenzweig, Martin Povišer, Hector Martin,
linux-sound, linux-kernel, devicetree, asahi, linux-hwmon,
Neal Gompa
On Thu, 27 Feb 2025 22:07:27 +1000, James Calligeros wrote:
> This series introduces a number of changes to the drivers for
> the Texas Instruments TAS2764 and TAS2770 amplifiers in order to
> introduce (and improve in the case of TAS2770) support for the
> variants of these amps found in Apple Silicon Macs.
>
> Apple's variant of TAS2764 is known as SN012776, and as always with
> Apple is a subtly incompatible variant with a number of quirks. It
> is not publicly available. The TAS2770 variant is known as TAS5770L,
> and does not require incompatible handling.
>
> [...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[07/20] ASoC: tas2764: Reinit cache on part reset
commit: 592ab3936b096da5deb64d4c906edbeb989174d6
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
^ permalink raw reply [flat|nested] 40+ messages in thread